mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9.git
synced 2026-09-09 00:08:12 +08:00
Merge: Wireless core and drivers rebase to v7.1
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8320 JIRA: https://issues.redhat.com/browse/RHEL-186475 Tested: basic testing with several supported WiFi cards (Intel, Qualcomm, Mediatek and Realtek). Wireless core and drivers update to v7.1 Upstream status: linux.git Depends: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8309 Depends: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8206 Depends: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8130 Not supported drivers: Omitted-fix: c882b7a603ef wifi: at76c50x: drop redundant device reference Omitted-fix: ea06baf59bd4 wifi: ipw2x00: Rename michael_mic() to libipw_michael_mic() Omitted-fix: 32a0e1c63cdf wifi: ipw2x00: Use michael_mic() from cfg80211 Omitted-fix: 75e375816392 wifi: libertas: drop redundant device reference Omitted-fix: b1af0de313bd wifi: libertas_tf: drop redundant device reference Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com> Approved-by: Jarod Wilson <jarod@redhat.com> Approved-by: Kamal Heib <kheib@redhat.com> Approved-by: Ivan Vecera <ivecera@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
This commit is contained in:
@@ -172,6 +172,12 @@ properties:
|
||||
Quirk specifying that the firmware expects the 8bit version
|
||||
of the host capability QMI request
|
||||
|
||||
qcom,snoc-host-cap-skip-quirk:
|
||||
type: boolean
|
||||
description:
|
||||
Quirk specifying that the firmware wants to skip the host
|
||||
capability QMI request
|
||||
|
||||
qcom,xo-cal-data:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
@@ -293,6 +299,11 @@ allOf:
|
||||
required:
|
||||
- interrupts
|
||||
|
||||
- not:
|
||||
required:
|
||||
- qcom,snoc-host-cap-8bit-quirk
|
||||
- qcom,snoc-host-cap-skip-quirk
|
||||
|
||||
examples:
|
||||
# SNoC
|
||||
- |
|
||||
|
||||
@@ -808,6 +808,7 @@ out:
|
||||
static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
|
||||
{
|
||||
struct ath10k *ar = qmi->ar;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
int ret;
|
||||
|
||||
ret = ath10k_qmi_ind_register_send_sync_msg(qmi);
|
||||
@@ -819,9 +820,15 @@ static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = ath10k_qmi_host_cap_send_sync(qmi);
|
||||
if (ret)
|
||||
return;
|
||||
/*
|
||||
* Skip the host capability request for the firmware versions which
|
||||
* do not support this feature.
|
||||
*/
|
||||
if (!test_bit(ATH10K_SNOC_FLAG_SKIP_HOST_CAP_QUIRK, &ar_snoc->flags)) {
|
||||
ret = ath10k_qmi_host_cap_send_sync(qmi);
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = ath10k_qmi_msa_mem_info_send_sync_msg(qmi);
|
||||
if (ret)
|
||||
|
||||
@@ -1362,6 +1362,9 @@ static void ath10k_snoc_quirks_init(struct ath10k *ar)
|
||||
|
||||
if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))
|
||||
set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);
|
||||
|
||||
if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-skip-quirk"))
|
||||
set_bit(ATH10K_SNOC_FLAG_SKIP_HOST_CAP_QUIRK, &ar_snoc->flags);
|
||||
}
|
||||
|
||||
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
|
||||
|
||||
@@ -51,6 +51,7 @@ enum ath10k_snoc_flags {
|
||||
ATH10K_SNOC_FLAG_MODEM_STOPPED,
|
||||
ATH10K_SNOC_FLAG_RECOVERY,
|
||||
ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
|
||||
ATH10K_SNOC_FLAG_SKIP_HOST_CAP_QUIRK,
|
||||
};
|
||||
|
||||
struct clk_bulk_data;
|
||||
|
||||
@@ -1016,7 +1016,6 @@ static int ath10k_usb_probe(struct usb_interface *interface,
|
||||
|
||||
netif_napi_add(ar->napi_dev, &ar->napi, ath10k_usb_napi_poll);
|
||||
|
||||
usb_get_dev(dev);
|
||||
vendor_id = le16_to_cpu(dev->descriptor.idVendor);
|
||||
product_id = le16_to_cpu(dev->descriptor.idProduct);
|
||||
|
||||
@@ -1055,12 +1054,10 @@ err_usb_destroy:
|
||||
err:
|
||||
ath10k_core_destroy(ar);
|
||||
|
||||
usb_put_dev(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath10k_usb_remove(struct usb_interface *interface)
|
||||
static void ath10k_usb_disconnect(struct usb_interface *interface)
|
||||
{
|
||||
struct ath10k_usb *ar_usb;
|
||||
|
||||
@@ -1071,7 +1068,6 @@ static void ath10k_usb_remove(struct usb_interface *interface)
|
||||
ath10k_core_unregister(ar_usb->ar);
|
||||
netif_napi_del(&ar_usb->ar->napi);
|
||||
ath10k_usb_destroy(ar_usb->ar);
|
||||
usb_put_dev(interface_to_usbdev(interface));
|
||||
ath10k_core_destroy(ar_usb->ar);
|
||||
}
|
||||
|
||||
@@ -1117,7 +1113,7 @@ static struct usb_driver ath10k_usb_driver = {
|
||||
.probe = ath10k_usb_probe,
|
||||
.suspend = ath10k_usb_pm_suspend,
|
||||
.resume = ath10k_usb_pm_resume,
|
||||
.disconnect = ath10k_usb_remove,
|
||||
.disconnect = ath10k_usb_disconnect,
|
||||
.id_table = ath10k_usb_ids,
|
||||
.supports_autosuspend = true,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
@@ -1947,15 +1946,15 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
|
||||
ret = -ESHUTDOWN;
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"drop wmi command %d, hardware is wedged\n", cmd_id);
|
||||
} else {
|
||||
/* try to send pending beacons first. they take priority */
|
||||
ath10k_wmi_tx_beacons_nowait(ar);
|
||||
|
||||
ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
|
||||
|
||||
if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
|
||||
ret = -ESHUTDOWN;
|
||||
}
|
||||
/* try to send pending beacons first. they take priority */
|
||||
ath10k_wmi_tx_beacons_nowait(ar);
|
||||
|
||||
ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
|
||||
|
||||
if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
|
||||
ret = -ESHUTDOWN;
|
||||
|
||||
(ret != -EAGAIN);
|
||||
}), 3 * HZ);
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
config ATH11K
|
||||
tristate "Qualcomm Technologies 802.11ax chipset support"
|
||||
depends on MAC80211 && HAS_DMA
|
||||
select CRYPTO_MICHAEL_MIC
|
||||
select ATH_COMMON
|
||||
select QCOM_QMI_HELPERS
|
||||
help
|
||||
|
||||
@@ -807,10 +807,8 @@ static int ath11k_core_get_rproc(struct ath11k_base *ab)
|
||||
}
|
||||
|
||||
prproc = rproc_get_by_phandle(rproc_phandle);
|
||||
if (!prproc) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_AHB, "failed to get rproc, deferring\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
if (!prproc)
|
||||
return dev_err_probe(&ab->pdev->dev, -EPROBE_DEFER, "failed to get rproc\n");
|
||||
ab_ahb->tgt_rproc = prproc;
|
||||
|
||||
return 0;
|
||||
@@ -1201,10 +1199,8 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
|
||||
ath11k_ahb_init_qmi_ce_config(ab);
|
||||
|
||||
ret = ath11k_core_get_rproc(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to get rproc: %d\n", ret);
|
||||
if (ret)
|
||||
goto err_ce_free;
|
||||
}
|
||||
|
||||
ret = ath11k_core_init(ab);
|
||||
if (ret) {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#include <crypto/hash.h>
|
||||
#include <linux/export.h>
|
||||
#include "core.h"
|
||||
#include "dp_tx.h"
|
||||
@@ -39,7 +38,6 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr)
|
||||
|
||||
ath11k_peer_rx_tid_cleanup(ar, peer);
|
||||
peer->dp_setup_done = false;
|
||||
crypto_free_shash(peer->tfm_mmic);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#include <linux/fips.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <crypto/hash.h>
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
#include "debugfs_htt_stats.h"
|
||||
@@ -1761,6 +1761,7 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
|
||||
int buf_first_hdr_len, buf_first_len;
|
||||
struct hal_rx_desc *ldesc;
|
||||
int space_extra, rem_len, buf_len;
|
||||
bool is_continuation;
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz;
|
||||
|
||||
/* As the msdu is spread across multiple rx buffers,
|
||||
@@ -1810,7 +1811,8 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
|
||||
rem_len = msdu_len - buf_first_len;
|
||||
while ((skb = __skb_dequeue(msdu_list)) != NULL && rem_len > 0) {
|
||||
rxcb = ATH11K_SKB_RXCB(skb);
|
||||
if (rxcb->is_continuation)
|
||||
is_continuation = rxcb->is_continuation;
|
||||
if (is_continuation)
|
||||
buf_len = DP_RX_BUFFER_SIZE - hal_rx_desc_sz;
|
||||
else
|
||||
buf_len = rem_len;
|
||||
@@ -1828,7 +1830,7 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
rem_len -= buf_len;
|
||||
if (!rxcb->is_continuation)
|
||||
if (!is_continuation)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2214,8 +2216,7 @@ ath11k_dp_rx_h_find_peer(struct ath11k_base *ab, struct sk_buff *msdu)
|
||||
|
||||
lockdep_assert_held(&ab->base_lock);
|
||||
|
||||
if (rxcb->peer_id)
|
||||
peer = ath11k_peer_find_by_id(ab, rxcb->peer_id);
|
||||
peer = ath11k_peer_find_by_id(ab, rxcb->peer_id);
|
||||
|
||||
if (peer)
|
||||
return peer;
|
||||
@@ -3182,16 +3183,13 @@ static void ath11k_dp_rx_frag_timer(struct timer_list *timer)
|
||||
int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct crypto_shash *tfm;
|
||||
struct ath11k_peer *peer;
|
||||
struct dp_rx_tid *rx_tid;
|
||||
int i;
|
||||
|
||||
tfm = crypto_alloc_shash("michael_mic", 0, 0);
|
||||
if (IS_ERR(tfm)) {
|
||||
ath11k_warn(ab, "failed to allocate michael_mic shash: %ld\n",
|
||||
PTR_ERR(tfm));
|
||||
return PTR_ERR(tfm);
|
||||
if (fips_enabled) {
|
||||
ath11k_warn(ab, "This driver is disabled due to FIPS\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
@@ -3200,7 +3198,6 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id
|
||||
if (!peer) {
|
||||
ath11k_warn(ab, "failed to find the peer to set up fragment info\n");
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
crypto_free_shash(tfm);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -3211,54 +3208,12 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id
|
||||
skb_queue_head_init(&rx_tid->rx_frags);
|
||||
}
|
||||
|
||||
peer->tfm_mmic = tfm;
|
||||
peer->dp_setup_done = true;
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key,
|
||||
struct ieee80211_hdr *hdr, u8 *data,
|
||||
size_t data_len, u8 *mic)
|
||||
{
|
||||
SHASH_DESC_ON_STACK(desc, tfm);
|
||||
u8 mic_hdr[16] = {};
|
||||
u8 tid = 0;
|
||||
int ret;
|
||||
|
||||
if (!tfm)
|
||||
return -EINVAL;
|
||||
|
||||
desc->tfm = tfm;
|
||||
|
||||
ret = crypto_shash_setkey(tfm, key, 8);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = crypto_shash_init(desc);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* TKIP MIC header */
|
||||
memcpy(mic_hdr, ieee80211_get_DA(hdr), ETH_ALEN);
|
||||
memcpy(mic_hdr + ETH_ALEN, ieee80211_get_SA(hdr), ETH_ALEN);
|
||||
if (ieee80211_is_data_qos(hdr->frame_control))
|
||||
tid = ieee80211_get_tid(hdr);
|
||||
mic_hdr[12] = tid;
|
||||
|
||||
ret = crypto_shash_update(desc, mic_hdr, 16);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = crypto_shash_update(desc, data, data_len);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = crypto_shash_final(desc, mic);
|
||||
out:
|
||||
shash_desc_zero(desc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_dp_rx_h_verify_tkip_mic(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
struct sk_buff *msdu)
|
||||
{
|
||||
@@ -3267,7 +3222,7 @@ static int ath11k_dp_rx_h_verify_tkip_mic(struct ath11k *ar, struct ath11k_peer
|
||||
struct ieee80211_key_conf *key_conf;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u8 mic[IEEE80211_CCMP_MIC_LEN];
|
||||
int head_len, tail_len, ret;
|
||||
int head_len, tail_len;
|
||||
size_t data_len;
|
||||
u32 hdr_len, hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz;
|
||||
u8 *key, *data;
|
||||
@@ -3293,8 +3248,8 @@ static int ath11k_dp_rx_h_verify_tkip_mic(struct ath11k *ar, struct ath11k_peer
|
||||
data_len = msdu->len - head_len - tail_len;
|
||||
key = &key_conf->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
|
||||
|
||||
ret = ath11k_dp_rx_h_michael_mic(peer->tfm_mmic, key, hdr, data, data_len, mic);
|
||||
if (ret || memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
|
||||
michael_mic(key, hdr, data, data_len, mic);
|
||||
if (memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
|
||||
goto mic_fail;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1387,14 +1387,22 @@ EXPORT_SYMBOL(ath11k_hal_srng_deinit);
|
||||
|
||||
void ath11k_hal_srng_clear(struct ath11k_base *ab)
|
||||
{
|
||||
/* No need to memset rdp and wrp memory since each individual
|
||||
* segment would get cleared in ath11k_hal_srng_src_hw_init()
|
||||
* and ath11k_hal_srng_dst_hw_init().
|
||||
/*
|
||||
* Preserve the shared pointer buffers, but clear the previous
|
||||
* firmware instance's hp/tp state before handing them back to FW.
|
||||
* LMAC rings reuse this shared memory without going through the
|
||||
* normal SRNG hw-init path that zeros non-LMAC ring pointers.
|
||||
*/
|
||||
memset(ab->hal.srng_list, 0,
|
||||
sizeof(ab->hal.srng_list));
|
||||
memset(ab->hal.shadow_reg_addr, 0,
|
||||
sizeof(ab->hal.shadow_reg_addr));
|
||||
if (ab->hal.rdp.vaddr)
|
||||
memset(ab->hal.rdp.vaddr, 0,
|
||||
sizeof(*ab->hal.rdp.vaddr) * HAL_SRNG_RING_ID_MAX);
|
||||
if (ab->hal.wrp.vaddr)
|
||||
memset(ab->hal.wrp.vaddr, 0,
|
||||
sizeof(*ab->hal.wrp.vaddr) * HAL_SRNG_NUM_LMAC_RINGS);
|
||||
ab->hal.avail_blk_resource = 0;
|
||||
ab->hal.current_blk_index = 0;
|
||||
ab->hal.num_shadow_reg_configured = 0;
|
||||
|
||||
@@ -1467,11 +1467,8 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
|
||||
case HAL_RX_MPDU_START: {
|
||||
struct hal_rx_mpdu_info *mpdu_info =
|
||||
(struct hal_rx_mpdu_info *)tlv_data;
|
||||
u16 peer_id;
|
||||
|
||||
peer_id = ath11k_hal_rx_mpduinfo_get_peerid(ab, mpdu_info);
|
||||
if (peer_id)
|
||||
ppdu_info->peer_id = peer_id;
|
||||
ppdu_info->peer_id = ath11k_hal_rx_mpduinfo_get_peerid(ab, mpdu_info);
|
||||
break;
|
||||
}
|
||||
case HAL_RXPCU_PPDU_END_INFO: {
|
||||
|
||||
@@ -1557,12 +1557,15 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif,
|
||||
if (!beacons || !beacons->cnt) {
|
||||
ath11k_warn(arvif->ar->ab,
|
||||
"failed to get ema beacon templates from mac80211\n");
|
||||
return -EPERM;
|
||||
ret = -EPERM;
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (tx_arvif == arvif) {
|
||||
if (ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb))
|
||||
return -EINVAL;
|
||||
if (ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb)) {
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
} else {
|
||||
arvif->wpaie_present = tx_arvif->wpaie_present;
|
||||
}
|
||||
@@ -1589,11 +1592,11 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif,
|
||||
}
|
||||
}
|
||||
|
||||
ieee80211_beacon_free_ema_list(beacons);
|
||||
|
||||
if (tx_arvif != arvif && !nontx_vif_params_set)
|
||||
return -EINVAL; /* Profile not found in the beacons */
|
||||
ret = -EINVAL; /* Profile not found in the beacons */
|
||||
|
||||
free:
|
||||
ieee80211_beacon_free_ema_list(beacons);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1622,19 +1625,22 @@ static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif,
|
||||
}
|
||||
|
||||
if (tx_arvif == arvif) {
|
||||
if (ath11k_mac_set_vif_params(tx_arvif, bcn))
|
||||
return -EINVAL;
|
||||
if (ath11k_mac_set_vif_params(tx_arvif, bcn)) {
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
} else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn)) {
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
|
||||
kfree_skb(bcn);
|
||||
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to submit beacon template command: %d\n",
|
||||
ret);
|
||||
|
||||
free:
|
||||
kfree_skb(bcn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3305,7 +3311,7 @@ static int ath11k_mac_fils_discovery(struct ath11k_vif *arvif,
|
||||
if (info->fils_discovery.max_interval) {
|
||||
interval = info->fils_discovery.max_interval;
|
||||
|
||||
tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif);
|
||||
tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif, 0);
|
||||
if (tmpl)
|
||||
ret = ath11k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,
|
||||
tmpl);
|
||||
@@ -3314,7 +3320,7 @@ static int ath11k_mac_fils_discovery(struct ath11k_vif *arvif,
|
||||
interval = info->unsol_bcast_probe_resp_interval;
|
||||
|
||||
tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ar->hw,
|
||||
arvif->vif);
|
||||
arvif->vif, 0);
|
||||
if (tmpl)
|
||||
ret = ath11k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,
|
||||
tmpl);
|
||||
@@ -6282,10 +6288,10 @@ static int ath11k_mac_mgmt_action_frame_fill_elem_data(struct ath11k_vif *arvif,
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
/* make sure category field is present */
|
||||
if (skb->len < IEEE80211_MIN_ACTION_SIZE)
|
||||
if (skb->len < IEEE80211_MIN_ACTION_SIZE(category))
|
||||
return -EINVAL;
|
||||
|
||||
remaining_len = skb->len - IEEE80211_MIN_ACTION_SIZE;
|
||||
remaining_len = skb->len - IEEE80211_MIN_ACTION_SIZE(category);
|
||||
has_protected = ieee80211_has_protected(hdr->frame_control);
|
||||
|
||||
/* In case of SW crypto and hdr protected (PMF), packet will already be encrypted,
|
||||
|
||||
@@ -29,7 +29,6 @@ struct ath11k_peer {
|
||||
/* Info used in MMIC verification of
|
||||
* RX fragments
|
||||
*/
|
||||
struct crypto_shash *tfm_mmic;
|
||||
u8 mcast_keyidx;
|
||||
u8 ucast_keyidx;
|
||||
u16 sec_type;
|
||||
|
||||
@@ -457,6 +457,7 @@ static int ath11k_tm_cmd_wmi_ftm(struct ath11k *ar, struct nlattr *tb[])
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, cmd_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send wmi ftm command: %d\n", ret);
|
||||
dev_kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -9301,7 +9301,7 @@ int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id,
|
||||
{
|
||||
struct wmi_hw_data_filter_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -9326,7 +9326,13 @@ int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id,
|
||||
"hw data filter enable %d filter_bitmap 0x%x\n",
|
||||
enable, filter_bitmap);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_HW_DATA_FILTER_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar)
|
||||
@@ -9334,6 +9340,7 @@ int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar)
|
||||
struct wmi_wow_host_wakeup_ind *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -9347,14 +9354,20 @@ int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar)
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow host wakeup ind\n");
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_enable(struct ath11k *ar)
|
||||
{
|
||||
struct wmi_wow_enable_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -9369,7 +9382,13 @@ int ath11k_wmi_wow_enable(struct ath11k *ar)
|
||||
cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED;
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow enable\n");
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
|
||||
@@ -9378,7 +9397,7 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
|
||||
struct sk_buff *skb;
|
||||
struct wmi_scan_prob_req_oui_cmd *cmd;
|
||||
u32 prob_req_oui;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
prob_req_oui = (((u32)mac_addr[0]) << 16) |
|
||||
(((u32)mac_addr[1]) << 8) | mac_addr[2];
|
||||
@@ -9397,7 +9416,13 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "scan prob req oui %d\n",
|
||||
prob_req_oui);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_SCAN_PROB_REQ_OUI_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id,
|
||||
@@ -9407,6 +9432,7 @@ int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id,
|
||||
struct wmi_wow_add_del_event_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -9424,7 +9450,13 @@ int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id,
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add wakeup event %s enable %d vdev_id %d\n",
|
||||
wow_wakeup_event(event), enable, vdev_id);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id,
|
||||
@@ -9437,6 +9469,7 @@ int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id,
|
||||
struct sk_buff *skb;
|
||||
u8 *ptr;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
sizeof(*tlv) + /* array struct */
|
||||
@@ -9529,7 +9562,13 @@ int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id,
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d\n",
|
||||
vdev_id, pattern_id, pattern_offset);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_ADD_WAKE_PATTERN_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id)
|
||||
@@ -9537,6 +9576,7 @@ int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id)
|
||||
struct wmi_wow_del_pattern_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -9555,7 +9595,13 @@ int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id)
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow del pattern vdev_id %d pattern_id %d\n",
|
||||
vdev_id, pattern_id);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_WOW_DEL_WAKE_PATTERN_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
@@ -9699,6 +9745,7 @@ int ath11k_wmi_wow_config_pno(struct ath11k *ar, u32 vdev_id,
|
||||
struct wmi_pno_scan_req *pno_scan)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
if (pno_scan->enable)
|
||||
skb = ath11k_wmi_op_gen_config_pno_start(ar, vdev_id, pno_scan);
|
||||
@@ -9708,7 +9755,13 @@ int ath11k_wmi_wow_config_pno(struct ath11k *ar, u32 vdev_id,
|
||||
if (IS_ERR_OR_NULL(skb))
|
||||
return -ENOMEM;
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_wmi_fill_ns_offload(struct ath11k *ar,
|
||||
@@ -9826,6 +9879,7 @@ int ath11k_wmi_arp_ns_offload(struct ath11k *ar,
|
||||
u8 *buf_ptr;
|
||||
size_t len;
|
||||
u8 ns_cnt, ns_ext_tuples = 0;
|
||||
int ret;
|
||||
|
||||
offload = &arvif->arp_ns_offload;
|
||||
ns_cnt = offload->ipv6_count;
|
||||
@@ -9864,7 +9918,13 @@ int ath11k_wmi_arp_ns_offload(struct ath11k *ar,
|
||||
if (ns_ext_tuples)
|
||||
ath11k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 1);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_SET_ARP_NS_OFFLOAD_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_gtk_rekey_offload(struct ath11k *ar,
|
||||
@@ -9872,7 +9932,7 @@ int ath11k_wmi_gtk_rekey_offload(struct ath11k *ar,
|
||||
{
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
struct ath11k_rekey_data *rekey_data = &arvif->rekey_data;
|
||||
int len;
|
||||
int ret, len;
|
||||
struct sk_buff *skb;
|
||||
__le64 replay_ctr;
|
||||
|
||||
@@ -9906,14 +9966,20 @@ int ath11k_wmi_gtk_rekey_offload(struct ath11k *ar,
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "offload gtk rekey vdev: %d %d\n",
|
||||
arvif->vdev_id, enable);
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID offload\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_gtk_rekey_getinfo(struct ath11k *ar,
|
||||
struct ath11k_vif *arvif)
|
||||
{
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
int len;
|
||||
int ret, len;
|
||||
struct sk_buff *skb;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
@@ -9930,7 +9996,13 @@ int ath11k_wmi_gtk_rekey_getinfo(struct ath11k *ar,
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "get gtk rekey vdev_id: %d\n",
|
||||
arvif->vdev_id);
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID getinfo\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_val)
|
||||
@@ -9940,6 +10012,7 @@ int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_va
|
||||
struct sk_buff *skb;
|
||||
u8 *buf_ptr;
|
||||
u32 len, sar_len_aligned, rsvd_len_aligned;
|
||||
int ret;
|
||||
|
||||
sar_len_aligned = roundup(BIOS_SAR_TABLE_LEN, sizeof(u32));
|
||||
rsvd_len_aligned = roundup(BIOS_SAR_RSVD1_LEN, sizeof(u32));
|
||||
@@ -9970,7 +10043,13 @@ int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_va
|
||||
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
|
||||
FIELD_PREP(WMI_TLV_LEN, rsvd_len_aligned);
|
||||
|
||||
return ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar)
|
||||
@@ -9981,6 +10060,7 @@ int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar)
|
||||
struct sk_buff *skb;
|
||||
u8 *buf_ptr;
|
||||
u32 len, rsvd_len_aligned;
|
||||
int ret;
|
||||
|
||||
rsvd_len_aligned = roundup(BIOS_SAR_RSVD2_LEN, sizeof(u32));
|
||||
len = sizeof(*cmd) + TLV_HDR_SIZE + rsvd_len_aligned;
|
||||
@@ -10000,7 +10080,13 @@ int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar)
|
||||
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
|
||||
FIELD_PREP(WMI_TLV_LEN, rsvd_len_aligned);
|
||||
|
||||
return ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
||||
@@ -10011,6 +10097,7 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
||||
struct wmi_sta_keepalive_arp_resp *arp;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd) + sizeof(*arp);
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
@@ -10042,7 +10129,13 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
||||
"sta keepalive vdev %d enabled %d method %d interval %d\n",
|
||||
arg->vdev_id, arg->enabled, arg->method, arg->interval);
|
||||
|
||||
return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_STA_KEEPALIVE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *ar)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
config ATH12K
|
||||
tristate "Qualcomm Technologies Wi-Fi 7 support (ath12k)"
|
||||
depends on MAC80211 && HAS_DMA && PCI
|
||||
select CRYPTO_MICHAEL_MIC
|
||||
select QCOM_QMI_HELPERS
|
||||
select MHI_BUS
|
||||
select QRTR
|
||||
|
||||
@@ -32,6 +32,7 @@ ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
|
||||
ath12k-$(CONFIG_PM) += wow.o
|
||||
ath12k-$(CONFIG_ATH12K_COREDUMP) += coredump.o
|
||||
ath12k-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
ath12k-$(CONFIG_THERMAL) += thermal.o
|
||||
|
||||
# for tracing framework to find trace.h
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
||||
@@ -382,8 +382,12 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab)
|
||||
ATH12K_AHB_UPD_SWID;
|
||||
|
||||
/* Load FW image to a reserved memory location */
|
||||
ret = qcom_mdt_load(dev, fw, fw_name, pasid, mem_region, mem_phys, mem_size,
|
||||
&mem_phys);
|
||||
if (ab_ahb->scm_auth_enabled)
|
||||
ret = qcom_mdt_load(dev, fw, fw_name, pasid, mem_region,
|
||||
mem_phys, mem_size, &mem_phys);
|
||||
else
|
||||
ret = qcom_mdt_load_no_init(dev, fw, fw_name, mem_region,
|
||||
mem_phys, mem_size, &mem_phys);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "Failed to load MDT segments: %d\n", ret);
|
||||
goto err_fw;
|
||||
@@ -414,11 +418,13 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab)
|
||||
goto err_fw2;
|
||||
}
|
||||
|
||||
/* Authenticate FW image using peripheral ID */
|
||||
ret = qcom_scm_pas_auth_and_reset(pasid);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to boot the remote processor %d\n", ret);
|
||||
goto err_fw2;
|
||||
if (ab_ahb->scm_auth_enabled) {
|
||||
/* Authenticate FW image using peripheral ID */
|
||||
ret = qcom_scm_pas_auth_and_reset(pasid);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to boot the remote processor %d\n", ret);
|
||||
goto err_fw2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Instruct Q6 to spawn userPD thread */
|
||||
@@ -475,13 +481,15 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab, bool is_suspend)
|
||||
|
||||
qcom_smem_state_update_bits(ab_ahb->stop_state, BIT(ab_ahb->stop_bit), 0);
|
||||
|
||||
pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) |
|
||||
ATH12K_AHB_UPD_SWID;
|
||||
/* Release the firmware */
|
||||
ret = qcom_scm_pas_shutdown(pasid);
|
||||
if (ret)
|
||||
ath12k_err(ab, "scm pas shutdown failed for userPD%d: %d\n",
|
||||
ab_ahb->userpd_id, ret);
|
||||
if (ab_ahb->scm_auth_enabled) {
|
||||
pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) |
|
||||
ATH12K_AHB_UPD_SWID;
|
||||
/* Release the firmware */
|
||||
ret = qcom_scm_pas_shutdown(pasid);
|
||||
if (ret)
|
||||
ath12k_err(ab, "scm pas shutdown failed for userPD%d\n",
|
||||
ab_ahb->userpd_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath12k_ahb_init_qmi_ce_config(struct ath12k_base *ab)
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#define ATH12K_ROOTPD_READY_TIMEOUT (5 * HZ)
|
||||
#define ATH12K_RPROC_AFTER_POWERUP QCOM_SSR_AFTER_POWERUP
|
||||
#define ATH12K_AHB_FW_PREFIX "q6_fw"
|
||||
#define ATH12K_AHB_FW_SUFFIX ".mdt"
|
||||
#define ATH12K_AHB_FW2 "iu_fw.mdt"
|
||||
#define ATH12K_AHB_FW_SUFFIX ".mbn"
|
||||
#define ATH12K_AHB_FW2 "iu_fw.mbn"
|
||||
#define ATH12K_AHB_UPD_SWID 0x12
|
||||
#define ATH12K_USERPD_SPAWN_TIMEOUT (5 * HZ)
|
||||
#define ATH12K_USERPD_READY_TIMEOUT (10 * HZ)
|
||||
@@ -68,6 +68,7 @@ struct ath12k_ahb {
|
||||
int userpd_irq_num[ATH12K_USERPD_MAX_IRQ];
|
||||
const struct ath12k_ahb_ops *ahb_ops;
|
||||
const struct ath12k_ahb_device_family_ops *device_family_ops;
|
||||
bool scm_auth_enabled;
|
||||
};
|
||||
|
||||
struct ath12k_ahb_driver {
|
||||
|
||||
@@ -38,10 +38,15 @@
|
||||
#define PIPEDIR_INOUT 3 /* bidirectional */
|
||||
#define PIPEDIR_INOUT_H2H 4 /* bidirectional, host to host */
|
||||
|
||||
/* CE address/mask */
|
||||
#define CE_HOST_IE_ADDRESS 0x75804C
|
||||
#define CE_HOST_IE_2_ADDRESS 0x758050
|
||||
#define CE_HOST_IE_3_ADDRESS CE_HOST_IE_ADDRESS
|
||||
/* IPQ5332 CE address/mask */
|
||||
#define CE_HOST_IPQ5332_IE_ADDRESS 0x75804C
|
||||
#define CE_HOST_IPQ5332_IE_2_ADDRESS 0x758050
|
||||
#define CE_HOST_IPQ5332_IE_3_ADDRESS CE_HOST_IPQ5332_IE_ADDRESS
|
||||
|
||||
/* IPQ5424 CE address/mask */
|
||||
#define CE_HOST_IPQ5424_IE_ADDRESS 0x21804C
|
||||
#define CE_HOST_IPQ5424_IE_2_ADDRESS 0x218050
|
||||
#define CE_HOST_IPQ5424_IE_3_ADDRESS CE_HOST_IPQ5424_IE_ADDRESS
|
||||
|
||||
#define CE_HOST_IE_3_SHIFT 0xC
|
||||
|
||||
|
||||
@@ -835,8 +835,6 @@ static int ath12k_core_soc_create(struct ath12k_base *ab)
|
||||
goto err_qmi_deinit;
|
||||
}
|
||||
|
||||
ath12k_debugfs_pdev_create(ab);
|
||||
|
||||
return 0;
|
||||
|
||||
err_qmi_deinit:
|
||||
@@ -863,11 +861,24 @@ static int ath12k_core_pdev_create(struct ath12k_base *ab)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath12k_thermal_register(ab);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "could not register thermal device: %d\n", ret);
|
||||
goto err_dp_pdev_free;
|
||||
}
|
||||
|
||||
ath12k_debugfs_pdev_create(ab);
|
||||
|
||||
return 0;
|
||||
|
||||
err_dp_pdev_free:
|
||||
ath12k_dp_pdev_free(ab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_core_pdev_destroy(struct ath12k_base *ab)
|
||||
{
|
||||
ath12k_thermal_unregister(ab);
|
||||
ath12k_dp_pdev_free(ab);
|
||||
}
|
||||
|
||||
@@ -1006,6 +1017,8 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag)
|
||||
|
||||
ath12k_mac_unregister(ag);
|
||||
|
||||
ath12k_mac_mlo_teardown(ag);
|
||||
|
||||
for (i = ag->num_devices - 1; i >= 0; i--) {
|
||||
ab = ag->ab[i];
|
||||
if (!ab)
|
||||
@@ -1123,8 +1136,14 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag)
|
||||
|
||||
lockdep_assert_held(&ag->mutex);
|
||||
|
||||
if (test_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags))
|
||||
if (test_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags)) {
|
||||
ret = ath12k_core_mlo_setup(ag);
|
||||
if (WARN_ON(ret)) {
|
||||
ath12k_mac_unregister(ag);
|
||||
goto err_mac_destroy;
|
||||
}
|
||||
goto core_pdev_create;
|
||||
}
|
||||
|
||||
ret = ath12k_mac_allocate(ag);
|
||||
if (WARN_ON(ret))
|
||||
@@ -1361,6 +1380,7 @@ static int ath12k_core_reconfigure_on_crash(struct ath12k_base *ab)
|
||||
|
||||
mutex_lock(&ab->core_lock);
|
||||
ath12k_link_sta_rhash_tbl_destroy(ab);
|
||||
ath12k_thermal_unregister(ab);
|
||||
ath12k_dp_pdev_free(ab);
|
||||
ath12k_ce_cleanup_pipes(ab);
|
||||
ath12k_wmi_detach(ab);
|
||||
@@ -1502,6 +1522,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
||||
complete(&ar->vdev_delete_done);
|
||||
complete(&ar->bss_survey_done);
|
||||
complete_all(&ar->regd_update_completed);
|
||||
complete_all(&ar->thermal.wmi_sync);
|
||||
|
||||
wake_up(&ar->dp.tx_empty_waitq);
|
||||
idr_for_each(&ar->txmgmt_idr,
|
||||
@@ -1817,10 +1838,22 @@ static struct ath12k_hw_group *ath12k_core_hw_group_alloc(struct ath12k_base *ab
|
||||
return ag;
|
||||
}
|
||||
|
||||
static void ath12k_core_free_wsi_info(struct ath12k_hw_group *ag)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ag->num_devices; i++) {
|
||||
of_node_put(ag->wsi_node[i]);
|
||||
ag->wsi_node[i] = NULL;
|
||||
}
|
||||
ag->num_devices = 0;
|
||||
}
|
||||
|
||||
static void ath12k_core_hw_group_free(struct ath12k_hw_group *ag)
|
||||
{
|
||||
mutex_lock(&ath12k_hw_group_mutex);
|
||||
|
||||
ath12k_core_free_wsi_info(ag);
|
||||
list_del(&ag->list);
|
||||
kfree(ag);
|
||||
|
||||
@@ -1846,52 +1879,59 @@ static struct ath12k_hw_group *ath12k_core_hw_group_find_by_dt(struct ath12k_bas
|
||||
static int ath12k_core_get_wsi_info(struct ath12k_hw_group *ag,
|
||||
struct ath12k_base *ab)
|
||||
{
|
||||
struct device_node *wsi_dev = ab->dev->of_node, *next_wsi_dev;
|
||||
struct device_node *tx_endpoint, *next_rx_endpoint;
|
||||
int device_count = 0;
|
||||
struct device_node *next_wsi_dev;
|
||||
int device_count = 0, ret = 0;
|
||||
struct device_node *wsi_dev;
|
||||
|
||||
next_wsi_dev = wsi_dev;
|
||||
|
||||
if (!next_wsi_dev)
|
||||
wsi_dev = of_node_get(ab->dev->of_node);
|
||||
if (!wsi_dev)
|
||||
return -ENODEV;
|
||||
|
||||
do {
|
||||
ag->wsi_node[device_count] = next_wsi_dev;
|
||||
if (device_count >= ATH12K_MAX_DEVICES) {
|
||||
ath12k_warn(ab, "device count in DT %d is more than limit %d\n",
|
||||
device_count, ATH12K_MAX_DEVICES);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
tx_endpoint = of_graph_get_endpoint_by_regs(next_wsi_dev, 0, -1);
|
||||
ag->wsi_node[device_count++] = of_node_get(wsi_dev);
|
||||
|
||||
struct device_node *tx_endpoint __free(device_node) =
|
||||
of_graph_get_endpoint_by_regs(wsi_dev, 0, -1);
|
||||
if (!tx_endpoint) {
|
||||
of_node_put(next_wsi_dev);
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
next_rx_endpoint = of_graph_get_remote_endpoint(tx_endpoint);
|
||||
struct device_node *next_rx_endpoint __free(device_node) =
|
||||
of_graph_get_remote_endpoint(tx_endpoint);
|
||||
if (!next_rx_endpoint) {
|
||||
of_node_put(next_wsi_dev);
|
||||
of_node_put(tx_endpoint);
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
of_node_put(tx_endpoint);
|
||||
of_node_put(next_wsi_dev);
|
||||
|
||||
next_wsi_dev = of_graph_get_port_parent(next_rx_endpoint);
|
||||
if (!next_wsi_dev) {
|
||||
of_node_put(next_rx_endpoint);
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
of_node_put(next_rx_endpoint);
|
||||
of_node_put(wsi_dev);
|
||||
wsi_dev = next_wsi_dev;
|
||||
} while (ab->dev->of_node != wsi_dev);
|
||||
|
||||
device_count++;
|
||||
if (device_count > ATH12K_MAX_DEVICES) {
|
||||
ath12k_warn(ab, "device count in DT %d is more than limit %d\n",
|
||||
device_count, ATH12K_MAX_DEVICES);
|
||||
of_node_put(next_wsi_dev);
|
||||
return -EINVAL;
|
||||
if (ret) {
|
||||
while (--device_count >= 0) {
|
||||
of_node_put(ag->wsi_node[device_count]);
|
||||
ag->wsi_node[device_count] = NULL;
|
||||
}
|
||||
} while (wsi_dev != next_wsi_dev);
|
||||
|
||||
of_node_put(next_wsi_dev);
|
||||
of_node_put(wsi_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_node_put(wsi_dev);
|
||||
ag->num_devices = device_count;
|
||||
|
||||
return 0;
|
||||
@@ -1962,9 +2002,9 @@ static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *a
|
||||
ath12k_core_get_wsi_index(ag, ab)) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"unable to get wsi info from dt, grouping single device");
|
||||
ath12k_core_free_wsi_info(ag);
|
||||
ag->id = ATH12K_INVALID_GROUP_ID;
|
||||
ag->num_devices = 1;
|
||||
memset(ag->wsi_node, 0, sizeof(ag->wsi_node));
|
||||
wsi->index = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "coredump.h"
|
||||
#include "cmn_defs.h"
|
||||
#include "dp_cmn.h"
|
||||
#include "thermal.h"
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
||||
|
||||
@@ -156,6 +157,7 @@ enum ath12k_hw_rev {
|
||||
ATH12K_HW_WCN7850_HW20,
|
||||
ATH12K_HW_IPQ5332_HW10,
|
||||
ATH12K_HW_QCC2072_HW10,
|
||||
ATH12K_HW_IPQ5424_HW10,
|
||||
};
|
||||
|
||||
enum ath12k_firmware_mode {
|
||||
@@ -522,7 +524,7 @@ struct ath12k_sta {
|
||||
u16 links_map;
|
||||
u8 assoc_link_id;
|
||||
u16 ml_peer_id;
|
||||
u8 num_peer;
|
||||
u16 free_logical_link_idx_map;
|
||||
|
||||
enum ieee80211_sta_state state;
|
||||
};
|
||||
@@ -587,6 +589,7 @@ struct ath12k_dbg_htt_stats {
|
||||
struct ath12k_debug {
|
||||
struct dentry *debugfs_pdev;
|
||||
struct dentry *debugfs_pdev_symlink;
|
||||
struct dentry *debugfs_pdev_symlink_default;
|
||||
struct ath12k_dbg_htt_stats htt_stats;
|
||||
enum wmi_halphy_ctrl_path_stats_id tpc_stats_type;
|
||||
bool tpc_request;
|
||||
@@ -672,6 +675,7 @@ struct ath12k {
|
||||
u8 pdev_idx;
|
||||
u8 lmac_id;
|
||||
u8 hw_link_id;
|
||||
u8 radio_idx;
|
||||
|
||||
struct completion peer_assoc_done;
|
||||
struct completion peer_delete_done;
|
||||
@@ -757,6 +761,8 @@ struct ath12k {
|
||||
|
||||
s8 max_allowed_tx_power;
|
||||
struct ath12k_pdev_rssi_offsets rssi_info;
|
||||
|
||||
struct ath12k_thermal thermal;
|
||||
};
|
||||
|
||||
struct ath12k_hw {
|
||||
@@ -1363,13 +1369,13 @@ static inline struct ath12k_hw *ath12k_hw_to_ah(struct ieee80211_hw *hw)
|
||||
return hw->priv;
|
||||
}
|
||||
|
||||
static inline struct ath12k *ath12k_ah_to_ar(struct ath12k_hw *ah, u8 hw_link_id)
|
||||
static inline struct ath12k *ath12k_ah_to_ar(struct ath12k_hw *ah, u8 radio_idx)
|
||||
{
|
||||
if (WARN(hw_link_id >= ah->num_radio,
|
||||
"bad hw link id %d, so switch to default link\n", hw_link_id))
|
||||
hw_link_id = 0;
|
||||
if (WARN(radio_idx >= ah->num_radio,
|
||||
"bad radio index %d, use default radio\n", radio_idx))
|
||||
radio_idx = 0;
|
||||
|
||||
return &ah->radio[hw_link_id];
|
||||
return &ah->radio[radio_idx];
|
||||
}
|
||||
|
||||
static inline struct ath12k_hw *ath12k_ar_to_ah(struct ath12k *ar)
|
||||
|
||||
@@ -1473,18 +1473,35 @@ void ath12k_debugfs_register(struct ath12k *ar)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ieee80211_hw *hw = ar->ah->hw;
|
||||
char pdev_name[5];
|
||||
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
|
||||
struct dentry *ath12k_fs;
|
||||
char buf[100] = {};
|
||||
char pdev_name[5];
|
||||
|
||||
scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
|
||||
|
||||
ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
|
||||
|
||||
/* Create a symlink under ieee80211/phy* */
|
||||
scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
|
||||
ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
|
||||
hw->wiphy->debugfsdir,
|
||||
buf);
|
||||
if (ar->radio_idx == 0) {
|
||||
scnprintf(buf, sizeof(buf), "../../ath12k/%pd2",
|
||||
ar->debug.debugfs_pdev);
|
||||
ath12k_fs = hw->wiphy->debugfsdir;
|
||||
|
||||
/* symbolic link for compatibility */
|
||||
ar->debug.debugfs_pdev_symlink_default = debugfs_create_symlink("ath12k",
|
||||
ath12k_fs,
|
||||
buf);
|
||||
}
|
||||
|
||||
if (ah->num_radio > 1) {
|
||||
scnprintf(buf, sizeof(buf), "../../../ath12k/%pd2",
|
||||
ar->debug.debugfs_pdev);
|
||||
ath12k_fs = hw->wiphy->radio_cfg[ar->radio_idx].radio_debugfsdir;
|
||||
ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
|
||||
ath12k_fs,
|
||||
buf);
|
||||
}
|
||||
|
||||
if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
|
||||
debugfs_create_file("dfs_simulate_radar", 0200,
|
||||
@@ -1513,7 +1530,9 @@ void ath12k_debugfs_unregister(struct ath12k *ar)
|
||||
|
||||
/* Remove symlink under ieee80211/phy* */
|
||||
debugfs_remove(ar->debug.debugfs_pdev_symlink);
|
||||
debugfs_remove(ar->debug.debugfs_pdev_symlink_default);
|
||||
debugfs_remove_recursive(ar->debug.debugfs_pdev);
|
||||
ar->debug.debugfs_pdev_symlink = NULL;
|
||||
ar->debug.debugfs_pdev_symlink_default = NULL;
|
||||
ar->debug.debugfs_pdev = NULL;
|
||||
}
|
||||
|
||||
@@ -5722,6 +5722,75 @@ ath12k_htt_print_tx_hwq_stats_cmn_tlv(const void *tag_buf, u16 tag_len,
|
||||
stats_req->buf_len = len;
|
||||
}
|
||||
|
||||
static void
|
||||
ath12k_htt_print_chan_switch_stats_tlv(const void *tag_buf, u16 tag_len,
|
||||
struct debug_htt_stats_req *stats_req)
|
||||
{
|
||||
const struct ath12k_htt_chan_switch_stats_tlv *sbuf = tag_buf;
|
||||
u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
|
||||
u32 switch_freq, switch_profile;
|
||||
u32 len = stats_req->buf_len;
|
||||
u8 *buf = stats_req->buf;
|
||||
u8 i;
|
||||
|
||||
if (tag_len < sizeof(*sbuf))
|
||||
return;
|
||||
|
||||
i = min(le32_to_cpu(sbuf->switch_count), ATH12K_HTT_CHAN_SWITCH_STATS_BUF_LEN);
|
||||
if (!i)
|
||||
return;
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "Channel Change Timings:\n");
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"|%-20s|%-21s|%-7s|%-12s|%-12s|%-15s|",
|
||||
"PRIMARY CHANNEL FREQ", "BANDWIDTH CENTER FREQ", "PHYMODE",
|
||||
"TX_CHAINMASK", "RX_CHAINMASK", "SWITCH TIME(us)");
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"%-7s|%-11s|%-7s|%-8s|%-7s|%-10s|\n",
|
||||
"INI(us)", "TPC+CTL(us)", "CAL(us)", "MISC(us)", "CTL(us)",
|
||||
"SW PROFILE");
|
||||
|
||||
/*
|
||||
* sbuf->switch_count has the number of successful channel changes. The firmware
|
||||
* sends the record of channel change in such a way that sbuf->chan_stats[0] will
|
||||
* point to the channel change that occurred first and the recent channel change
|
||||
* records will be stored in sbuf->chan_stats[9]. As and when new channel change
|
||||
* occurs, sbuf->chan_stats[0] will be replaced by records from the next index,
|
||||
* sbuf->chan_stats[1]. While printing the records, reverse chronological order
|
||||
* is followed, i.e., the most recent channel change records are printed first
|
||||
* and the oldest one, last.
|
||||
*/
|
||||
while (i--) {
|
||||
switch_freq = le32_to_cpu(sbuf->chan_stats[i].chan_switch_freq);
|
||||
switch_profile = le32_to_cpu(sbuf->chan_stats[i].chan_switch_profile);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"|%20u|%21u|%7u|%12u|%12u|%15u|",
|
||||
u32_get_bits(switch_freq,
|
||||
ATH12K_HTT_STATS_CHAN_SWITCH_BW_MHZ),
|
||||
u32_get_bits(switch_freq,
|
||||
ATH12K_HTT_STATS_CHAN_SWITCH_BAND_FREQ),
|
||||
u32_get_bits(switch_profile,
|
||||
ATH12K_HTT_STATS_CHAN_SWITCH_PHY_MODE),
|
||||
u32_get_bits(switch_profile,
|
||||
ATH12K_HTT_STATS_CHAN_SWITCH_TX_CHAINMASK),
|
||||
u32_get_bits(switch_profile,
|
||||
ATH12K_HTT_STATS_CHAN_SWITCH_RX_CHAINMASK),
|
||||
le32_to_cpu(sbuf->chan_stats[i].chan_switch_time));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"%7u|%11u|%7u|%8u|%7u|%10u|\n",
|
||||
le32_to_cpu(sbuf->chan_stats[i].ini_module_time),
|
||||
le32_to_cpu(sbuf->chan_stats[i].tpc_module_time),
|
||||
le32_to_cpu(sbuf->chan_stats[i].cal_module_time),
|
||||
le32_to_cpu(sbuf->chan_stats[i].misc_module_time),
|
||||
le32_to_cpu(sbuf->chan_stats[i].ctl_module_time),
|
||||
u32_get_bits(switch_profile,
|
||||
ATH12K_HTT_STATS_CHAN_SWITCH_SW_PROFILE));
|
||||
}
|
||||
|
||||
stats_req->buf_len = len;
|
||||
}
|
||||
|
||||
static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
|
||||
u16 tag, u16 len, const void *tag_buf,
|
||||
void *user_data)
|
||||
@@ -6024,6 +6093,9 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
|
||||
case HTT_STATS_TX_HWQ_CMN_TAG:
|
||||
ath12k_htt_print_tx_hwq_stats_cmn_tlv(tag_buf, len, stats_req);
|
||||
break;
|
||||
case HTT_STATS_CHAN_SWITCH_STATS_TAG:
|
||||
ath12k_htt_print_chan_switch_stats_tlv(tag_buf, len, stats_req);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -164,6 +164,7 @@ enum ath12k_dbg_htt_ext_stats_type {
|
||||
ATH12K_DBG_HTT_PDEV_MLO_IPC_STATS = 64,
|
||||
ATH12K_DBG_HTT_EXT_PDEV_RTT_RESP_STATS = 65,
|
||||
ATH12K_DBG_HTT_EXT_PDEV_RTT_INITIATOR_STATS = 66,
|
||||
ATH12K_DBG_HTT_EXT_CHAN_SWITCH_STATS = 76,
|
||||
|
||||
/* keep this last */
|
||||
ATH12K_DBG_HTT_NUM_EXT_STATS,
|
||||
@@ -267,6 +268,7 @@ enum ath12k_dbg_htt_tlv_tag {
|
||||
HTT_STATS_PDEV_RTT_HW_STATS_TAG = 196,
|
||||
HTT_STATS_PDEV_RTT_TBR_SELFGEN_QUEUED_STATS_TAG = 197,
|
||||
HTT_STATS_PDEV_RTT_TBR_CMD_RESULT_STATS_TAG = 198,
|
||||
HTT_STATS_CHAN_SWITCH_STATS_TAG = 213,
|
||||
|
||||
HTT_STATS_MAX_TAG,
|
||||
};
|
||||
@@ -2156,4 +2158,28 @@ struct htt_tx_hwq_stats_cmn_tlv {
|
||||
__le32 txq_timeout;
|
||||
} __packed;
|
||||
|
||||
#define ATH12K_HTT_CHAN_SWITCH_STATS_BUF_LEN 10
|
||||
|
||||
#define ATH12K_HTT_STATS_CHAN_SWITCH_BW_MHZ GENMASK(15, 0)
|
||||
#define ATH12K_HTT_STATS_CHAN_SWITCH_BAND_FREQ GENMASK(31, 16)
|
||||
#define ATH12K_HTT_STATS_CHAN_SWITCH_PHY_MODE GENMASK(7, 0)
|
||||
#define ATH12K_HTT_STATS_CHAN_SWITCH_TX_CHAINMASK GENMASK(15, 8)
|
||||
#define ATH12K_HTT_STATS_CHAN_SWITCH_RX_CHAINMASK GENMASK(23, 16)
|
||||
#define ATH12K_HTT_STATS_CHAN_SWITCH_SW_PROFILE GENMASK(31, 24)
|
||||
|
||||
struct ath12k_htt_chan_switch_stats_tlv {
|
||||
struct {
|
||||
__le32 chan_switch_freq;
|
||||
__le32 chan_switch_profile;
|
||||
__le32 chan_switch_time;
|
||||
__le32 cal_module_time;
|
||||
__le32 ini_module_time;
|
||||
__le32 tpc_module_time;
|
||||
__le32 misc_module_time;
|
||||
__le32 ctl_module_time;
|
||||
__le32 reserved;
|
||||
} chan_stats[ATH12K_HTT_CHAN_SWITCH_STATS_BUF_LEN];
|
||||
__le32 switch_count; /* shows how many channel changes have occurred */
|
||||
} __packed;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#include <crypto/hash.h>
|
||||
#include "core.h"
|
||||
#include "dp_tx.h"
|
||||
#include "hif.h"
|
||||
@@ -41,7 +40,6 @@ void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr)
|
||||
}
|
||||
|
||||
ath12k_dp_rx_peer_tid_cleanup(ar, peer);
|
||||
crypto_free_shash(peer->dp_peer->tfm_mmic);
|
||||
peer->dp_peer->dp_setup_done = false;
|
||||
spin_unlock_bh(&dp->dp_lock);
|
||||
}
|
||||
|
||||
@@ -205,16 +205,9 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev,
|
||||
if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE)))
|
||||
return;
|
||||
|
||||
if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {
|
||||
if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON))
|
||||
is_ampdu =
|
||||
HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags);
|
||||
tx_retry_failed =
|
||||
__le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_tried) -
|
||||
__le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_success);
|
||||
tx_retry_count =
|
||||
HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
|
||||
HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
|
||||
}
|
||||
|
||||
if (usr_stats->tlv_flags &
|
||||
BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) {
|
||||
@@ -223,10 +216,19 @@ ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev,
|
||||
HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M);
|
||||
tid = le32_get_bits(usr_stats->ack_ba.info,
|
||||
HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM);
|
||||
}
|
||||
|
||||
if (common->fes_duration_us)
|
||||
tx_duration = le32_to_cpu(common->fes_duration_us);
|
||||
if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {
|
||||
tx_retry_failed =
|
||||
__le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_tried) -
|
||||
__le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_success);
|
||||
tx_retry_count =
|
||||
HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
|
||||
HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
|
||||
}
|
||||
|
||||
if (common->fes_duration_us)
|
||||
tx_duration = le32_to_cpu(common->fes_duration_us);
|
||||
}
|
||||
|
||||
user_rate = &usr_stats->rate;
|
||||
flags = HTT_USR_RATE_PREAMBLE(user_rate->rate_flags);
|
||||
|
||||
@@ -139,7 +139,6 @@ struct ath12k_dp_peer {
|
||||
u16 sec_type;
|
||||
|
||||
/* Info used in MMIC verification of * RX fragments */
|
||||
struct crypto_shash *tfm_mmic;
|
||||
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
|
||||
struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS];
|
||||
struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#include <linux/fips.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <crypto/hash.h>
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
#include "hw.h"
|
||||
@@ -1122,7 +1122,6 @@ static void ath12k_dp_rx_h_undecap_eth(struct ath12k_pdev_dp *dp_pdev,
|
||||
}
|
||||
|
||||
void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
|
||||
struct hal_rx_desc *rx_desc,
|
||||
enum hal_encrypt_type enctype,
|
||||
bool decrypted,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
@@ -1398,7 +1397,6 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc
|
||||
EXPORT_SYMBOL(ath12k_dp_rx_deliver_msdu);
|
||||
|
||||
bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_dp *dp,
|
||||
struct hal_rx_desc *rx_desc,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
{
|
||||
@@ -1438,29 +1436,27 @@ static void ath12k_dp_rx_frag_timer(struct timer_list *timer)
|
||||
int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct crypto_shash *tfm;
|
||||
struct ath12k_dp_link_peer *peer;
|
||||
struct ath12k_dp_rx_tid *rx_tid;
|
||||
int i;
|
||||
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
|
||||
|
||||
tfm = crypto_alloc_shash("michael_mic", 0, 0);
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
if (fips_enabled) {
|
||||
ath12k_warn(ab, "This driver is disabled due to FIPS\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
spin_lock_bh(&dp->dp_lock);
|
||||
|
||||
peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac);
|
||||
if (!peer || !peer->dp_peer) {
|
||||
spin_unlock_bh(&dp->dp_lock);
|
||||
crypto_free_shash(tfm);
|
||||
ath12k_warn(ab, "failed to find the peer to set up fragment info\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!peer->primary_link) {
|
||||
spin_unlock_bh(&dp->dp_lock);
|
||||
crypto_free_shash(tfm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1471,55 +1467,12 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev
|
||||
skb_queue_head_init(&rx_tid->rx_frags);
|
||||
}
|
||||
|
||||
peer->dp_peer->tfm_mmic = tfm;
|
||||
peer->dp_peer->dp_setup_done = true;
|
||||
spin_unlock_bh(&dp->dp_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath12k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key,
|
||||
struct ieee80211_hdr *hdr, u8 *data,
|
||||
size_t data_len, u8 *mic)
|
||||
{
|
||||
SHASH_DESC_ON_STACK(desc, tfm);
|
||||
u8 mic_hdr[16] = {};
|
||||
u8 tid = 0;
|
||||
int ret;
|
||||
|
||||
if (!tfm)
|
||||
return -EINVAL;
|
||||
|
||||
desc->tfm = tfm;
|
||||
|
||||
ret = crypto_shash_setkey(tfm, key, 8);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = crypto_shash_init(desc);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* TKIP MIC header */
|
||||
memcpy(mic_hdr, ieee80211_get_DA(hdr), ETH_ALEN);
|
||||
memcpy(mic_hdr + ETH_ALEN, ieee80211_get_SA(hdr), ETH_ALEN);
|
||||
if (ieee80211_is_data_qos(hdr->frame_control))
|
||||
tid = ieee80211_get_tid(hdr);
|
||||
mic_hdr[12] = tid;
|
||||
|
||||
ret = crypto_shash_update(desc, mic_hdr, 16);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = crypto_shash_update(desc, data, data_len);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = crypto_shash_final(desc, mic);
|
||||
out:
|
||||
shash_desc_zero(desc);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath12k_dp_rx_h_michael_mic);
|
||||
|
||||
void ath12k_dp_rx_h_undecap_frag(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
|
||||
enum hal_encrypt_type enctype, u32 flags)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#ifndef ATH12K_DP_RX_H
|
||||
#define ATH12K_DP_RX_H
|
||||
|
||||
#include <crypto/hash.h>
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
||||
@@ -189,7 +188,6 @@ void ath12k_dp_extract_rx_desc_data(struct ath12k_hal *hal,
|
||||
}
|
||||
|
||||
void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
|
||||
struct hal_rx_desc *rx_desc,
|
||||
enum hal_encrypt_type enctype,
|
||||
bool decrypted,
|
||||
struct hal_rx_desc_data *rx_info);
|
||||
@@ -197,7 +195,6 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info);
|
||||
bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_dp *dp,
|
||||
struct hal_rx_desc *rx_desc,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info);
|
||||
u64 ath12k_dp_rx_h_get_pn(struct ath12k_dp *dp, struct sk_buff *skb);
|
||||
@@ -206,9 +203,6 @@ void ath12k_dp_rx_h_sort_frags(struct ath12k_hal *hal,
|
||||
struct sk_buff *cur_frag);
|
||||
void ath12k_dp_rx_h_undecap_frag(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
|
||||
enum hal_encrypt_type enctype, u32 flags);
|
||||
int ath12k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key,
|
||||
struct ieee80211_hdr *hdr, u8 *data,
|
||||
size_t data_len, u8 *mic);
|
||||
int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
u8 link_id);
|
||||
|
||||
@@ -268,21 +268,28 @@ enum hal_rx_reception_type {
|
||||
};
|
||||
|
||||
enum hal_rx_legacy_rate {
|
||||
HAL_RX_LEGACY_RATE_1_MBPS,
|
||||
HAL_RX_LEGACY_RATE_2_MBPS,
|
||||
HAL_RX_LEGACY_RATE_5_5_MBPS,
|
||||
HAL_RX_LEGACY_RATE_6_MBPS,
|
||||
HAL_RX_LEGACY_RATE_9_MBPS,
|
||||
HAL_RX_LEGACY_RATE_11_MBPS,
|
||||
HAL_RX_LEGACY_RATE_12_MBPS,
|
||||
HAL_RX_LEGACY_RATE_18_MBPS,
|
||||
HAL_RX_LEGACY_RATE_24_MBPS,
|
||||
HAL_RX_LEGACY_RATE_36_MBPS,
|
||||
HAL_RX_LEGACY_RATE_48_MBPS,
|
||||
HAL_RX_LEGACY_RATE_54_MBPS,
|
||||
HAL_RX_LEGACY_RATE_LP_1_MBPS,
|
||||
HAL_RX_LEGACY_RATE_LP_2_MBPS,
|
||||
HAL_RX_LEGACY_RATE_LP_5_5_MBPS,
|
||||
HAL_RX_LEGACY_RATE_LP_11_MBPS,
|
||||
HAL_RX_LEGACY_RATE_SP_2_MBPS,
|
||||
HAL_RX_LEGACY_RATE_SP_5_5_MBPS,
|
||||
HAL_RX_LEGACY_RATE_SP_11_MBPS,
|
||||
HAL_RX_LEGACY_RATE_INVALID,
|
||||
};
|
||||
|
||||
enum hal_rx_legacy_rates_ofdm {
|
||||
HAL_RX_LEGACY_RATE_OFDM_48_MBPS,
|
||||
HAL_RX_LEGACY_RATE_OFDM_24_MBPS,
|
||||
HAL_RX_LEGACY_RATE_OFDM_12_MBPS,
|
||||
HAL_RX_LEGACY_RATE_OFDM_6_MBPS,
|
||||
HAL_RX_LEGACY_RATE_OFDM_54_MBPS,
|
||||
HAL_RX_LEGACY_RATE_OFDM_36_MBPS,
|
||||
HAL_RX_LEGACY_RATE_OFDM_18_MBPS,
|
||||
HAL_RX_LEGACY_RATE_OFDM_9_MBPS,
|
||||
HAL_RX_LEGACY_RATE_OFDM_INVALID,
|
||||
};
|
||||
|
||||
enum hal_ring_type {
|
||||
HAL_REO_DST,
|
||||
HAL_REO_EXCEPTION,
|
||||
|
||||
@@ -164,30 +164,31 @@ static const struct ieee80211_channel ath12k_6ghz_channels[] = {
|
||||
CHAN6G(233, 7115, 0),
|
||||
};
|
||||
|
||||
#define ATH12K_MAC_RATE_A_M(bps, code) \
|
||||
{ .bitrate = (bps), .hw_value = (code),\
|
||||
.flags = IEEE80211_RATE_MANDATORY_A }
|
||||
|
||||
#define ATH12K_MAC_RATE_B(bps, code, code_short) \
|
||||
{ .bitrate = (bps), .hw_value = (code), .hw_value_short = (code_short),\
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE }
|
||||
|
||||
static struct ieee80211_rate ath12k_legacy_rates[] = {
|
||||
{ .bitrate = 10,
|
||||
.hw_value = ATH12K_HW_RATE_CCK_LP_1M },
|
||||
{ .bitrate = 20,
|
||||
.hw_value = ATH12K_HW_RATE_CCK_LP_2M,
|
||||
.hw_value_short = ATH12K_HW_RATE_CCK_SP_2M,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE },
|
||||
{ .bitrate = 55,
|
||||
.hw_value = ATH12K_HW_RATE_CCK_LP_5_5M,
|
||||
.hw_value_short = ATH12K_HW_RATE_CCK_SP_5_5M,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE },
|
||||
{ .bitrate = 110,
|
||||
.hw_value = ATH12K_HW_RATE_CCK_LP_11M,
|
||||
.hw_value_short = ATH12K_HW_RATE_CCK_SP_11M,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE },
|
||||
|
||||
{ .bitrate = 60, .hw_value = ATH12K_HW_RATE_OFDM_6M },
|
||||
{ .bitrate = 90, .hw_value = ATH12K_HW_RATE_OFDM_9M },
|
||||
{ .bitrate = 120, .hw_value = ATH12K_HW_RATE_OFDM_12M },
|
||||
{ .bitrate = 180, .hw_value = ATH12K_HW_RATE_OFDM_18M },
|
||||
{ .bitrate = 240, .hw_value = ATH12K_HW_RATE_OFDM_24M },
|
||||
{ .bitrate = 360, .hw_value = ATH12K_HW_RATE_OFDM_36M },
|
||||
{ .bitrate = 480, .hw_value = ATH12K_HW_RATE_OFDM_48M },
|
||||
{ .bitrate = 540, .hw_value = ATH12K_HW_RATE_OFDM_54M },
|
||||
ATH12K_MAC_RATE_B(20, ATH12K_HW_RATE_CCK_LP_2M,
|
||||
ATH12K_HW_RATE_CCK_SP_2M),
|
||||
ATH12K_MAC_RATE_B(55, ATH12K_HW_RATE_CCK_LP_5_5M,
|
||||
ATH12K_HW_RATE_CCK_SP_5_5M),
|
||||
ATH12K_MAC_RATE_B(110, ATH12K_HW_RATE_CCK_LP_11M,
|
||||
ATH12K_HW_RATE_CCK_SP_11M),
|
||||
ATH12K_MAC_RATE_A_M(60, ATH12K_HW_RATE_OFDM_6M),
|
||||
ATH12K_MAC_RATE_A_M(90, ATH12K_HW_RATE_OFDM_9M),
|
||||
ATH12K_MAC_RATE_A_M(120, ATH12K_HW_RATE_OFDM_12M),
|
||||
ATH12K_MAC_RATE_A_M(180, ATH12K_HW_RATE_OFDM_18M),
|
||||
ATH12K_MAC_RATE_A_M(240, ATH12K_HW_RATE_OFDM_24M),
|
||||
ATH12K_MAC_RATE_A_M(360, ATH12K_HW_RATE_OFDM_36M),
|
||||
ATH12K_MAC_RATE_A_M(480, ATH12K_HW_RATE_OFDM_48M),
|
||||
ATH12K_MAC_RATE_A_M(540, ATH12K_HW_RATE_OFDM_54M),
|
||||
};
|
||||
|
||||
static const int
|
||||
@@ -732,11 +733,17 @@ u8 ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
|
||||
if (ath12k_mac_bitrate_is_cck(rate->bitrate) != cck)
|
||||
continue;
|
||||
|
||||
if (rate->hw_value == hw_rate)
|
||||
/* To handle 802.11a PPDU type */
|
||||
if ((!cck) && (rate->hw_value == hw_rate) &&
|
||||
(rate->flags & IEEE80211_RATE_MANDATORY_A))
|
||||
return i;
|
||||
/* To handle 802.11b short PPDU type */
|
||||
else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
|
||||
rate->hw_value_short == hw_rate)
|
||||
return i;
|
||||
/* To handle 802.11b long PPDU type */
|
||||
else if (rate->hw_value == hw_rate)
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -781,7 +788,7 @@ struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
|
||||
|
||||
/* To use the arvif returned, caller must have held rcu read lock.
|
||||
*/
|
||||
WARN_ON(!rcu_read_lock_any_held());
|
||||
lockdep_assert_in_rcu_read_lock();
|
||||
arvif_iter.vdev_id = vdev_id;
|
||||
arvif_iter.ar = ar;
|
||||
|
||||
@@ -3439,7 +3446,9 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
|
||||
arg->peer_eht_mcs_count++;
|
||||
fallthrough;
|
||||
default:
|
||||
if (!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
if ((vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_MESH_POINT) &&
|
||||
!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
|
||||
bw_20 = &eht_cap->eht_mcs_nss_supp.only_20mhz;
|
||||
|
||||
@@ -3468,7 +3477,9 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
|
||||
arg->punct_bitmap = ~arvif->punct_bitmap;
|
||||
arg->eht_disable_mcs15 = link_conf->eht_disable_mcs15;
|
||||
|
||||
if (!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
if ((vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_MESH_POINT) &&
|
||||
!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
|
||||
if (bw_20->rx_tx_mcs13_max_nss)
|
||||
max_nss = max(max_nss, u8_get_bits(bw_20->rx_tx_mcs13_max_nss,
|
||||
@@ -4311,7 +4322,8 @@ static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif,
|
||||
if (info->fils_discovery.max_interval) {
|
||||
interval = info->fils_discovery.max_interval;
|
||||
|
||||
tmpl = ieee80211_get_fils_discovery_tmpl(hw, vif);
|
||||
tmpl = ieee80211_get_fils_discovery_tmpl(hw, vif,
|
||||
info->link_id);
|
||||
if (tmpl)
|
||||
ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,
|
||||
tmpl);
|
||||
@@ -4319,7 +4331,8 @@ static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif,
|
||||
unsol_bcast_probe_resp_enabled = 1;
|
||||
interval = info->unsol_bcast_probe_resp_interval;
|
||||
|
||||
tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
|
||||
tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif,
|
||||
info->link_id);
|
||||
if (tmpl)
|
||||
ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,
|
||||
tmpl);
|
||||
@@ -6784,6 +6797,8 @@ static void ath12k_mac_free_unassign_link_sta(struct ath12k_hw *ah,
|
||||
return;
|
||||
|
||||
ahsta->links_map &= ~BIT(link_id);
|
||||
ahsta->free_logical_link_idx_map |= BIT(arsta->link_idx);
|
||||
|
||||
rcu_assign_pointer(ahsta->link[link_id], NULL);
|
||||
synchronize_rcu();
|
||||
|
||||
@@ -7102,6 +7117,7 @@ static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah,
|
||||
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct ath12k_link_vif *arvif;
|
||||
int link_idx;
|
||||
|
||||
lockdep_assert_wiphy(ah->hw->wiphy);
|
||||
|
||||
@@ -7120,8 +7136,16 @@ static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah,
|
||||
|
||||
ether_addr_copy(arsta->addr, link_sta->addr);
|
||||
|
||||
/* logical index of the link sta in order of creation */
|
||||
arsta->link_idx = ahsta->num_peer++;
|
||||
if (!ahsta->free_logical_link_idx_map)
|
||||
return -ENOSPC;
|
||||
|
||||
/*
|
||||
* Allocate a logical link index by selecting the first available bit
|
||||
* from the free logical index map
|
||||
*/
|
||||
link_idx = __ffs(ahsta->free_logical_link_idx_map);
|
||||
ahsta->free_logical_link_idx_map &= ~BIT(link_idx);
|
||||
arsta->link_idx = link_idx;
|
||||
|
||||
arsta->link_id = link_id;
|
||||
ahsta->links_map |= BIT(arsta->link_id);
|
||||
@@ -7630,6 +7654,7 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
if (old_state == IEEE80211_STA_NOTEXIST &&
|
||||
new_state == IEEE80211_STA_NONE) {
|
||||
memset(ahsta, 0, sizeof(*ahsta));
|
||||
ahsta->free_logical_link_idx_map = U16_MAX;
|
||||
|
||||
arsta = &ahsta->deflink;
|
||||
|
||||
@@ -9117,10 +9142,10 @@ static int ath12k_mac_mgmt_action_frame_fill_elem_data(struct ath12k_link_vif *a
|
||||
lockdep_assert_wiphy(wiphy);
|
||||
|
||||
/* make sure category field is present */
|
||||
if (skb->len < IEEE80211_MIN_ACTION_SIZE)
|
||||
if (skb->len < IEEE80211_MIN_ACTION_SIZE(category))
|
||||
return -EINVAL;
|
||||
|
||||
remaining_len = skb->len - IEEE80211_MIN_ACTION_SIZE;
|
||||
remaining_len = skb->len - IEEE80211_MIN_ACTION_SIZE(category);
|
||||
has_protected = ieee80211_has_protected(hdr->frame_control);
|
||||
|
||||
/* In case of SW crypto and hdr protected (PMF), packet will already be encrypted,
|
||||
@@ -11110,7 +11135,7 @@ ath12k_mac_mlo_get_vdev_args(struct ath12k_link_vif *arvif,
|
||||
if (arvif == arvif_p)
|
||||
continue;
|
||||
|
||||
if (!arvif_p->is_created)
|
||||
if (!arvif_p->is_started)
|
||||
continue;
|
||||
|
||||
link_conf = wiphy_dereference(ahvif->ah->hw->wiphy,
|
||||
@@ -14792,6 +14817,10 @@ static void ath12k_mac_setup(struct ath12k *ar)
|
||||
init_completion(&ar->mlo_setup_done);
|
||||
init_completion(&ar->completed_11d_scan);
|
||||
init_completion(&ar->regd_update_completed);
|
||||
init_completion(&ar->thermal.wmi_sync);
|
||||
|
||||
ar->thermal.temperature = 0;
|
||||
ar->thermal.hwmon_dev = NULL;
|
||||
|
||||
INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work);
|
||||
wiphy_work_init(&ar->scan.vdev_clean_wk, ath12k_scan_vdev_clean_work);
|
||||
@@ -15041,6 +15070,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,
|
||||
ar->hw_link_id = pdev->hw_link_id;
|
||||
ar->pdev = pdev;
|
||||
ar->pdev_idx = pdev_idx;
|
||||
ar->radio_idx = i;
|
||||
pdev->ar = ar;
|
||||
|
||||
ag->hw_links[ar->hw_link_id].device_id = ab->device_id;
|
||||
@@ -15108,7 +15138,6 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
|
||||
if (!ab)
|
||||
continue;
|
||||
|
||||
ath12k_debugfs_pdev_create(ab);
|
||||
ath12k_mac_set_device_defaults(ab);
|
||||
total_radio += ab->num_radios;
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ static void ath12k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
|
||||
struct ath12k_p2p_noa_arg *arg = data;
|
||||
struct ath12k_link_vif *arvif;
|
||||
|
||||
WARN_ON(!rcu_read_lock_any_held());
|
||||
lockdep_assert_in_rcu_read_lock();
|
||||
arvif = &ahvif->deflink;
|
||||
if (!arvif->is_created || arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id)
|
||||
return;
|
||||
|
||||
@@ -3339,7 +3339,7 @@ static int ath12k_qmi_aux_uc_load(struct ath12k_base *ab)
|
||||
goto out;
|
||||
}
|
||||
|
||||
aux_uc_mem->total_size = aux_uc_len;
|
||||
aux_uc_mem->total_size = aux_uc_len;
|
||||
|
||||
copy:
|
||||
memcpy(aux_uc_mem->vaddr, aux_uc_data, aux_uc_len);
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/thermal.h>
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
||||
static ssize_t ath12k_thermal_temp_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ath12k *ar = dev_get_drvdata(dev);
|
||||
unsigned long time_left;
|
||||
int ret, temperature;
|
||||
|
||||
guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
|
||||
|
||||
if (ar->ah->state != ATH12K_HW_STATE_ON)
|
||||
return -ENETDOWN;
|
||||
|
||||
reinit_completion(&ar->thermal.wmi_sync);
|
||||
ret = ath12k_wmi_send_pdev_temperature_cmd(ar);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to read temperature %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
|
||||
return -ESHUTDOWN;
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->thermal.wmi_sync,
|
||||
ATH12K_THERMAL_SYNC_TIMEOUT_HZ);
|
||||
if (!time_left) {
|
||||
ath12k_warn(ar->ab, "failed to synchronize thermal read\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
temperature = ar->thermal.temperature;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* display in millidegree celsius */
|
||||
return sysfs_emit(buf, "%d\n", temperature * 1000);
|
||||
}
|
||||
|
||||
void ath12k_thermal_event_temperature(struct ath12k *ar, int temperature)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->thermal.temperature = temperature;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
complete_all(&ar->thermal.wmi_sync);
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_input, ath12k_thermal_temp, 0);
|
||||
|
||||
static struct attribute *ath12k_hwmon_attrs[] = {
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ath12k_hwmon);
|
||||
|
||||
int ath12k_thermal_register(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k *ar;
|
||||
int i, j, ret;
|
||||
|
||||
if (!IS_REACHABLE(CONFIG_HWMON))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
ar = ab->pdevs[i].ar;
|
||||
if (!ar)
|
||||
continue;
|
||||
|
||||
ar->thermal.hwmon_dev =
|
||||
hwmon_device_register_with_groups(&ar->ah->hw->wiphy->dev,
|
||||
"ath12k_hwmon", ar,
|
||||
ath12k_hwmon_groups);
|
||||
if (IS_ERR(ar->thermal.hwmon_dev)) {
|
||||
ret = PTR_ERR(ar->thermal.hwmon_dev);
|
||||
ar->thermal.hwmon_dev = NULL;
|
||||
ath12k_err(ar->ab, "failed to register hwmon device: %d\n",
|
||||
ret);
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
ar = ab->pdevs[j].ar;
|
||||
if (!ar)
|
||||
continue;
|
||||
|
||||
hwmon_device_unregister(ar->thermal.hwmon_dev);
|
||||
ar->thermal.hwmon_dev = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath12k_thermal_unregister(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k *ar;
|
||||
int i;
|
||||
|
||||
if (!IS_REACHABLE(CONFIG_HWMON))
|
||||
return;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
ar = ab->pdevs[i].ar;
|
||||
if (!ar)
|
||||
continue;
|
||||
|
||||
if (ar->thermal.hwmon_dev) {
|
||||
hwmon_device_unregister(ar->thermal.hwmon_dev);
|
||||
ar->thermal.hwmon_dev = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#ifndef _ATH12K_THERMAL_
|
||||
#define _ATH12K_THERMAL_
|
||||
|
||||
#define ATH12K_THERMAL_SYNC_TIMEOUT_HZ (5 * HZ)
|
||||
|
||||
struct ath12k_thermal {
|
||||
struct completion wmi_sync;
|
||||
|
||||
/* temperature value in Celsius degree protected by data_lock. */
|
||||
int temperature;
|
||||
struct device *hwmon_dev;
|
||||
};
|
||||
|
||||
#if IS_REACHABLE(CONFIG_THERMAL)
|
||||
int ath12k_thermal_register(struct ath12k_base *ab);
|
||||
void ath12k_thermal_unregister(struct ath12k_base *ab);
|
||||
void ath12k_thermal_event_temperature(struct ath12k *ar, int temperature);
|
||||
#else
|
||||
static inline int ath12k_thermal_register(struct ath12k_base *ab)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath12k_thermal_unregister(struct ath12k_base *ab)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath12k_thermal_event_temperature(struct ath12k *ar,
|
||||
int temperature)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* _ATH12K_THERMAL_ */
|
||||
@@ -19,6 +19,9 @@ static const struct of_device_id ath12k_wifi7_ahb_of_match[] = {
|
||||
{ .compatible = "qcom,ipq5332-wifi",
|
||||
.data = (void *)ATH12K_HW_IPQ5332_HW10,
|
||||
},
|
||||
{ .compatible = "qcom,ipq5424-wifi",
|
||||
.data = (void *)ATH12K_HW_IPQ5424_HW10,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -38,6 +41,11 @@ static int ath12k_wifi7_ahb_probe(struct platform_device *pdev)
|
||||
switch (hw_rev) {
|
||||
case ATH12K_HW_IPQ5332_HW10:
|
||||
ab_ahb->userpd_id = ATH12K_IPQ5332_USERPD_ID;
|
||||
ab_ahb->scm_auth_enabled = true;
|
||||
break;
|
||||
case ATH12K_HW_IPQ5424_HW10:
|
||||
ab_ahb->userpd_id = ATH12K_IPQ5332_USERPD_ID;
|
||||
ab_ahb->scm_auth_enabled = false;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -405,6 +405,42 @@ ath12k_wifi7_dp_mon_hal_rx_parse_user_info(const struct hal_receive_user_info *r
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline u8
|
||||
ath12k_wifi7_hal_mon_map_legacy_rate_to_hw_rate(u8 rate)
|
||||
{
|
||||
u8 ath12k_rate;
|
||||
|
||||
/* Map hal_rx_legacy_rate to ath12k_hw_rate_cck */
|
||||
switch (rate) {
|
||||
case HAL_RX_LEGACY_RATE_LP_1_MBPS:
|
||||
ath12k_rate = ATH12K_HW_RATE_CCK_LP_1M;
|
||||
break;
|
||||
case HAL_RX_LEGACY_RATE_LP_2_MBPS:
|
||||
ath12k_rate = ATH12K_HW_RATE_CCK_LP_2M;
|
||||
break;
|
||||
case HAL_RX_LEGACY_RATE_LP_5_5_MBPS:
|
||||
ath12k_rate = ATH12K_HW_RATE_CCK_LP_5_5M;
|
||||
break;
|
||||
case HAL_RX_LEGACY_RATE_LP_11_MBPS:
|
||||
ath12k_rate = ATH12K_HW_RATE_CCK_LP_11M;
|
||||
break;
|
||||
case HAL_RX_LEGACY_RATE_SP_2_MBPS:
|
||||
ath12k_rate = ATH12K_HW_RATE_CCK_SP_2M;
|
||||
break;
|
||||
case HAL_RX_LEGACY_RATE_SP_5_5_MBPS:
|
||||
ath12k_rate = ATH12K_HW_RATE_CCK_SP_5_5M;
|
||||
break;
|
||||
case HAL_RX_LEGACY_RATE_SP_11_MBPS:
|
||||
ath12k_rate = ATH12K_HW_RATE_CCK_SP_11M;
|
||||
break;
|
||||
default:
|
||||
ath12k_rate = rate;
|
||||
break;
|
||||
}
|
||||
|
||||
return ath12k_rate;
|
||||
}
|
||||
|
||||
static void
|
||||
ath12k_wifi7_dp_mon_parse_l_sig_b(const struct hal_rx_lsig_b_info *lsigb,
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info)
|
||||
@@ -415,25 +451,32 @@ ath12k_wifi7_dp_mon_parse_l_sig_b(const struct hal_rx_lsig_b_info *lsigb,
|
||||
rate = u32_get_bits(info0, HAL_RX_LSIG_B_INFO_INFO0_RATE);
|
||||
switch (rate) {
|
||||
case 1:
|
||||
rate = HAL_RX_LEGACY_RATE_1_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_LP_1_MBPS;
|
||||
break;
|
||||
case 2:
|
||||
case 5:
|
||||
rate = HAL_RX_LEGACY_RATE_2_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_LP_2_MBPS;
|
||||
break;
|
||||
case 3:
|
||||
case 6:
|
||||
rate = HAL_RX_LEGACY_RATE_5_5_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_LP_5_5_MBPS;
|
||||
break;
|
||||
case 4:
|
||||
rate = HAL_RX_LEGACY_RATE_LP_11_MBPS;
|
||||
break;
|
||||
case 5:
|
||||
rate = HAL_RX_LEGACY_RATE_SP_2_MBPS;
|
||||
break;
|
||||
case 6:
|
||||
rate = HAL_RX_LEGACY_RATE_SP_5_5_MBPS;
|
||||
break;
|
||||
case 7:
|
||||
rate = HAL_RX_LEGACY_RATE_11_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_SP_11_MBPS;
|
||||
break;
|
||||
default:
|
||||
rate = HAL_RX_LEGACY_RATE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
ppdu_info->rate = rate;
|
||||
ppdu_info->rate = ath12k_wifi7_hal_mon_map_legacy_rate_to_hw_rate(rate);
|
||||
ppdu_info->cck_flag = 1;
|
||||
}
|
||||
|
||||
@@ -447,31 +490,32 @@ ath12k_wifi7_dp_mon_parse_l_sig_a(const struct hal_rx_lsig_a_info *lsiga,
|
||||
rate = u32_get_bits(info0, HAL_RX_LSIG_A_INFO_INFO0_RATE);
|
||||
switch (rate) {
|
||||
case 8:
|
||||
rate = HAL_RX_LEGACY_RATE_48_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_OFDM_48_MBPS;
|
||||
break;
|
||||
case 9:
|
||||
rate = HAL_RX_LEGACY_RATE_24_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_OFDM_24_MBPS;
|
||||
break;
|
||||
case 10:
|
||||
rate = HAL_RX_LEGACY_RATE_12_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_OFDM_12_MBPS;
|
||||
break;
|
||||
case 11:
|
||||
rate = HAL_RX_LEGACY_RATE_6_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_OFDM_6_MBPS;
|
||||
break;
|
||||
case 12:
|
||||
rate = HAL_RX_LEGACY_RATE_54_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_OFDM_54_MBPS;
|
||||
break;
|
||||
case 13:
|
||||
rate = HAL_RX_LEGACY_RATE_36_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_OFDM_36_MBPS;
|
||||
break;
|
||||
case 14:
|
||||
rate = HAL_RX_LEGACY_RATE_18_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_OFDM_18_MBPS;
|
||||
break;
|
||||
case 15:
|
||||
rate = HAL_RX_LEGACY_RATE_9_MBPS;
|
||||
rate = HAL_RX_LEGACY_RATE_OFDM_9_MBPS;
|
||||
break;
|
||||
default:
|
||||
rate = HAL_RX_LEGACY_RATE_INVALID;
|
||||
rate = HAL_RX_LEGACY_RATE_OFDM_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
ppdu_info->rate = rate;
|
||||
|
||||
@@ -325,7 +325,6 @@ static void ath12k_wifi7_dp_rx_h_csum_offload(struct sk_buff *msdu,
|
||||
|
||||
static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc *rx_desc,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
{
|
||||
struct ath12k_skb_rxcb *rxcb;
|
||||
@@ -388,8 +387,7 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
|
||||
}
|
||||
|
||||
ath12k_wifi7_dp_rx_h_csum_offload(msdu, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, rx_desc,
|
||||
enctype, is_decrypted, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, enctype, is_decrypted, rx_info);
|
||||
|
||||
if (!is_decrypted || rx_info->is_mcbc)
|
||||
return;
|
||||
@@ -549,14 +547,14 @@ static int ath12k_wifi7_dp_rx_process_msdu(struct ath12k_pdev_dp *dp_pdev,
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, rx_desc, msdu,
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, msdu,
|
||||
rx_info))) {
|
||||
ret = -EINVAL;
|
||||
goto free_out;
|
||||
}
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_desc, rx_info);
|
||||
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
|
||||
rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
|
||||
|
||||
@@ -985,7 +983,7 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
|
||||
struct ieee80211_key_conf *key_conf;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u8 mic[IEEE80211_CCMP_MIC_LEN];
|
||||
int head_len, tail_len, ret;
|
||||
int head_len, tail_len;
|
||||
size_t data_len;
|
||||
u32 hdr_len, hal_rx_desc_sz = hal->hal_desc_sz;
|
||||
u8 *key, *data;
|
||||
@@ -1013,9 +1011,8 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
|
||||
data_len = msdu->len - head_len - tail_len;
|
||||
key = &key_conf->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
|
||||
|
||||
ret = ath12k_dp_rx_h_michael_mic(peer->tfm_mmic, key, hdr, data,
|
||||
data_len, mic);
|
||||
if (ret || memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
|
||||
michael_mic(key, hdr, data, data_len, mic);
|
||||
if (memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
|
||||
goto mic_fail;
|
||||
|
||||
return 0;
|
||||
@@ -1030,13 +1027,13 @@ mic_fail:
|
||||
RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED;
|
||||
skb_pull(msdu, hal_rx_desc_sz);
|
||||
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, rx_desc, msdu,
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, msdu,
|
||||
rx_info)))
|
||||
return -EINVAL;
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, rx_desc,
|
||||
HAL_ENCRYPT_TYPE_TKIP_MIC, true, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, HAL_ENCRYPT_TYPE_TKIP_MIC, true,
|
||||
rx_info);
|
||||
ieee80211_rx(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1588,7 +1585,6 @@ static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
|
||||
struct ath12k_dp *dp = dp_pdev->dp;
|
||||
struct ath12k_base *ab = dp->ab;
|
||||
u16 msdu_len = rx_info->msdu_len;
|
||||
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
|
||||
u8 l3pad_bytes = rx_info->l3_pad_bytes;
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
u32 hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
|
||||
@@ -1632,11 +1628,11 @@ static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
|
||||
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
|
||||
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
|
||||
}
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, desc, msdu, rx_info)))
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, msdu, rx_info)))
|
||||
return -EINVAL;
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, desc, rx_info);
|
||||
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
|
||||
rxcb->tid = rx_info->tid;
|
||||
|
||||
@@ -1673,7 +1669,7 @@ static bool ath12k_wifi7_dp_rx_h_tkip_mic_err(struct ath12k_pdev_dp *dp_pdev,
|
||||
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
|
||||
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
|
||||
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, desc, msdu, rx_info)))
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, msdu, rx_info)))
|
||||
return true;
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
@@ -1681,8 +1677,8 @@ static bool ath12k_wifi7_dp_rx_h_tkip_mic_err(struct ath12k_pdev_dp *dp_pdev,
|
||||
rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
|
||||
RX_FLAG_DECRYPTED);
|
||||
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, desc,
|
||||
HAL_ENCRYPT_TYPE_TKIP_MIC, false, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, HAL_ENCRYPT_TYPE_TKIP_MIC, false,
|
||||
rx_info);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,13 @@ static const struct ath12k_hw_version_map ath12k_wifi7_hw_ver_map[] = {
|
||||
.hal_params = &ath12k_hw_hal_params_wcn7850,
|
||||
.hw_regs = &qcc2072_regs,
|
||||
},
|
||||
[ATH12K_HW_IPQ5424_HW10] = {
|
||||
.hal_ops = &hal_qcn9274_ops,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274_compact),
|
||||
.tcl_to_wbm_rbm_map = ath12k_hal_tcl_to_wbm_rbm_map_qcn9274,
|
||||
.hal_params = &ath12k_hw_hal_params_ipq5332,
|
||||
.hw_regs = &ipq5424_regs,
|
||||
},
|
||||
};
|
||||
|
||||
int ath12k_wifi7_hal_init(struct ath12k_base *ab)
|
||||
|
||||
@@ -364,6 +364,9 @@
|
||||
#define HAL_IPQ5332_CE_WFSS_REG_BASE 0x740000
|
||||
#define HAL_IPQ5332_CE_SIZE 0x100000
|
||||
|
||||
#define HAL_IPQ5424_CE_WFSS_REG_BASE 0x200000
|
||||
#define HAL_IPQ5424_CE_SIZE 0x100000
|
||||
|
||||
#define HAL_RX_MAX_BA_WINDOW 256
|
||||
|
||||
#define HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC (100 * 1000)
|
||||
|
||||
@@ -484,6 +484,94 @@ const struct ath12k_hw_regs ipq5332_regs = {
|
||||
HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
};
|
||||
|
||||
const struct ath12k_hw_regs ipq5424_regs = {
|
||||
/* SW2TCL(x) R0 ring configuration address */
|
||||
.tcl1_ring_id = 0x00000918,
|
||||
.tcl1_ring_misc = 0x00000920,
|
||||
.tcl1_ring_tp_addr_lsb = 0x0000092c,
|
||||
.tcl1_ring_tp_addr_msb = 0x00000930,
|
||||
.tcl1_ring_consumer_int_setup_ix0 = 0x00000940,
|
||||
.tcl1_ring_consumer_int_setup_ix1 = 0x00000944,
|
||||
.tcl1_ring_msi1_base_lsb = 0x00000958,
|
||||
.tcl1_ring_msi1_base_msb = 0x0000095c,
|
||||
.tcl1_ring_base_lsb = 0x00000910,
|
||||
.tcl1_ring_base_msb = 0x00000914,
|
||||
.tcl1_ring_msi1_data = 0x00000960,
|
||||
.tcl2_ring_base_lsb = 0x00000988,
|
||||
.tcl_ring_base_lsb = 0x00000b68,
|
||||
|
||||
/* TCL STATUS ring address */
|
||||
.tcl_status_ring_base_lsb = 0x00000d48,
|
||||
|
||||
/* REO DEST ring address */
|
||||
.reo2_ring_base = 0x00000578,
|
||||
.reo1_misc_ctrl_addr = 0x00000b9c,
|
||||
.reo1_sw_cookie_cfg0 = 0x0000006c,
|
||||
.reo1_sw_cookie_cfg1 = 0x00000070,
|
||||
.reo1_qdesc_lut_base0 = 0x00000074,
|
||||
.reo1_qdesc_lut_base1 = 0x00000078,
|
||||
.reo1_ring_base_lsb = 0x00000500,
|
||||
.reo1_ring_base_msb = 0x00000504,
|
||||
.reo1_ring_id = 0x00000508,
|
||||
.reo1_ring_misc = 0x00000510,
|
||||
.reo1_ring_hp_addr_lsb = 0x00000514,
|
||||
.reo1_ring_hp_addr_msb = 0x00000518,
|
||||
.reo1_ring_producer_int_setup = 0x00000524,
|
||||
.reo1_ring_msi1_base_lsb = 0x00000548,
|
||||
.reo1_ring_msi1_base_msb = 0x0000054C,
|
||||
.reo1_ring_msi1_data = 0x00000550,
|
||||
.reo1_aging_thres_ix0 = 0x00000B28,
|
||||
.reo1_aging_thres_ix1 = 0x00000B2C,
|
||||
.reo1_aging_thres_ix2 = 0x00000B30,
|
||||
.reo1_aging_thres_ix3 = 0x00000B34,
|
||||
|
||||
/* REO Exception ring address */
|
||||
.reo2_sw0_ring_base = 0x000008c0,
|
||||
|
||||
/* REO Reinject ring address */
|
||||
.sw2reo_ring_base = 0x00000320,
|
||||
.sw2reo1_ring_base = 0x00000398,
|
||||
|
||||
/* REO cmd ring address */
|
||||
.reo_cmd_ring_base = 0x000002A8,
|
||||
|
||||
/* REO status ring address */
|
||||
.reo_status_ring_base = 0x00000aa0,
|
||||
|
||||
/* WBM idle link ring address */
|
||||
.wbm_idle_ring_base_lsb = 0x00000d3c,
|
||||
.wbm_idle_ring_misc_addr = 0x00000d4c,
|
||||
.wbm_r0_idle_list_cntl_addr = 0x00000240,
|
||||
.wbm_r0_idle_list_size_addr = 0x00000244,
|
||||
.wbm_scattered_ring_base_lsb = 0x00000250,
|
||||
.wbm_scattered_ring_base_msb = 0x00000254,
|
||||
.wbm_scattered_desc_head_info_ix0 = 0x00000260,
|
||||
.wbm_scattered_desc_head_info_ix1 = 0x00000264,
|
||||
.wbm_scattered_desc_tail_info_ix0 = 0x00000270,
|
||||
.wbm_scattered_desc_tail_info_ix1 = 0x00000274,
|
||||
.wbm_scattered_desc_ptr_hp_addr = 0x0000027c,
|
||||
|
||||
/* SW2WBM release ring address */
|
||||
.wbm_sw_release_ring_base_lsb = 0x0000037c,
|
||||
|
||||
/* WBM2SW release ring address */
|
||||
.wbm0_release_ring_base_lsb = 0x00000e08,
|
||||
.wbm1_release_ring_base_lsb = 0x00000e80,
|
||||
|
||||
/* PPE release ring address */
|
||||
.ppe_rel_ring_base = 0x0000046c,
|
||||
|
||||
/* CE address */
|
||||
.umac_ce0_src_reg_base = 0x00200000 -
|
||||
HAL_IPQ5424_CE_WFSS_REG_BASE,
|
||||
.umac_ce0_dest_reg_base = 0x00201000 -
|
||||
HAL_IPQ5424_CE_WFSS_REG_BASE,
|
||||
.umac_ce1_src_reg_base = 0x00202000 -
|
||||
HAL_IPQ5424_CE_WFSS_REG_BASE,
|
||||
.umac_ce1_dest_reg_base = 0x00203000 -
|
||||
HAL_IPQ5424_CE_WFSS_REG_BASE,
|
||||
};
|
||||
|
||||
static inline
|
||||
bool ath12k_hal_rx_desc_get_first_msdu_qcn9274(struct hal_rx_desc *desc)
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@ extern const struct hal_ops hal_qcn9274_ops;
|
||||
extern const struct ath12k_hw_regs qcn9274_v1_regs;
|
||||
extern const struct ath12k_hw_regs qcn9274_v2_regs;
|
||||
extern const struct ath12k_hw_regs ipq5332_regs;
|
||||
extern const struct ath12k_hw_regs ipq5424_regs;
|
||||
extern const struct ath12k_hal_tcl_to_wbm_rbm_map
|
||||
ath12k_hal_tcl_to_wbm_rbm_map_qcn9274[DP_TCL_NUM_RING_MAX];
|
||||
extern const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274;
|
||||
|
||||
@@ -104,7 +104,7 @@ static bool ath12k_is_addba_resp_action_code(struct ieee80211_mgmt *mgmt)
|
||||
if (mgmt->u.action.category != WLAN_CATEGORY_BACK)
|
||||
return false;
|
||||
|
||||
if (mgmt->u.action.u.addba_resp.action_code != WLAN_ACTION_ADDBA_RESP)
|
||||
if (mgmt->u.action.action_code != WLAN_ACTION_ADDBA_RESP)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -329,9 +329,15 @@ static const struct ath12k_hw_ring_mask ath12k_wifi7_hw_ring_mask_wcn7850 = {
|
||||
};
|
||||
|
||||
static const struct ce_ie_addr ath12k_wifi7_ce_ie_addr_ipq5332 = {
|
||||
.ie1_reg_addr = CE_HOST_IE_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.ie2_reg_addr = CE_HOST_IE_2_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.ie3_reg_addr = CE_HOST_IE_3_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.ie1_reg_addr = CE_HOST_IPQ5332_IE_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.ie2_reg_addr = CE_HOST_IPQ5332_IE_2_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.ie3_reg_addr = CE_HOST_IPQ5332_IE_3_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
};
|
||||
|
||||
static const struct ce_ie_addr ath12k_wifi7_ce_ie_addr_ipq5424 = {
|
||||
.ie1_reg_addr = CE_HOST_IPQ5424_IE_ADDRESS - HAL_IPQ5424_CE_WFSS_REG_BASE,
|
||||
.ie2_reg_addr = CE_HOST_IPQ5424_IE_2_ADDRESS - HAL_IPQ5424_CE_WFSS_REG_BASE,
|
||||
.ie3_reg_addr = CE_HOST_IPQ5424_IE_3_ADDRESS - HAL_IPQ5424_CE_WFSS_REG_BASE,
|
||||
};
|
||||
|
||||
static const struct ce_remap ath12k_wifi7_ce_remap_ipq5332 = {
|
||||
@@ -340,6 +346,12 @@ static const struct ce_remap ath12k_wifi7_ce_remap_ipq5332 = {
|
||||
.cmem_offset = HAL_SEQ_WCSS_CMEM_OFFSET,
|
||||
};
|
||||
|
||||
static const struct ce_remap ath12k_wifi7_ce_remap_ipq5424 = {
|
||||
.base = HAL_IPQ5424_CE_WFSS_REG_BASE,
|
||||
.size = HAL_IPQ5424_CE_SIZE,
|
||||
.cmem_offset = HAL_SEQ_WCSS_CMEM_OFFSET,
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
||||
{
|
||||
.name = "qcn9274 hw1.0",
|
||||
@@ -617,7 +629,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
||||
ath12k_wifi7_target_service_to_ce_map_wlan_ipq5332,
|
||||
.svc_to_ce_map_len = 18,
|
||||
|
||||
.rxdma1_enable = false,
|
||||
.rxdma1_enable = true,
|
||||
.num_rxdma_per_pdev = 1,
|
||||
.num_rxdma_dst_ring = 0,
|
||||
.rx_mac_buf_ring = false,
|
||||
@@ -626,7 +638,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT),
|
||||
.supports_monitor = false,
|
||||
.supports_monitor = true,
|
||||
|
||||
.idle_ps = false,
|
||||
.download_calib = true,
|
||||
@@ -753,6 +765,85 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
||||
|
||||
.dp_primary_link_only = false,
|
||||
},
|
||||
{
|
||||
.name = "ipq5424 hw1.0",
|
||||
.hw_rev = ATH12K_HW_IPQ5424_HW10,
|
||||
.fw = {
|
||||
.dir = "IPQ5424/hw1.0",
|
||||
.board_size = 256 * 1024,
|
||||
.cal_offset = 128 * 1024,
|
||||
.m3_loader = ath12k_m3_fw_loader_remoteproc,
|
||||
.download_aux_ucode = false,
|
||||
},
|
||||
.max_radios = 1,
|
||||
.single_pdev_only = false,
|
||||
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,
|
||||
.internal_sleep_clock = false,
|
||||
|
||||
.hw_ops = &qcn9274_ops,
|
||||
.ring_mask = &ath12k_wifi7_hw_ring_mask_ipq5332,
|
||||
|
||||
.host_ce_config = ath12k_wifi7_host_ce_config_ipq5332,
|
||||
.ce_count = 12,
|
||||
.target_ce_config = ath12k_wifi7_target_ce_config_wlan_ipq5332,
|
||||
.target_ce_count = 12,
|
||||
.svc_to_ce_map =
|
||||
ath12k_wifi7_target_service_to_ce_map_wlan_ipq5332,
|
||||
.svc_to_ce_map_len = 18,
|
||||
|
||||
.rxdma1_enable = true,
|
||||
.num_rxdma_per_pdev = 1,
|
||||
.num_rxdma_dst_ring = 0,
|
||||
.rx_mac_buf_ring = false,
|
||||
.vdev_start_delay = false,
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT),
|
||||
.supports_monitor = true,
|
||||
|
||||
.idle_ps = false,
|
||||
.download_calib = true,
|
||||
.supports_suspend = false,
|
||||
.tcl_ring_retry = true,
|
||||
.reoq_lut_support = false,
|
||||
.supports_shadow_regs = false,
|
||||
|
||||
.num_tcl_banks = 48,
|
||||
.max_tx_ring = 4,
|
||||
|
||||
.mhi_config = NULL,
|
||||
|
||||
.wmi_init = &ath12k_wifi7_wmi_init_qcn9274,
|
||||
|
||||
.qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
|
||||
|
||||
.rfkill_pin = 0,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 0,
|
||||
|
||||
.rddm_size = 0,
|
||||
|
||||
.def_num_link = 0,
|
||||
.max_mlo_peer = 256,
|
||||
|
||||
.otp_board_id_register = 0,
|
||||
|
||||
.supports_sta_ps = false,
|
||||
|
||||
.acpi_guid = NULL,
|
||||
.supports_dynamic_smps_6ghz = false,
|
||||
.iova_mask = 0,
|
||||
.supports_aspm = false,
|
||||
|
||||
.ce_ie_addr = &ath12k_wifi7_ce_ie_addr_ipq5424,
|
||||
.ce_remap = &ath12k_wifi7_ce_remap_ipq5424,
|
||||
.bdf_addr_offset = 0x940000,
|
||||
|
||||
.current_cc_support = false,
|
||||
|
||||
.dp_primary_link_only = true,
|
||||
},
|
||||
};
|
||||
|
||||
/* Note: called under rcu_read_lock() */
|
||||
|
||||
@@ -6778,31 +6778,6 @@ static int ath12k_pull_peer_assoc_conf_ev(struct ath12k_base *ab, struct sk_buff
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ath12k_pull_pdev_temp_ev(struct ath12k_base *ab, struct sk_buff *skb,
|
||||
const struct wmi_pdev_temperature_event *ev)
|
||||
{
|
||||
const void **tb;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT];
|
||||
if (!ev) {
|
||||
ath12k_warn(ab, "failed to fetch pdev temp ev");
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath12k_wmi_op_ep_tx_credits(struct ath12k_base *ab)
|
||||
{
|
||||
/* try to send pending beacons first. they take priority */
|
||||
@@ -8801,25 +8776,45 @@ static void
|
||||
ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct wmi_pdev_temperature_event *ev;
|
||||
struct ath12k *ar;
|
||||
struct wmi_pdev_temperature_event ev = {};
|
||||
const void **tb;
|
||||
int temp;
|
||||
u32 pdev_id;
|
||||
|
||||
if (ath12k_pull_pdev_temp_ev(ab, skb, &ev) != 0) {
|
||||
ath12k_warn(ab, "failed to extract pdev temperature event");
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ath12k_warn(ab, "failed to parse tlv: %ld\n", PTR_ERR(tb));
|
||||
return;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT];
|
||||
if (!ev) {
|
||||
ath12k_warn(ab, "failed to fetch pdev temp ev\n");
|
||||
kfree(tb);
|
||||
return;
|
||||
}
|
||||
|
||||
temp = a_sle32_to_cpu(ev->temp);
|
||||
pdev_id = le32_to_cpu(ev->pdev_id);
|
||||
|
||||
kfree(tb);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI,
|
||||
"pdev temperature ev temp %d pdev_id %d\n", ev.temp, ev.pdev_id);
|
||||
"pdev temperature ev temp %d pdev_id %u\n",
|
||||
temp, pdev_id);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, le32_to_cpu(ev.pdev_id));
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id);
|
||||
if (!ar) {
|
||||
ath12k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev.pdev_id);
|
||||
ath12k_warn(ab, "invalid pdev id %u in pdev temperature ev\n",
|
||||
pdev_id);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ath12k_thermal_event_temperature(ar, temp);
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@@ -9784,7 +9779,7 @@ static void
|
||||
ath12k_wmi_rssi_dbm_conversion_params_info_event(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath12k_wmi_rssi_dbm_conv_info_arg rssi_info;
|
||||
struct ath12k_wmi_rssi_dbm_conv_info_arg rssi_info = {};
|
||||
struct ath12k *ar;
|
||||
s32 noise_floor;
|
||||
u32 pdev_id;
|
||||
@@ -10023,50 +10018,46 @@ static int ath12k_connect_pdev_htc_service(struct ath12k_base *ab,
|
||||
|
||||
static int
|
||||
ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,
|
||||
struct wmi_unit_test_cmd ut_cmd,
|
||||
u32 *test_args)
|
||||
const struct wmi_unit_test_arg *ut)
|
||||
{
|
||||
struct ath12k_wmi_pdev *wmi = ar->wmi;
|
||||
struct wmi_unit_test_cmd *cmd;
|
||||
int buf_len, arg_len;
|
||||
struct sk_buff *skb;
|
||||
struct wmi_tlv *tlv;
|
||||
__le32 *ut_cmd_args;
|
||||
void *ptr;
|
||||
u32 *ut_cmd_args;
|
||||
int buf_len, arg_len;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
arg_len = sizeof(u32) * le32_to_cpu(ut_cmd.num_args);
|
||||
buf_len = sizeof(ut_cmd) + arg_len + TLV_HDR_SIZE;
|
||||
arg_len = sizeof(*ut_cmd_args) * ut->num_args;
|
||||
buf_len = sizeof(*cmd) + arg_len + TLV_HDR_SIZE;
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, buf_len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_unit_test_cmd *)skb->data;
|
||||
ptr = skb->data;
|
||||
cmd = ptr;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_UNIT_TEST_CMD,
|
||||
sizeof(ut_cmd));
|
||||
|
||||
cmd->vdev_id = ut_cmd.vdev_id;
|
||||
cmd->module_id = ut_cmd.module_id;
|
||||
cmd->num_args = ut_cmd.num_args;
|
||||
cmd->diag_token = ut_cmd.diag_token;
|
||||
|
||||
ptr = skb->data + sizeof(ut_cmd);
|
||||
sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(ut->vdev_id);
|
||||
cmd->module_id = cpu_to_le32(ut->module_id);
|
||||
cmd->num_args = cpu_to_le32(ut->num_args);
|
||||
cmd->diag_token = cpu_to_le32(ut->diag_token);
|
||||
|
||||
ptr += sizeof(*cmd);
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, arg_len);
|
||||
|
||||
ptr += TLV_HDR_SIZE;
|
||||
|
||||
ut_cmd_args = ptr;
|
||||
for (i = 0; i < le32_to_cpu(ut_cmd.num_args); i++)
|
||||
ut_cmd_args[i] = test_args[i];
|
||||
for (i = 0; i < ut->num_args; i++)
|
||||
ut_cmd_args[i] = cpu_to_le32(ut->args[i]);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
|
||||
"WMI unit test : module %d vdev %d n_args %d token %d\n",
|
||||
cmd->module_id, cmd->vdev_id, cmd->num_args,
|
||||
cmd->diag_token);
|
||||
ut->module_id, ut->vdev_id, ut->num_args, ut->diag_token);
|
||||
|
||||
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_UNIT_TEST_CMDID);
|
||||
|
||||
@@ -10082,8 +10073,7 @@ ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,
|
||||
int ath12k_wmi_simulate_radar(struct ath12k *ar)
|
||||
{
|
||||
struct ath12k_link_vif *arvif;
|
||||
u32 dfs_args[DFS_MAX_TEST_ARGS];
|
||||
struct wmi_unit_test_cmd wmi_ut;
|
||||
struct wmi_unit_test_arg wmi_ut = {};
|
||||
bool arvif_found = false;
|
||||
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
@@ -10096,22 +10086,23 @@ int ath12k_wmi_simulate_radar(struct ath12k *ar)
|
||||
if (!arvif_found)
|
||||
return -EINVAL;
|
||||
|
||||
dfs_args[DFS_TEST_CMDID] = 0;
|
||||
dfs_args[DFS_TEST_PDEV_ID] = ar->pdev->pdev_id;
|
||||
/* Currently we could pass segment_id(b0 - b1), chirp(b2)
|
||||
wmi_ut.args[DFS_TEST_CMDID] = 0;
|
||||
wmi_ut.args[DFS_TEST_PDEV_ID] = ar->pdev->pdev_id;
|
||||
/*
|
||||
* Currently we could pass segment_id(b0 - b1), chirp(b2)
|
||||
* freq offset (b3 - b10) to unit test. For simulation
|
||||
* purpose this can be set to 0 which is valid.
|
||||
*/
|
||||
dfs_args[DFS_TEST_RADAR_PARAM] = 0;
|
||||
wmi_ut.args[DFS_TEST_RADAR_PARAM] = 0;
|
||||
|
||||
wmi_ut.vdev_id = cpu_to_le32(arvif->vdev_id);
|
||||
wmi_ut.module_id = cpu_to_le32(DFS_UNIT_TEST_MODULE);
|
||||
wmi_ut.num_args = cpu_to_le32(DFS_MAX_TEST_ARGS);
|
||||
wmi_ut.diag_token = cpu_to_le32(DFS_UNIT_TEST_TOKEN);
|
||||
wmi_ut.vdev_id = arvif->vdev_id;
|
||||
wmi_ut.module_id = DFS_UNIT_TEST_MODULE;
|
||||
wmi_ut.num_args = DFS_MAX_TEST_ARGS;
|
||||
wmi_ut.diag_token = DFS_UNIT_TEST_TOKEN;
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Triggering Radar Simulation\n");
|
||||
|
||||
return ath12k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args);
|
||||
return ath12k_wmi_send_unit_test_cmd(ar, &wmi_ut);
|
||||
}
|
||||
|
||||
int ath12k_wmi_send_tpc_stats_request(struct ath12k *ar,
|
||||
@@ -10261,7 +10252,7 @@ int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar, struct wmi_hw_data_filter_a
|
||||
{
|
||||
struct wmi_hw_data_filter_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10285,7 +10276,13 @@ int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar, struct wmi_hw_data_filter_a
|
||||
"wmi hw data filter enable %d filter_bitmap 0x%x\n",
|
||||
arg->enable, arg->hw_filter_bitmap);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_HW_DATA_FILTER_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
|
||||
@@ -10293,6 +10290,7 @@ int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
|
||||
struct wmi_wow_host_wakeup_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10305,14 +10303,20 @@ int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_enable(struct ath12k *ar)
|
||||
{
|
||||
struct wmi_wow_enable_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10327,7 +10331,13 @@ int ath12k_wmi_wow_enable(struct ath12k *ar)
|
||||
cmd->pause_iface_config = cpu_to_le32(WOW_IFACE_PAUSE_ENABLED);
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow enable\n");
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
|
||||
@@ -10337,6 +10347,7 @@ int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
|
||||
struct wmi_wow_add_del_event_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10353,7 +10364,13 @@ int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
|
||||
wow_wakeup_event(event), enable, vdev_id);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
|
||||
@@ -10366,6 +10383,7 @@ int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
|
||||
struct sk_buff *skb;
|
||||
void *ptr;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
sizeof(*tlv) + /* array struct */
|
||||
@@ -10445,7 +10463,13 @@ int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
|
||||
ath12k_dbg_dump(ar->ab, ATH12K_DBG_WMI, NULL, "wow bitmask: ",
|
||||
bitmap->bitmaskbuf, pattern_len);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_ADD_WAKE_PATTERN_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
|
||||
@@ -10453,6 +10477,7 @@ int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
|
||||
struct wmi_wow_del_pattern_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10469,7 +10494,13 @@ int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
|
||||
vdev_id, pattern_id);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_WOW_DEL_WAKE_PATTERN_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
@@ -10605,6 +10636,7 @@ int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
|
||||
struct wmi_pno_scan_req_arg *pno_scan)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
if (pno_scan->enable)
|
||||
skb = ath12k_wmi_op_gen_config_pno_start(ar, vdev_id, pno_scan);
|
||||
@@ -10614,7 +10646,13 @@ int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
|
||||
if (IS_ERR_OR_NULL(skb))
|
||||
return -ENOMEM;
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_wmi_fill_ns_offload(struct ath12k *ar,
|
||||
@@ -10727,6 +10765,7 @@ int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
|
||||
void *buf_ptr;
|
||||
size_t len;
|
||||
u8 ns_cnt, ns_ext_tuples = 0;
|
||||
int ret;
|
||||
|
||||
ns_cnt = offload->ipv6_count;
|
||||
|
||||
@@ -10762,7 +10801,13 @@ int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
|
||||
if (ns_ext_tuples)
|
||||
ath12k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 1);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_SET_ARP_NS_OFFLOAD_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
|
||||
@@ -10772,7 +10817,7 @@ int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
__le64 replay_ctr;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10799,7 +10844,13 @@ int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "offload gtk rekey vdev: %d %d\n",
|
||||
arvif->vdev_id, enable);
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID offload\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
|
||||
@@ -10807,7 +10858,7 @@ int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
|
||||
{
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
@@ -10821,7 +10872,13 @@ int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "get gtk rekey vdev_id: %d\n",
|
||||
arvif->vdev_id);
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID getinfo\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_sta_keepalive(struct ath12k *ar,
|
||||
@@ -10832,6 +10889,7 @@ int ath12k_wmi_sta_keepalive(struct ath12k *ar,
|
||||
struct wmi_sta_keepalive_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd) + sizeof(*arp);
|
||||
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
@@ -10859,7 +10917,13 @@ int ath12k_wmi_sta_keepalive(struct ath12k *ar,
|
||||
"wmi sta keepalive vdev %d enabled %d method %d interval %d\n",
|
||||
arg->vdev_id, arg->enabled, arg->method, arg->interval);
|
||||
|
||||
return ath12k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_STA_KEEPALIVE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_mlo_setup(struct ath12k *ar, struct wmi_mlo_setup_arg *mlo_params)
|
||||
|
||||
@@ -4193,7 +4193,6 @@ struct wmi_addba_clear_resp_cmd {
|
||||
struct ath12k_wmi_mac_addr_params peer_macaddr;
|
||||
} __packed;
|
||||
|
||||
#define DFS_PHYERR_UNIT_TEST_CMD 0
|
||||
#define DFS_UNIT_TEST_MODULE 0x2b
|
||||
#define DFS_UNIT_TEST_TOKEN 0xAA
|
||||
|
||||
@@ -4204,10 +4203,15 @@ enum dfs_test_args_idx {
|
||||
DFS_MAX_TEST_ARGS,
|
||||
};
|
||||
|
||||
struct wmi_dfs_unit_test_arg {
|
||||
u32 cmd_id;
|
||||
u32 pdev_id;
|
||||
u32 radar_param;
|
||||
/* update if another test command requires more */
|
||||
#define WMI_UNIT_TEST_ARGS_MAX DFS_MAX_TEST_ARGS
|
||||
|
||||
struct wmi_unit_test_arg {
|
||||
u32 vdev_id;
|
||||
u32 module_id;
|
||||
u32 diag_token;
|
||||
u32 num_args;
|
||||
u32 args[WMI_UNIT_TEST_ARGS_MAX];
|
||||
};
|
||||
|
||||
struct wmi_unit_test_cmd {
|
||||
|
||||
@@ -1123,13 +1123,13 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
|
||||
wiphy_unlock(vif->ar->wiphy);
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
int link_id, u8 key_index, bool pairwise,
|
||||
const u8 *mac_addr,
|
||||
struct key_params *params)
|
||||
{
|
||||
struct ath6kl *ar = ath6kl_priv(ndev);
|
||||
struct ath6kl_vif *vif = netdev_priv(ndev);
|
||||
struct ath6kl *ar = ath6kl_priv(wdev->netdev);
|
||||
struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
|
||||
struct ath6kl_key *key = NULL;
|
||||
int seq_len;
|
||||
u8 key_usage;
|
||||
@@ -1248,12 +1248,12 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
(u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
int link_id, u8 key_index, bool pairwise,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
struct ath6kl *ar = ath6kl_priv(ndev);
|
||||
struct ath6kl_vif *vif = netdev_priv(ndev);
|
||||
struct ath6kl *ar = ath6kl_priv(wdev->netdev);
|
||||
struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
|
||||
|
||||
@@ -1278,13 +1278,13 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
return ath6kl_wmi_deletekey_cmd(ar->wmi, vif->fw_vif_idx, key_index);
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
int link_id, u8 key_index, bool pairwise,
|
||||
const u8 *mac_addr, void *cookie,
|
||||
void (*callback) (void *cookie,
|
||||
struct key_params *))
|
||||
{
|
||||
struct ath6kl_vif *vif = netdev_priv(ndev);
|
||||
struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
|
||||
struct ath6kl_key *key = NULL;
|
||||
struct key_params params;
|
||||
|
||||
@@ -1775,9 +1775,10 @@ static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
static int ath6kl_get_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct net_device *dev = wdev->netdev;
|
||||
struct ath6kl *ar = ath6kl_priv(dev);
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
long left;
|
||||
@@ -2992,9 +2993,10 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
||||
static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
static int ath6kl_del_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct station_del_parameters *params)
|
||||
{
|
||||
struct net_device *dev = wdev->netdev;
|
||||
struct ath6kl *ar = ath6kl_priv(dev);
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
const u8 *addr = params->mac ? params->mac : bcast_addr;
|
||||
@@ -3003,10 +3005,11 @@ static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
}
|
||||
|
||||
static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
static int ath6kl_change_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const u8 *mac,
|
||||
struct station_parameters *params)
|
||||
{
|
||||
struct net_device *dev = wdev->netdev;
|
||||
struct ath6kl *ar = ath6kl_priv(dev);
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
int err;
|
||||
|
||||
@@ -494,7 +494,7 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
|
||||
sinfo->assoc_req_ies = ies;
|
||||
sinfo->assoc_req_ies_len = ies_len;
|
||||
|
||||
cfg80211_new_sta(vif->ndev, mac_addr, sinfo, GFP_KERNEL);
|
||||
cfg80211_new_sta(&vif->wdev, mac_addr, sinfo, GFP_KERNEL);
|
||||
|
||||
netif_wake_queue(vif->ndev);
|
||||
|
||||
@@ -1011,7 +1011,7 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
|
||||
|
||||
if (!is_broadcast_ether_addr(bssid)) {
|
||||
/* send event to application */
|
||||
cfg80211_del_sta(vif->ndev, bssid, GFP_KERNEL);
|
||||
cfg80211_del_sta(&vif->wdev, bssid, GFP_KERNEL);
|
||||
}
|
||||
|
||||
if (memcmp(vif->ndev->dev_addr, bssid, ETH_ALEN) == 0) {
|
||||
|
||||
@@ -1112,8 +1112,6 @@ static int ath6kl_usb_probe(struct usb_interface *interface,
|
||||
int vendor_id, product_id;
|
||||
int ret = 0;
|
||||
|
||||
usb_get_dev(dev);
|
||||
|
||||
vendor_id = le16_to_cpu(dev->descriptor.idVendor);
|
||||
product_id = le16_to_cpu(dev->descriptor.idProduct);
|
||||
|
||||
@@ -1131,11 +1129,8 @@ static int ath6kl_usb_probe(struct usb_interface *interface,
|
||||
ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n");
|
||||
|
||||
ar_usb = ath6kl_usb_create(interface);
|
||||
|
||||
if (ar_usb == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_usb_put;
|
||||
}
|
||||
if (ar_usb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ar = ath6kl_core_create(&ar_usb->udev->dev);
|
||||
if (ar == NULL) {
|
||||
@@ -1164,15 +1159,12 @@ err_core_free:
|
||||
ath6kl_core_destroy(ar);
|
||||
err_usb_destroy:
|
||||
ath6kl_usb_destroy(ar_usb);
|
||||
err_usb_put:
|
||||
usb_put_dev(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath6kl_usb_remove(struct usb_interface *interface)
|
||||
static void ath6kl_usb_disconnect(struct usb_interface *interface)
|
||||
{
|
||||
usb_put_dev(interface_to_usbdev(interface));
|
||||
ath6kl_usb_device_detached(interface);
|
||||
}
|
||||
|
||||
@@ -1223,7 +1215,7 @@ static struct usb_driver ath6kl_usb_driver = {
|
||||
.probe = ath6kl_usb_probe,
|
||||
.suspend = ath6kl_usb_pm_suspend,
|
||||
.resume = ath6kl_usb_pm_resume,
|
||||
.disconnect = ath6kl_usb_remove,
|
||||
.disconnect = ath6kl_usb_disconnect,
|
||||
.id_table = ath6kl_usb_ids,
|
||||
.supports_autosuspend = true,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
|
||||
@@ -443,7 +443,7 @@ ath_node_to_tid(struct ath_node *an, u8 tidno)
|
||||
|
||||
#define case_rtn_string(val) case val: return #val
|
||||
|
||||
#define ath_for_each_chanctx(_sc, _ctx) \
|
||||
#define ath_for_each_chanctx(sc, ctx) \
|
||||
for (ctx = &sc->chanctx[0]; \
|
||||
ctx <= &sc->chanctx[ARRAY_SIZE(sc->chanctx) - 1]; \
|
||||
ctx++)
|
||||
|
||||
@@ -1384,8 +1384,6 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
usb_get_dev(udev);
|
||||
|
||||
hif_dev->udev = udev;
|
||||
hif_dev->interface = interface;
|
||||
hif_dev->usb_device_id = id;
|
||||
@@ -1405,7 +1403,6 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
||||
err_fw_req:
|
||||
usb_set_intfdata(interface, NULL);
|
||||
kfree(hif_dev);
|
||||
usb_put_dev(udev);
|
||||
err_alloc:
|
||||
return ret;
|
||||
}
|
||||
@@ -1453,7 +1450,6 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
|
||||
|
||||
kfree(hif_dev);
|
||||
dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");
|
||||
usb_put_dev(udev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
@@ -533,11 +533,11 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
|
||||
}
|
||||
|
||||
static int wil_cfg80211_get_station(struct wiphy *wiphy,
|
||||
struct net_device *ndev,
|
||||
struct wireless_dev *wdev,
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct wil6210_vif *vif = ndev_to_vif(ndev);
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
|
||||
int rc;
|
||||
|
||||
int cid = wil_find_cid(wil, vif->mid, mac);
|
||||
@@ -573,11 +573,11 @@ int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx)
|
||||
}
|
||||
|
||||
static int wil_cfg80211_dump_station(struct wiphy *wiphy,
|
||||
struct net_device *dev, int idx,
|
||||
struct wireless_dev *wdev, int idx,
|
||||
u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct wil6210_vif *vif = ndev_to_vif(dev);
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
|
||||
int rc;
|
||||
int cid = wil_find_cid_by_idx(wil, vif->mid, idx);
|
||||
|
||||
@@ -1620,15 +1620,14 @@ static void wil_del_rx_key(u8 key_index, enum wmi_key_usage key_usage,
|
||||
}
|
||||
|
||||
static int wil_cfg80211_add_key(struct wiphy *wiphy,
|
||||
struct net_device *ndev, int link_id,
|
||||
struct wireless_dev *wdev, int link_id,
|
||||
u8 key_index, bool pairwise,
|
||||
const u8 *mac_addr,
|
||||
struct key_params *params)
|
||||
{
|
||||
int rc;
|
||||
struct wil6210_vif *vif = ndev_to_vif(ndev);
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wireless_dev *wdev = vif_to_wdev(vif);
|
||||
struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
|
||||
enum wmi_key_usage key_usage = wil_detect_key_usage(wdev, pairwise);
|
||||
struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, vif->mid,
|
||||
key_usage,
|
||||
@@ -1697,13 +1696,12 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,
|
||||
}
|
||||
|
||||
static int wil_cfg80211_del_key(struct wiphy *wiphy,
|
||||
struct net_device *ndev, int link_id,
|
||||
struct wireless_dev *wdev, int link_id,
|
||||
u8 key_index, bool pairwise,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
struct wil6210_vif *vif = ndev_to_vif(ndev);
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wireless_dev *wdev = vif_to_wdev(vif);
|
||||
struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
|
||||
enum wmi_key_usage key_usage = wil_detect_key_usage(wdev, pairwise);
|
||||
struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, vif->mid,
|
||||
key_usage,
|
||||
@@ -2073,7 +2071,8 @@ void wil_cfg80211_ap_recovery(struct wil6210_priv *wil)
|
||||
key_params.key = vif->gtk;
|
||||
key_params.key_len = vif->gtk_len;
|
||||
key_params.seq_len = IEEE80211_GCMP_PN_LEN;
|
||||
rc = wil_cfg80211_add_key(wiphy, ndev, -1, vif->gtk_index,
|
||||
rc = wil_cfg80211_add_key(wiphy, vif_to_wdev(vif), -1,
|
||||
vif->gtk_index,
|
||||
false, NULL, &key_params);
|
||||
if (rc)
|
||||
wil_err(wil, "vif %d recovery add key failed (%d)\n",
|
||||
@@ -2227,12 +2226,12 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
|
||||
}
|
||||
|
||||
static int wil_cfg80211_add_station(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct wireless_dev *wdev,
|
||||
const u8 *mac,
|
||||
struct station_parameters *params)
|
||||
{
|
||||
struct wil6210_vif *vif = ndev_to_vif(dev);
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
|
||||
|
||||
wil_dbg_misc(wil, "add station %pM aid %d mid %d mask 0x%x set 0x%x\n",
|
||||
mac, params->aid, vif->mid,
|
||||
@@ -2252,11 +2251,11 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy,
|
||||
}
|
||||
|
||||
static int wil_cfg80211_del_station(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct wireless_dev *wdev,
|
||||
struct station_del_parameters *params)
|
||||
{
|
||||
struct wil6210_vif *vif = ndev_to_vif(dev);
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
|
||||
|
||||
wil_dbg_misc(wil, "del_station: %pM, reason=%d mid=%d\n",
|
||||
params->mac, params->reason_code, vif->mid);
|
||||
@@ -2269,12 +2268,12 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy,
|
||||
}
|
||||
|
||||
static int wil_cfg80211_change_station(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct wireless_dev *wdev,
|
||||
const u8 *mac,
|
||||
struct station_parameters *params)
|
||||
{
|
||||
struct wil6210_vif *vif = ndev_to_vif(dev);
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
|
||||
int authorize;
|
||||
int cid, i;
|
||||
struct wil_ring_tx_data *txdata = NULL;
|
||||
|
||||
@@ -245,7 +245,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
||||
{
|
||||
uint i;
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct net_device *ndev = vif_to_ndev(vif);
|
||||
struct wireless_dev *wdev = vif_to_wdev(vif);
|
||||
struct wil_sta_info *sta = &wil->sta[cid];
|
||||
int min_ring_id = wil_get_min_tx_ring_id(wil);
|
||||
@@ -265,7 +264,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
/* AP-like interface */
|
||||
cfg80211_del_sta(ndev, sta->addr, GFP_KERNEL);
|
||||
cfg80211_del_sta(wdev, sta->addr, GFP_KERNEL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -1076,7 +1076,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
|
||||
if (rc) {
|
||||
if (disable_ap_sme)
|
||||
/* notify new_sta has failed */
|
||||
cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL);
|
||||
cfg80211_del_sta(wdev, evt->bssid, GFP_KERNEL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1093,7 +1093,8 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
|
||||
sinfo->assoc_req_ies_len = assoc_req_ielen;
|
||||
}
|
||||
|
||||
cfg80211_new_sta(ndev, evt->bssid, sinfo, GFP_KERNEL);
|
||||
cfg80211_new_sta(ndev->ieee80211_ptr, evt->bssid, sinfo,
|
||||
GFP_KERNEL);
|
||||
|
||||
kfree(sinfo);
|
||||
} else {
|
||||
|
||||
@@ -2758,11 +2758,11 @@ done:
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
brcmf_cfg80211_del_key(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
int link_id, u8 key_idx, bool pairwise,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_if *ifp = netdev_priv(wdev->netdev);
|
||||
struct brcmf_wsec_key *key;
|
||||
s32 err;
|
||||
|
||||
@@ -2796,12 +2796,12 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
brcmf_cfg80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
int link_id, u8 key_idx, bool pairwise,
|
||||
const u8 *mac_addr, struct key_params *params)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_if *ifp = netdev_priv(wdev->netdev);
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
struct brcmf_wsec_key *key;
|
||||
s32 val;
|
||||
@@ -2822,7 +2822,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
}
|
||||
|
||||
if (params->key_len == 0)
|
||||
return brcmf_cfg80211_del_key(wiphy, ndev, -1, key_idx,
|
||||
return brcmf_cfg80211_del_key(wiphy, wdev, -1, key_idx,
|
||||
pairwise, mac_addr);
|
||||
|
||||
if (params->key_len > sizeof(key->data)) {
|
||||
@@ -2918,7 +2918,7 @@ done:
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
brcmf_cfg80211_get_key(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
int link_id, u8 key_idx, bool pairwise,
|
||||
const u8 *mac_addr, void *cookie,
|
||||
void (*callback)(void *cookie,
|
||||
@@ -2926,7 +2926,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct key_params params;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_if *ifp = netdev_priv(wdev->netdev);
|
||||
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
struct brcmf_cfg80211_security *sec;
|
||||
@@ -2976,10 +2976,10 @@ done:
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
|
||||
struct net_device *ndev, int link_id,
|
||||
struct wireless_dev *wdev, int link_id,
|
||||
u8 key_idx)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_if *ifp = netdev_priv(wdev->netdev);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter key_idx %d\n", key_idx);
|
||||
|
||||
@@ -3132,11 +3132,11 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_if *ifp = netdev_priv(wdev->netdev);
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
struct brcmf_scb_val_le scb_val;
|
||||
s32 err = 0;
|
||||
@@ -3255,11 +3255,11 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
int idx, u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_if *ifp = netdev_priv(wdev->netdev);
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
s32 err;
|
||||
|
||||
@@ -3284,7 +3284,8 @@ brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
}
|
||||
if (idx < le32_to_cpu(cfg->assoclist.count)) {
|
||||
memcpy(mac, cfg->assoclist.mac[idx], ETH_ALEN);
|
||||
return brcmf_cfg80211_get_station(wiphy, ndev, mac, sinfo);
|
||||
return brcmf_cfg80211_get_station(wiphy, wdev,
|
||||
mac, sinfo);
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
@@ -5452,12 +5453,13 @@ brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
brcmf_cfg80211_del_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct station_del_parameters *params)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
struct brcmf_scb_val_le scbval;
|
||||
struct net_device *ndev = wdev->netdev;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
s32 err;
|
||||
|
||||
@@ -5484,12 +5486,12 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
brcmf_cfg80211_change_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const u8 *mac, struct station_parameters *params)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_if *ifp = netdev_priv(wdev->netdev);
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, MAC %pM, mask 0x%04x set 0x%04x\n", mac,
|
||||
@@ -6548,13 +6550,14 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
|
||||
sinfo->assoc_req_ies_len = e->datalen;
|
||||
generation++;
|
||||
sinfo->generation = generation;
|
||||
cfg80211_new_sta(ndev, e->addr, sinfo, GFP_KERNEL);
|
||||
cfg80211_new_sta(ndev->ieee80211_ptr, e->addr, sinfo,
|
||||
GFP_KERNEL);
|
||||
|
||||
kfree(sinfo);
|
||||
} else if ((event == BRCMF_E_DISASSOC_IND) ||
|
||||
(event == BRCMF_E_DEAUTH_IND) ||
|
||||
(event == BRCMF_E_DEAUTH)) {
|
||||
cfg80211_del_sta(ndev, e->addr, GFP_KERNEL);
|
||||
cfg80211_del_sta(ndev->ieee80211_ptr, e->addr, GFP_KERNEL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1007,18 +1007,33 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
|
||||
|
||||
core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON,
|
||||
SI_ENUM_BASE_DEFAULT, 0);
|
||||
if (IS_ERR(core))
|
||||
return PTR_ERR(core);
|
||||
|
||||
brcmf_chip_sb_corerev(ci, core);
|
||||
core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
|
||||
BCM4329_CORE_BUS_BASE, 0);
|
||||
if (IS_ERR(core))
|
||||
return PTR_ERR(core);
|
||||
|
||||
brcmf_chip_sb_corerev(ci, core);
|
||||
core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
|
||||
BCM4329_CORE_SOCRAM_BASE, 0);
|
||||
if (IS_ERR(core))
|
||||
return PTR_ERR(core);
|
||||
|
||||
brcmf_chip_sb_corerev(ci, core);
|
||||
core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
|
||||
BCM4329_CORE_ARM_BASE, 0);
|
||||
if (IS_ERR(core))
|
||||
return PTR_ERR(core);
|
||||
|
||||
brcmf_chip_sb_corerev(ci, core);
|
||||
|
||||
core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0);
|
||||
if (IS_ERR(core))
|
||||
return PTR_ERR(core);
|
||||
|
||||
brcmf_chip_sb_corerev(ci, core);
|
||||
} else if (socitype == SOCI_AI) {
|
||||
ci->iscoreup = brcmf_chip_ai_iscoreup;
|
||||
|
||||
@@ -670,6 +670,9 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,
|
||||
}
|
||||
|
||||
fallback:
|
||||
if (cur->flags & BRCMF_FW_REQF_OPTIONAL)
|
||||
return firmware_request_nowarn(fw, cur->path, fwctx->dev);
|
||||
|
||||
return request_firmware(fw, cur->path, fwctx->dev);
|
||||
}
|
||||
|
||||
@@ -714,9 +717,10 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx)
|
||||
if (!alt_path)
|
||||
goto fallback;
|
||||
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
|
||||
fwctx->dev, GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_done_alt_path);
|
||||
ret = firmware_request_nowait_nowarn(THIS_MODULE,
|
||||
alt_path, fwctx->dev,
|
||||
GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_done_alt_path);
|
||||
kfree(alt_path);
|
||||
|
||||
if (ret < 0)
|
||||
@@ -779,9 +783,10 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
|
||||
fwctx->req->board_types[0]);
|
||||
if (alt_path) {
|
||||
fwctx->board_index++;
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
|
||||
fwctx->dev, GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_done_alt_path);
|
||||
ret = firmware_request_nowait_nowarn(THIS_MODULE,
|
||||
alt_path, fwctx->dev,
|
||||
GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_done_alt_path);
|
||||
kfree(alt_path);
|
||||
} else {
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, first->path,
|
||||
|
||||
@@ -128,7 +128,9 @@ int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
||||
if (err)
|
||||
brcmf_err("failed to get OF country code map (err=%d)\n", err);
|
||||
|
||||
of_get_mac_address(np, settings->mac);
|
||||
err = of_get_mac_address(np, settings->mac);
|
||||
if (err == -EPROBE_DEFER)
|
||||
return err;
|
||||
|
||||
if (bus_type != BRCMF_BUSTYPE_SDIO)
|
||||
return 0;
|
||||
|
||||
@@ -2476,8 +2476,9 @@ static void brcmf_sdio_bus_stop(struct device *dev)
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (bus->watchdog_tsk) {
|
||||
get_task_struct(bus->watchdog_tsk);
|
||||
send_sig(SIGTERM, bus->watchdog_tsk, 1);
|
||||
kthread_stop(bus->watchdog_tsk);
|
||||
kthread_stop_put(bus->watchdog_tsk);
|
||||
bus->watchdog_tsk = NULL;
|
||||
}
|
||||
|
||||
@@ -4567,8 +4568,9 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
|
||||
if (bus) {
|
||||
/* Stop watchdog task */
|
||||
if (bus->watchdog_tsk) {
|
||||
get_task_struct(bus->watchdog_tsk);
|
||||
send_sig(SIGTERM, bus->watchdog_tsk, 1);
|
||||
kthread_stop(bus->watchdog_tsk);
|
||||
kthread_stop_put(bus->watchdog_tsk);
|
||||
bus->watchdog_tsk = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware core release supported */
|
||||
#define IWL_BZ_UCODE_CORE_MAX 101
|
||||
#define IWL_BZ_UCODE_CORE_MAX 102
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_BZ_UCODE_API_MIN 100
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware core release supported */
|
||||
#define IWL_DR_UCODE_CORE_MAX 101
|
||||
#define IWL_DR_UCODE_CORE_MAX 102
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_DR_UCODE_API_MIN 100
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware core release supported */
|
||||
#define IWL_SC_UCODE_CORE_MAX 101
|
||||
#define IWL_SC_UCODE_CORE_MAX 102
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_SC_UCODE_API_MIN 100
|
||||
|
||||
@@ -504,7 +504,8 @@ iwl_acpi_parse_chains_table(union acpi_object *table,
|
||||
u8 num_chains, u8 num_sub_bands)
|
||||
{
|
||||
for (u8 chain = 0; chain < num_chains; chain++) {
|
||||
for (u8 subband = 0; subband < BIOS_SAR_MAX_SUB_BANDS_NUM;
|
||||
for (u8 subband = 0;
|
||||
subband < ARRAY_SIZE(chains[chain].subbands);
|
||||
subband++) {
|
||||
/* if we don't have the values, use the default */
|
||||
if (subband >= num_sub_bands) {
|
||||
@@ -534,7 +535,23 @@ int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
/* start by trying to read revision 2 */
|
||||
/* start by trying to read revision 3 */
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_WRDS_WIFI_DATA_SIZE_REV3,
|
||||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev != 3) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
num_chains = ACPI_SAR_NUM_CHAINS_REV2;
|
||||
num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV3;
|
||||
|
||||
goto read_table;
|
||||
}
|
||||
|
||||
/* then try revision 2 */
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_WRDS_WIFI_DATA_SIZE_REV2,
|
||||
&tbl_rev);
|
||||
@@ -591,6 +608,13 @@ read_table:
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (WARN_ON(num_chains * num_sub_bands >
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains) *
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Reading WRDS tbl_rev=%d\n", tbl_rev);
|
||||
|
||||
flags = wifi_pkg->package.elements[1].integer.value;
|
||||
@@ -624,7 +648,22 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
/* start by trying to read revision 2 */
|
||||
/* start by trying to read revision 3 */
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_EWRD_WIFI_DATA_SIZE_REV3,
|
||||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev != 3) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV3;
|
||||
|
||||
goto read_table;
|
||||
}
|
||||
|
||||
/* then try revision 2 */
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_EWRD_WIFI_DATA_SIZE_REV2,
|
||||
&tbl_rev);
|
||||
@@ -679,6 +718,13 @@ read_table:
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands >
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains) *
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
enabled = !!(wifi_pkg->package.elements[1].integer.value);
|
||||
n_profiles = wifi_pkg->package.elements[2].integer.value;
|
||||
|
||||
@@ -721,6 +767,13 @@ read_table:
|
||||
if (tbl_rev < 2)
|
||||
goto set_enabled;
|
||||
|
||||
if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * 2 * num_sub_bands >
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains) *
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* parse cdb chains for all profiles */
|
||||
for (i = 0; i < n_profiles; i++) {
|
||||
struct iwl_sar_profile_chain *chains;
|
||||
@@ -759,6 +812,12 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
u8 profiles;
|
||||
u8 min_profiles;
|
||||
} rev_data[] = {
|
||||
{
|
||||
.revisions = BIT(4),
|
||||
.bands = ACPI_GEO_NUM_BANDS_REV4,
|
||||
.profiles = ACPI_NUM_GEO_PROFILES_REV3,
|
||||
.min_profiles = BIOS_GEO_MIN_PROFILE_NUM,
|
||||
},
|
||||
{
|
||||
.revisions = BIT(3),
|
||||
.bands = ACPI_GEO_NUM_BANDS_REV2,
|
||||
@@ -812,6 +871,18 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
num_bands = rev_data[idx].bands;
|
||||
num_profiles = rev_data[idx].profiles;
|
||||
|
||||
if (WARN_ON(num_profiles >
|
||||
ARRAY_SIZE(fwrt->geo_profiles))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (WARN_ON(num_bands >
|
||||
ARRAY_SIZE(fwrt->geo_profiles[0].bands))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (rev_data[idx].min_profiles) {
|
||||
/* read header that says # of profiles */
|
||||
union acpi_object *entry;
|
||||
@@ -851,18 +922,20 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
|
||||
read_table:
|
||||
fwrt->geo_rev = tbl_rev;
|
||||
|
||||
for (i = 0; i < num_profiles; i++) {
|
||||
for (j = 0; j < BIOS_GEO_MAX_NUM_BANDS; j++) {
|
||||
struct iwl_geo_profile *prof = &fwrt->geo_profiles[i];
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(prof->bands); j++) {
|
||||
union acpi_object *entry;
|
||||
|
||||
/*
|
||||
* num_bands is either 2 or 3, if it's only 2 then
|
||||
* fill the third band (6 GHz) with the values from
|
||||
* 5 GHz (second band)
|
||||
* num_bands is either 2 or 3 or 4, if it's lower
|
||||
* than 4, fill the third band (6 GHz) with the values
|
||||
* from 5 GHz (second band)
|
||||
*/
|
||||
if (j >= num_bands) {
|
||||
fwrt->geo_profiles[i].bands[j].max =
|
||||
fwrt->geo_profiles[i].bands[1].max;
|
||||
prof->bands[j].max = prof->bands[1].max;
|
||||
} else {
|
||||
entry = &wifi_pkg->package.elements[entry_idx];
|
||||
entry_idx++;
|
||||
@@ -872,15 +945,17 @@ read_table:
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
fwrt->geo_profiles[i].bands[j].max =
|
||||
prof->bands[j].max =
|
||||
entry->integer.value;
|
||||
}
|
||||
|
||||
for (k = 0; k < BIOS_GEO_NUM_CHAINS; k++) {
|
||||
for (k = 0;
|
||||
k < ARRAY_SIZE(prof->bands[0].chains);
|
||||
k++) {
|
||||
/* same here as above */
|
||||
if (j >= num_bands) {
|
||||
fwrt->geo_profiles[i].bands[j].chains[k] =
|
||||
fwrt->geo_profiles[i].bands[1].chains[k];
|
||||
prof->bands[j].chains[k] =
|
||||
prof->bands[1].chains[k];
|
||||
} else {
|
||||
entry = &wifi_pkg->package.elements[entry_idx];
|
||||
entry_idx++;
|
||||
@@ -890,7 +965,7 @@ read_table:
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
fwrt->geo_profiles[i].bands[j].chains[k] =
|
||||
prof->bands[j].chains[k] =
|
||||
entry->integer.value;
|
||||
}
|
||||
}
|
||||
@@ -898,6 +973,7 @@ read_table:
|
||||
}
|
||||
|
||||
fwrt->geo_num_profiles = num_profiles;
|
||||
fwrt->geo_bios_source = BIOS_SOURCE_ACPI;
|
||||
fwrt->geo_enabled = true;
|
||||
ret = 0;
|
||||
out_free:
|
||||
@@ -915,6 +991,22 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
/* try to read ppag table rev 5 */
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_PPAG_WIFI_DATA_SIZE_V3, &tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev == 5) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V3;
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Reading PPAG table (tbl_rev=%d)\n",
|
||||
tbl_rev);
|
||||
goto read_table;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
/* try to read ppag table rev 1 to 4 (all have the same data size) */
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
|
||||
@@ -950,6 +1042,15 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
goto out_free;
|
||||
|
||||
read_table:
|
||||
if (WARN_ON_ONCE(num_sub_bands >
|
||||
ARRAY_SIZE(fwrt->ppag_chains[0].subbands))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(ACPI_PPAG_NUM_CHAINS >
|
||||
ARRAY_SIZE(fwrt->ppag_chains));
|
||||
|
||||
fwrt->ppag_bios_rev = tbl_rev;
|
||||
flags = &wifi_pkg->package.elements[1];
|
||||
|
||||
@@ -966,7 +1067,7 @@ read_table:
|
||||
* first sub-band (j=0) corresponds to Low-Band (2.4GHz), and the
|
||||
* following sub-bands to High-Band (5GHz).
|
||||
*/
|
||||
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
|
||||
for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
|
||||
for (j = 0; j < num_sub_bands; j++) {
|
||||
union acpi_object *ent;
|
||||
|
||||
@@ -980,6 +1081,7 @@ read_table:
|
||||
}
|
||||
}
|
||||
|
||||
iwl_bios_print_ppag(fwrt, num_sub_bands);
|
||||
fwrt->ppag_bios_source = BIOS_SOURCE_ACPI;
|
||||
ret = 0;
|
||||
|
||||
|
||||
@@ -8,11 +8,6 @@
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include "fw/regulatory.h"
|
||||
#include "fw/api/commands.h"
|
||||
#include "fw/api/power.h"
|
||||
#include "fw/api/phy.h"
|
||||
#include "fw/api/nvm-reg.h"
|
||||
#include "fw/api/config.h"
|
||||
#include "fw/img.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
@@ -44,6 +39,7 @@
|
||||
#define ACPI_SAR_NUM_SUB_BANDS_REV0 5
|
||||
#define ACPI_SAR_NUM_SUB_BANDS_REV1 11
|
||||
#define ACPI_SAR_NUM_SUB_BANDS_REV2 11
|
||||
#define ACPI_SAR_NUM_SUB_BANDS_REV3 12
|
||||
|
||||
#define ACPI_WRDS_WIFI_DATA_SIZE_REV0 (ACPI_SAR_NUM_CHAINS_REV0 * \
|
||||
ACPI_SAR_NUM_SUB_BANDS_REV0 + 2)
|
||||
@@ -51,6 +47,8 @@
|
||||
ACPI_SAR_NUM_SUB_BANDS_REV1 + 2)
|
||||
#define ACPI_WRDS_WIFI_DATA_SIZE_REV2 (ACPI_SAR_NUM_CHAINS_REV2 * \
|
||||
ACPI_SAR_NUM_SUB_BANDS_REV2 + 2)
|
||||
#define ACPI_WRDS_WIFI_DATA_SIZE_REV3 (ACPI_SAR_NUM_CHAINS_REV2 * \
|
||||
ACPI_SAR_NUM_SUB_BANDS_REV3 + 2)
|
||||
#define ACPI_EWRD_WIFI_DATA_SIZE_REV0 ((ACPI_SAR_PROFILE_NUM - 1) * \
|
||||
ACPI_SAR_NUM_CHAINS_REV0 * \
|
||||
ACPI_SAR_NUM_SUB_BANDS_REV0 + 3)
|
||||
@@ -60,11 +58,15 @@
|
||||
#define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \
|
||||
ACPI_SAR_NUM_CHAINS_REV2 * \
|
||||
ACPI_SAR_NUM_SUB_BANDS_REV2 + 3)
|
||||
#define ACPI_EWRD_WIFI_DATA_SIZE_REV3 ((ACPI_SAR_PROFILE_NUM - 1) * \
|
||||
ACPI_SAR_NUM_CHAINS_REV2 * \
|
||||
ACPI_SAR_NUM_SUB_BANDS_REV3 + 3)
|
||||
#define ACPI_WPFC_WIFI_DATA_SIZE 5 /* domain and 4 filter config words */
|
||||
|
||||
/* revision 0 and 1 are identical, except for the semantics in the FW */
|
||||
#define ACPI_GEO_NUM_BANDS_REV0 2
|
||||
#define ACPI_GEO_NUM_BANDS_REV2 3
|
||||
#define ACPI_GEO_NUM_BANDS_REV4 4
|
||||
|
||||
#define ACPI_WRDD_WIFI_DATA_SIZE 2
|
||||
#define ACPI_SPLC_WIFI_DATA_SIZE 2
|
||||
@@ -96,10 +98,18 @@
|
||||
*/
|
||||
#define ACPI_WTAS_WIFI_DATA_SIZE (3 + IWL_WTAS_BLACK_LIST_MAX)
|
||||
|
||||
#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((IWL_NUM_CHAIN_LIMITS * \
|
||||
IWL_NUM_SUB_BANDS_V1) + 2)
|
||||
#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \
|
||||
IWL_NUM_SUB_BANDS_V2) + 2)
|
||||
#define ACPI_PPAG_NUM_CHAINS 2
|
||||
#define ACPI_PPAG_NUM_BANDS_V1 5
|
||||
#define ACPI_PPAG_NUM_BANDS_V2 11
|
||||
#define ACPI_PPAG_NUM_BANDS_V3 12
|
||||
#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((ACPI_PPAG_NUM_CHAINS * \
|
||||
ACPI_PPAG_NUM_BANDS_V1) + 2)
|
||||
#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((ACPI_PPAG_NUM_CHAINS * \
|
||||
ACPI_PPAG_NUM_BANDS_V2) + 2)
|
||||
|
||||
/* used for ACPI PPAG table rev 5 */
|
||||
#define ACPI_PPAG_WIFI_DATA_SIZE_V3 ((ACPI_PPAG_NUM_CHAINS * \
|
||||
ACPI_PPAG_NUM_BANDS_V3) + 2)
|
||||
|
||||
#define IWL_SAR_ENABLE_MSK BIT(0)
|
||||
#define IWL_REDUCE_POWER_FLAGS_POS 1
|
||||
|
||||
@@ -56,7 +56,8 @@ enum iwl_data_path_subcmd_ids {
|
||||
RFH_QUEUE_CONFIG_CMD = 0xD,
|
||||
|
||||
/**
|
||||
* @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd_v4
|
||||
* @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd_v4 or
|
||||
* &struct iwl_tlc_config_cmd_v5 or &struct iwl_tlc_config_cmd.
|
||||
*/
|
||||
TLC_MNG_CONFIG_CMD = 0xF,
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2025 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2026 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -26,7 +26,7 @@ enum iwl_mac_conf_subcmd_ids {
|
||||
*/
|
||||
MISSED_VAP_NOTIF = 0xFA,
|
||||
/**
|
||||
* @SESSION_PROTECTION_CMD: &struct iwl_mvm_session_prot_cmd
|
||||
* @SESSION_PROTECTION_CMD: &struct iwl_session_prot_cmd
|
||||
*/
|
||||
SESSION_PROTECTION_CMD = 0x5,
|
||||
/**
|
||||
@@ -34,7 +34,8 @@ enum iwl_mac_conf_subcmd_ids {
|
||||
*/
|
||||
CANCEL_CHANNEL_SWITCH_CMD = 0x6,
|
||||
/**
|
||||
* @MAC_CONFIG_CMD: &struct iwl_mac_config_cmd
|
||||
* @MAC_CONFIG_CMD: &struct iwl_mac_config_cmd_v3 or
|
||||
* &struct iwl_mac_config_cmd
|
||||
*/
|
||||
MAC_CONFIG_CMD = 0x8,
|
||||
/**
|
||||
@@ -42,7 +43,8 @@ enum iwl_mac_conf_subcmd_ids {
|
||||
*/
|
||||
LINK_CONFIG_CMD = 0x9,
|
||||
/**
|
||||
* @STA_CONFIG_CMD: &struct iwl_sta_cfg_cmd
|
||||
* @STA_CONFIG_CMD: &struct iwl_sta_cfg_cmd_v1,
|
||||
* &struct iwl_sta_cfg_cmd_v2, or &struct iwl_sta_cfg_cmd
|
||||
*/
|
||||
STA_CONFIG_CMD = 0xA,
|
||||
/**
|
||||
@@ -356,7 +358,7 @@ struct iwl_mac_wifi_gen_support {
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_mac_config_cmd - command structure to configure MAC contexts in
|
||||
* struct iwl_mac_config_cmd_v3 - command structure to configure MAC contexts in
|
||||
* MLD API for versions 2 and 3
|
||||
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
|
||||
*
|
||||
@@ -375,7 +377,7 @@ struct iwl_mac_wifi_gen_support {
|
||||
* @client: client mac data
|
||||
* @p2p_dev: mac data for p2p device
|
||||
*/
|
||||
struct iwl_mac_config_cmd {
|
||||
struct iwl_mac_config_cmd_v3 {
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
/* MAC_CONTEXT_TYPE_API_E */
|
||||
@@ -393,7 +395,62 @@ struct iwl_mac_config_cmd {
|
||||
struct iwl_mac_client_data client;
|
||||
struct iwl_mac_p2p_dev_data p2p_dev;
|
||||
};
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2_VER_3 */
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2, _VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_nan_data - NAN specific MAC data
|
||||
* @ndi_addrs: extra NDI addresses being used
|
||||
* @ndi_addrs_count: number of extra NDI addresses
|
||||
*/
|
||||
struct iwl_mac_nan_data {
|
||||
struct {
|
||||
u8 addr[ETH_ALEN];
|
||||
__le16 reserved;
|
||||
} __packed ndi_addrs[2];
|
||||
__le32 ndi_addrs_count;
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_NAN_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_config_cmd - command structure to configure MAC contexts in
|
||||
* MLD API for versions 4
|
||||
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
|
||||
*
|
||||
* @id_and_color: ID and color of the MAC
|
||||
* @action: action to perform, see &enum iwl_ctxt_action
|
||||
* @mac_type: one of &enum iwl_mac_types
|
||||
* @local_mld_addr: mld address
|
||||
* @reserved_for_local_mld_addr: reserved
|
||||
* @filter_flags: combination of &enum iwl_mac_config_filter_flags
|
||||
* @wifi_gen_v2: he/eht parameters as in cmd version 2
|
||||
* @wifi_gen: he/eht/uhr parameters as in cmd version 3
|
||||
* @nic_not_ack_enabled: mark that the NIC doesn't support receiving
|
||||
* ACK-enabled AGG, (i.e. both BACK and non-BACK frames in single AGG).
|
||||
* If the NIC is not ACK_ENABLED it may use the EOF-bit in first non-0
|
||||
* len delim to determine if AGG or single.
|
||||
* @client: client mac data
|
||||
* @p2p_dev: mac data for p2p device
|
||||
* @nan: NAN specific data (NAN data interface addresses)
|
||||
*/
|
||||
struct iwl_mac_config_cmd {
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
/* MAC_CONTEXT_TYPE_API_E */
|
||||
__le32 mac_type;
|
||||
u8 local_mld_addr[6];
|
||||
__le16 reserved_for_local_mld_addr;
|
||||
__le32 filter_flags;
|
||||
union {
|
||||
struct iwl_mac_wifi_gen_support_v2 wifi_gen_v2;
|
||||
struct iwl_mac_wifi_gen_support wifi_gen;
|
||||
};
|
||||
__le32 nic_not_ack_enabled;
|
||||
/* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_3 */
|
||||
union {
|
||||
struct iwl_mac_client_data client;
|
||||
struct iwl_mac_p2p_dev_data p2p_dev;
|
||||
struct iwl_mac_nan_data nan;
|
||||
};
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_4 */
|
||||
|
||||
/**
|
||||
* enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being
|
||||
@@ -652,6 +709,7 @@ struct iwl_link_config_cmd {
|
||||
*/
|
||||
#define IWL_FW_MAX_ACTIVE_LINKS_NUM 2
|
||||
#define IWL_FW_MAX_LINK_ID 3
|
||||
#define IWL_FW_MAX_LINKS IWL_FW_MAX_LINK_ID + 1
|
||||
|
||||
/**
|
||||
* enum iwl_fw_sta_type - FW station types
|
||||
@@ -662,6 +720,13 @@ struct iwl_link_config_cmd {
|
||||
* @STATION_TYPE_MCAST: the station used for BCAST / MCAST in GO. Will be
|
||||
* suspended / resumed at the right timing depending on the clients'
|
||||
* power save state and the DTIM timing
|
||||
* @STATION_TYPE_NAN_PEER_NMI: NAN management peer station type. A station
|
||||
* of this type can have any number of links (even none) set in the
|
||||
* link_mask. (Supported since version 3.)
|
||||
* @STATION_TYPE_NAN_PEER_NDI: NAN data peer station type. A station
|
||||
* of this type can have any number of links (even none) set in the
|
||||
* link_mask. (Supported since version 3.)
|
||||
* @STATION_TYPE_MAX: maximum number of FW station types
|
||||
* @STATION_TYPE_AUX: aux sta. In the FW there is no need for a special type
|
||||
* for the aux sta, so this type is only for driver - internal use.
|
||||
*/
|
||||
@@ -669,8 +734,11 @@ enum iwl_fw_sta_type {
|
||||
STATION_TYPE_PEER,
|
||||
STATION_TYPE_BCAST_MGMT,
|
||||
STATION_TYPE_MCAST,
|
||||
STATION_TYPE_AUX,
|
||||
}; /* STATION_TYPE_E_VER_1 */
|
||||
STATION_TYPE_NAN_PEER_NMI,
|
||||
STATION_TYPE_NAN_PEER_NDI,
|
||||
STATION_TYPE_MAX,
|
||||
STATION_TYPE_AUX = STATION_TYPE_MAX /* this doesn't exist in FW */
|
||||
}; /* STATION_TYPE_E_VER_1, _VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_sta_cfg_cmd_v1 - cmd structure to add a peer sta to the uCode's
|
||||
@@ -729,7 +797,7 @@ struct iwl_sta_cfg_cmd_v1 {
|
||||
} __packed; /* STA_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's
|
||||
* struct iwl_sta_cfg_cmd_v2 - cmd structure to add a peer sta to the uCode's
|
||||
* station table
|
||||
* ( STA_CONFIG_CMD = 0xA )
|
||||
*
|
||||
@@ -769,7 +837,7 @@ struct iwl_sta_cfg_cmd_v1 {
|
||||
* @mic_compute_pad_delay: MIC compute time padding
|
||||
* @reserved: Reserved for alignment
|
||||
*/
|
||||
struct iwl_sta_cfg_cmd {
|
||||
struct iwl_sta_cfg_cmd_v2 {
|
||||
__le32 sta_id;
|
||||
__le32 link_id;
|
||||
u8 peer_mld_address[ETH_ALEN];
|
||||
@@ -799,6 +867,83 @@ struct iwl_sta_cfg_cmd {
|
||||
u8 reserved[2];
|
||||
} __packed; /* STA_CMD_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's
|
||||
* station table
|
||||
* ( STA_CONFIG_CMD = 0xA )
|
||||
*
|
||||
* @sta_id: index of station in uCode's station table
|
||||
* @link_mask: bitmap of link FW IDs used with this STA
|
||||
* @peer_mld_address: the peers mld address
|
||||
* @reserved_for_peer_mld_address: reserved
|
||||
* @peer_link_address: the address of the link that is used to communicate
|
||||
* with this sta
|
||||
* @reserved_for_peer_link_address: reserved
|
||||
* @station_type: type of this station. See &enum iwl_fw_sta_type
|
||||
* @assoc_id: for GO only
|
||||
* @beamform_flags: beam forming controls
|
||||
* @mfp: indicates whether the STA uses management frame protection or not.
|
||||
* @mimo: indicates whether the sta uses mimo or not
|
||||
* @mimo_protection: indicates whether the sta uses mimo protection or not
|
||||
* @ack_enabled: indicates that the AP supports receiving ACK-
|
||||
* enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
|
||||
* @trig_rnd_alloc: indicates that trigger based random allocation
|
||||
* is enabled according to UORA element existence
|
||||
* @tx_ampdu_spacing: minimum A-MPDU spacing:
|
||||
* 4 - 2us density, 5 - 4us density, 6 - 8us density, 7 - 16us density
|
||||
* @tx_ampdu_max_size: maximum A-MPDU length: 0 - 8K, 1 - 16K, 2 - 32K,
|
||||
* 3 - 64K, 4 - 128K, 5 - 256K, 6 - 512K, 7 - 1024K.
|
||||
* @sp_length: the size of the SP in actual number of frames
|
||||
* @uapsd_acs: 4 LS bits are trigger enabled ACs, 4 MS bits are the deliver
|
||||
* enabled ACs.
|
||||
* @pkt_ext: optional, exists according to PPE-present bit in the HE/EHT-PHY
|
||||
* capa
|
||||
* @htc_flags: which features are supported in HTC
|
||||
* @use_ldpc_x2_cw: Indicates whether to use LDPC with double CW
|
||||
* @use_icf: Indicates whether to use ICF instead of RTS
|
||||
* @dps_pad_time: DPS (Dynamic Power Save) padding delay resolution to ensure
|
||||
* proper timing alignment
|
||||
* @dps_trans_delay: DPS minimal time that takes the peer to return to low power
|
||||
* @dps_enabled: flag indicating whether or not DPS is enabled
|
||||
* @mic_prep_pad_delay: MIC prep time padding
|
||||
* @mic_compute_pad_delay: MIC compute time padding
|
||||
* @nmi_sta_id: for an NDI peer STA, the NMI peer STA ID it relates to
|
||||
* @ndi_local_addr: for an NDI peer STA, the local NDI interface MAC address
|
||||
* @reserved: Reserved for alignment
|
||||
*/
|
||||
struct iwl_sta_cfg_cmd {
|
||||
__le32 sta_id;
|
||||
__le32 link_mask;
|
||||
u8 peer_mld_address[ETH_ALEN];
|
||||
__le16 reserved_for_peer_mld_address;
|
||||
u8 peer_link_address[ETH_ALEN];
|
||||
__le16 reserved_for_peer_link_address;
|
||||
__le32 station_type;
|
||||
__le32 assoc_id;
|
||||
__le32 beamform_flags;
|
||||
__le32 mfp;
|
||||
__le32 mimo;
|
||||
__le32 mimo_protection;
|
||||
__le32 ack_enabled;
|
||||
__le32 trig_rnd_alloc;
|
||||
__le32 tx_ampdu_spacing;
|
||||
__le32 tx_ampdu_max_size;
|
||||
__le32 sp_length;
|
||||
__le32 uapsd_acs;
|
||||
struct iwl_he_pkt_ext_v2 pkt_ext;
|
||||
__le32 htc_flags;
|
||||
u8 use_ldpc_x2_cw;
|
||||
u8 use_icf;
|
||||
u8 dps_pad_time;
|
||||
u8 dps_trans_delay;
|
||||
u8 dps_enabled;
|
||||
u8 mic_prep_pad_delay;
|
||||
u8 mic_compute_pad_delay;
|
||||
u8 nmi_sta_id;
|
||||
u8 ndi_local_addr[ETH_ALEN];
|
||||
u8 reserved[2];
|
||||
} __packed; /* STA_CMD_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_aux_sta_cmd - command for AUX STA configuration
|
||||
* ( AUX_STA_CMD = 0xB )
|
||||
|
||||
@@ -57,8 +57,7 @@ enum iwl_mac_protection_flags {
|
||||
* @FW_MAC_TYPE_P2P_DEVICE: P2P Device
|
||||
* @FW_MAC_TYPE_P2P_STA: P2P client
|
||||
* @FW_MAC_TYPE_GO: P2P GO
|
||||
* @FW_MAC_TYPE_TEST: ?
|
||||
* @FW_MAC_TYPE_MAX: highest support MAC type
|
||||
* @FW_MAC_TYPE_NAN: NAN (since version 4)
|
||||
*/
|
||||
enum iwl_mac_types {
|
||||
FW_MAC_TYPE_FIRST = 1,
|
||||
@@ -70,8 +69,7 @@ enum iwl_mac_types {
|
||||
FW_MAC_TYPE_P2P_DEVICE,
|
||||
FW_MAC_TYPE_P2P_STA,
|
||||
FW_MAC_TYPE_GO,
|
||||
FW_MAC_TYPE_TEST,
|
||||
FW_MAC_TYPE_MAX = FW_MAC_TYPE_TEST
|
||||
FW_MAC_TYPE_NAN,
|
||||
}; /* MAC_CONTEXT_TYPE_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
|
||||
@@ -204,7 +204,7 @@ struct iwl_nvm_get_info_phy {
|
||||
} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
|
||||
|
||||
#define IWL_NUM_CHANNELS_V1 51
|
||||
#define IWL_NUM_CHANNELS 110
|
||||
#define IWL_NUM_CHANNELS_V2 110
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_get_info_regulatory_v1 - regulatory information
|
||||
@@ -227,7 +227,7 @@ struct iwl_nvm_get_info_regulatory_v1 {
|
||||
struct iwl_nvm_get_info_regulatory {
|
||||
__le32 lar_enabled;
|
||||
__le32 n_channels;
|
||||
__le32 channel_profile[IWL_NUM_CHANNELS];
|
||||
__le32 channel_profile[IWL_NUM_CHANNELS_V2];
|
||||
} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */
|
||||
|
||||
/**
|
||||
@@ -701,13 +701,23 @@ struct iwl_pnvm_init_complete_ntfy {
|
||||
#define UATS_TABLE_COL_SIZE 13
|
||||
|
||||
/**
|
||||
* struct iwl_mcc_allowed_ap_type_cmd - struct for MCC_ALLOWED_AP_TYPE_CMD
|
||||
* struct iwl_mcc_allowed_ap_type_cmd_v1 - struct for MCC_ALLOWED_AP_TYPE_CMD
|
||||
* @mcc_to_ap_type_map: mapping an MCC to 6 GHz AP type support (UATS)
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_mcc_allowed_ap_type_cmd {
|
||||
struct iwl_mcc_allowed_ap_type_cmd_v1 {
|
||||
u8 mcc_to_ap_type_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
|
||||
__le16 reserved;
|
||||
} __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mcc_allowed_ap_type_cmd - struct for MCC_ALLOWED_AP_TYPE_CMD
|
||||
* @mcc_to_ap_type_map: mapping an MCC to 6 GHz AP type support (UATS)
|
||||
* @mcc_to_ap_type_unii9_map: mapping an MCC to UNII-9 AP type support allowed
|
||||
*/
|
||||
struct iwl_mcc_allowed_ap_type_cmd {
|
||||
u8 mcc_to_ap_type_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
|
||||
u8 mcc_to_ap_type_unii9_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
|
||||
} __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_2 */
|
||||
|
||||
#endif /* __iwl_fw_api_nvm_reg_h__ */
|
||||
|
||||
@@ -269,6 +269,7 @@ enum iwl_dev_tx_power_cmd_mode {
|
||||
#define IWL_NUM_CHAIN_LIMITS 2
|
||||
#define IWL_NUM_SUB_BANDS_V1 5
|
||||
#define IWL_NUM_SUB_BANDS_V2 11
|
||||
#define IWL_NUM_SUB_BANDS_V3 12
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_common - Common part of the TX power reduction cmd
|
||||
@@ -425,24 +426,38 @@ struct iwl_dev_tx_power_cmd_v10 {
|
||||
__le32 flags;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_10 */
|
||||
|
||||
struct iwl_dev_tx_power_cmd_v11 {
|
||||
__le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3];
|
||||
u8 per_chain_restriction_changed;
|
||||
u8 reserved;
|
||||
__le32 timer_period;
|
||||
__le32 flags;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_11 */
|
||||
|
||||
/*
|
||||
* struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)
|
||||
* @common: common part of the command
|
||||
* @v9: version 9 part of the command
|
||||
* @v10: version 10 part of the command
|
||||
* @v11: version 11 part of the command
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd {
|
||||
struct iwl_dev_tx_power_common common;
|
||||
union {
|
||||
struct iwl_dev_tx_power_cmd_v9 v9;
|
||||
struct iwl_dev_tx_power_cmd_v10 v10;
|
||||
struct iwl_dev_tx_power_cmd_v11 v11;
|
||||
};
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_9_VER10 */
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_9
|
||||
* TX_REDUCED_POWER_API_S_VER_10
|
||||
* TX_REDUCED_POWER_API_S_VER_11
|
||||
*/
|
||||
|
||||
#define IWL_NUM_GEO_PROFILES 3
|
||||
#define IWL_NUM_GEO_PROFILES_V3 8
|
||||
#define IWL_NUM_BANDS_PER_CHAIN_V1 2
|
||||
#define IWL_NUM_BANDS_PER_CHAIN_V2 3
|
||||
#define IWL_NUM_BANDS_PER_CHAIN_V6 4
|
||||
|
||||
/**
|
||||
* enum iwl_geo_per_chain_offset_operation - type of operation
|
||||
@@ -524,12 +539,25 @@ struct iwl_geo_tx_power_profiles_cmd_v5 {
|
||||
__le32 table_revision;
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_5 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profiles_cmd_v6 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @bios_hdr: describes the revision and the source of the BIOS
|
||||
*/
|
||||
struct iwl_geo_tx_power_profiles_cmd_v6 {
|
||||
__le32 ops;
|
||||
struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V6];
|
||||
struct iwl_bios_config_hdr bios_hdr;
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_6 */
|
||||
|
||||
union iwl_geo_tx_power_profiles_cmd {
|
||||
struct iwl_geo_tx_power_profiles_cmd_v1 v1;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v2 v2;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v3 v3;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v4 v4;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v5 v5;
|
||||
struct iwl_geo_tx_power_profiles_cmd_v6 v6;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -573,6 +601,7 @@ enum iwl_ppag_flags {
|
||||
* @v1: command version 1 structure.
|
||||
* @v5: command version 5 structure.
|
||||
* @v7: command version 7 structure.
|
||||
* @v8: command version 8 structure.
|
||||
* @v1.flags: values from &enum iwl_ppag_flags
|
||||
* @v1.gain: table of antenna gain values per chain and sub-band
|
||||
* @v1.reserved: reserved
|
||||
@@ -581,6 +610,8 @@ enum iwl_ppag_flags {
|
||||
* @v7.ppag_config_info: see @struct bios_value_u32
|
||||
* @v7.gain: table of antenna gain values per chain and sub-band
|
||||
* @v7.reserved: reserved
|
||||
* @v8.ppag_config_info: see @struct bios_value_u32
|
||||
* @v8.gain: table of antenna gain values per chain and sub-band
|
||||
*/
|
||||
union iwl_ppag_table_cmd {
|
||||
struct {
|
||||
@@ -598,6 +629,10 @@ union iwl_ppag_table_cmd {
|
||||
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
|
||||
s8 reserved[2];
|
||||
} __packed v7; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */
|
||||
struct {
|
||||
struct bios_value_u32 ppag_config_info;
|
||||
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3];
|
||||
} __packed v8; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_8 */
|
||||
} __packed;
|
||||
|
||||
#define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
|
||||
|
||||
@@ -985,6 +985,7 @@ struct iwl_scan_probe_params_v4 {
|
||||
} __packed; /* SCAN_PROBE_PARAMS_API_S_VER_4 */
|
||||
|
||||
#define SCAN_MAX_NUM_CHANS_V3 67
|
||||
#define SCAN_MAX_NUM_CHANS_V4 68
|
||||
|
||||
/**
|
||||
* struct iwl_scan_channel_params_v4 - channel params
|
||||
@@ -1027,6 +1028,24 @@ struct iwl_scan_channel_params_v7 {
|
||||
struct iwl_scan_channel_cfg_umac channel_config[SCAN_MAX_NUM_CHANS_V3];
|
||||
} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_channel_params_v8 - channel params
|
||||
* @flags: channel flags &enum iwl_scan_channel_flags
|
||||
* @count: num of channels in scan request
|
||||
* @n_aps_override: override the number of APs the FW uses to calculate dwell
|
||||
* time when adaptive dwell is used.
|
||||
* Channel k will use n_aps_override[i] when BIT(20 + i) is set in
|
||||
* channel_config[k].flags
|
||||
* @channel_config: array of explicit channel configurations
|
||||
* for 2.4Ghz and 5.2Ghz bands
|
||||
*/
|
||||
struct iwl_scan_channel_params_v8 {
|
||||
u8 flags;
|
||||
u8 count;
|
||||
u8 n_aps_override[2];
|
||||
struct iwl_scan_channel_cfg_umac channel_config[SCAN_MAX_NUM_CHANS_V4];
|
||||
} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_8 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_general_params_v11 - channel params
|
||||
* @flags: &enum iwl_umac_scan_general_flags_v2
|
||||
@@ -1109,6 +1128,20 @@ struct iwl_scan_req_params_v17 {
|
||||
struct iwl_scan_probe_params_v4 probe_params;
|
||||
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_17 - 14 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_params_v18 - scan request parameters (v18)
|
||||
* @general_params: &struct iwl_scan_general_params_v11
|
||||
* @channel_params: &struct iwl_scan_channel_params_v8
|
||||
* @periodic_params: &struct iwl_scan_periodic_parms_v1
|
||||
* @probe_params: &struct iwl_scan_probe_params_v4
|
||||
*/
|
||||
struct iwl_scan_req_params_v18 {
|
||||
struct iwl_scan_general_params_v11 general_params;
|
||||
struct iwl_scan_channel_params_v8 channel_params;
|
||||
struct iwl_scan_periodic_parms_v1 periodic_params;
|
||||
struct iwl_scan_probe_params_v4 probe_params;
|
||||
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_18 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_umac_v12 - scan request command (v12)
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
@@ -1133,6 +1166,18 @@ struct iwl_scan_req_umac_v17 {
|
||||
struct iwl_scan_req_params_v17 scan_params;
|
||||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_17 - 14 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_umac_v18 - scan request command (v18)
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
|
||||
* @scan_params: scan parameters
|
||||
*/
|
||||
struct iwl_scan_req_umac_v18 {
|
||||
__le32 uid;
|
||||
__le32 ooc_priority;
|
||||
struct iwl_scan_req_params_v18 scan_params;
|
||||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_18 */
|
||||
|
||||
/**
|
||||
* struct iwl_umac_scan_abort - scan abort command
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
|
||||
@@ -598,7 +598,6 @@ struct iwl_stats_ntfy_per_sta {
|
||||
} __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_PHY_OPERATIONAL 3
|
||||
#define IWL_STATS_MAX_FW_LINKS (IWL_FW_MAX_LINK_ID + 1)
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_notif_oper - statistics notification
|
||||
@@ -610,7 +609,7 @@ struct iwl_stats_ntfy_per_sta {
|
||||
*/
|
||||
struct iwl_system_statistics_notif_oper {
|
||||
__le32 time_stamp;
|
||||
struct iwl_stats_ntfy_per_link per_link[IWL_STATS_MAX_FW_LINKS];
|
||||
struct iwl_stats_ntfy_per_link per_link[IWL_FW_MAX_LINKS];
|
||||
struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */
|
||||
@@ -624,7 +623,7 @@ struct iwl_system_statistics_notif_oper {
|
||||
*/
|
||||
struct iwl_system_statistics_part1_notif_oper {
|
||||
__le32 time_stamp;
|
||||
struct iwl_stats_ntfy_part1_per_link per_link[IWL_STATS_MAX_FW_LINKS];
|
||||
struct iwl_stats_ntfy_part1_per_link per_link[IWL_FW_MAX_LINKS];
|
||||
__le32 per_phy_crc_error_stats[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_API_S_VER_4 */
|
||||
|
||||
|
||||
@@ -2933,7 +2933,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
||||
IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n",
|
||||
le32_to_cpu(desc->trig_desc.type));
|
||||
|
||||
queue_delayed_work(system_unbound_wq, &wk_data->wk,
|
||||
queue_delayed_work(system_dfl_wq, &wk_data->wk,
|
||||
usecs_to_jiffies(delay));
|
||||
|
||||
return 0;
|
||||
@@ -3237,7 +3237,7 @@ int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
|
||||
if (sync)
|
||||
iwl_fw_dbg_collect_sync(fwrt, idx);
|
||||
else
|
||||
queue_delayed_work(system_unbound_wq,
|
||||
queue_delayed_work(system_dfl_wq,
|
||||
&fwrt->dump.wks[idx].wk,
|
||||
usecs_to_jiffies(delay));
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2026 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@@ -128,19 +128,11 @@ static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt)
|
||||
|
||||
IWL_ERR(fwrt, "0x%08X | %s\n", table.error_id,
|
||||
iwl_fw_lookup_assert_desc(table.error_id));
|
||||
IWL_ERR(fwrt, "0x%08X | umac branchlink1\n", table.blink1);
|
||||
IWL_ERR(fwrt, "0x%08X | umac branchlink2\n", table.blink2);
|
||||
IWL_ERR(fwrt, "0x%08X | umac interruptlink1\n", table.ilink1);
|
||||
IWL_ERR(fwrt, "0x%08X | umac interruptlink2\n", table.ilink2);
|
||||
IWL_ERR(fwrt, "0x%08X | umac data1\n", table.data1);
|
||||
IWL_ERR(fwrt, "0x%08X | umac data2\n", table.data2);
|
||||
IWL_ERR(fwrt, "0x%08X | umac data3\n", table.data3);
|
||||
IWL_ERR(fwrt, "0x%08X | umac major\n", table.umac_major);
|
||||
IWL_ERR(fwrt, "0x%08X | umac minor\n", table.umac_minor);
|
||||
IWL_ERR(fwrt, "0x%08X | frame pointer\n", table.frame_pointer);
|
||||
IWL_ERR(fwrt, "0x%08X | stack pointer\n", table.stack_pointer);
|
||||
IWL_ERR(fwrt, "0x%08X | last host cmd\n", table.cmd_header);
|
||||
IWL_ERR(fwrt, "0x%08X | isr status reg\n", table.nic_isr_pref);
|
||||
}
|
||||
|
||||
static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_num)
|
||||
@@ -200,39 +192,10 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
|
||||
|
||||
IWL_ERR(fwrt, "0x%08X | %-28s\n", table.error_id,
|
||||
iwl_fw_lookup_assert_desc(table.error_id));
|
||||
IWL_ERR(fwrt, "0x%08X | trm_hw_status0\n", table.trm_hw_status0);
|
||||
IWL_ERR(fwrt, "0x%08X | trm_hw_status1\n", table.trm_hw_status1);
|
||||
IWL_ERR(fwrt, "0x%08X | branchlink2\n", table.blink2);
|
||||
IWL_ERR(fwrt, "0x%08X | interruptlink1\n", table.ilink1);
|
||||
IWL_ERR(fwrt, "0x%08X | interruptlink2\n", table.ilink2);
|
||||
IWL_ERR(fwrt, "0x%08X | data1\n", table.data1);
|
||||
IWL_ERR(fwrt, "0x%08X | data2\n", table.data2);
|
||||
IWL_ERR(fwrt, "0x%08X | data3\n", table.data3);
|
||||
IWL_ERR(fwrt, "0x%08X | beacon time\n", table.bcon_time);
|
||||
IWL_ERR(fwrt, "0x%08X | tsf low\n", table.tsf_low);
|
||||
IWL_ERR(fwrt, "0x%08X | tsf hi\n", table.tsf_hi);
|
||||
IWL_ERR(fwrt, "0x%08X | time gp1\n", table.gp1);
|
||||
IWL_ERR(fwrt, "0x%08X | time gp2\n", table.gp2);
|
||||
IWL_ERR(fwrt, "0x%08X | uCode revision type\n", table.fw_rev_type);
|
||||
IWL_ERR(fwrt, "0x%08X | uCode version major\n", table.major);
|
||||
IWL_ERR(fwrt, "0x%08X | uCode version minor\n", table.minor);
|
||||
IWL_ERR(fwrt, "0x%08X | hw version\n", table.hw_ver);
|
||||
IWL_ERR(fwrt, "0x%08X | board version\n", table.brd_ver);
|
||||
IWL_ERR(fwrt, "0x%08X | hcmd\n", table.hcmd);
|
||||
IWL_ERR(fwrt, "0x%08X | isr0\n", table.isr0);
|
||||
IWL_ERR(fwrt, "0x%08X | isr1\n", table.isr1);
|
||||
IWL_ERR(fwrt, "0x%08X | isr2\n", table.isr2);
|
||||
IWL_ERR(fwrt, "0x%08X | isr3\n", table.isr3);
|
||||
IWL_ERR(fwrt, "0x%08X | isr4\n", table.isr4);
|
||||
IWL_ERR(fwrt, "0x%08X | last cmd Id\n", table.last_cmd_id);
|
||||
IWL_ERR(fwrt, "0x%08X | wait_event\n", table.wait_event);
|
||||
IWL_ERR(fwrt, "0x%08X | l2p_control\n", table.l2p_control);
|
||||
IWL_ERR(fwrt, "0x%08X | l2p_duration\n", table.l2p_duration);
|
||||
IWL_ERR(fwrt, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid);
|
||||
IWL_ERR(fwrt, "0x%08X | l2p_addr_match\n", table.l2p_addr_match);
|
||||
IWL_ERR(fwrt, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
|
||||
IWL_ERR(fwrt, "0x%08X | timestamp\n", table.u_timestamp);
|
||||
IWL_ERR(fwrt, "0x%08X | flow_handler\n", table.flow_handler);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -264,7 +227,6 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt, int idx)
|
||||
struct iwl_trans *trans = fwrt->trans;
|
||||
struct iwl_tcm_error_event_table table = {};
|
||||
u32 base = fwrt->trans->dbg.tcm_error_event_table[idx];
|
||||
int i;
|
||||
u32 flag = idx ? IWL_ERROR_EVENT_TABLE_TCM2 :
|
||||
IWL_ERROR_EVENT_TABLE_TCM1;
|
||||
|
||||
@@ -275,23 +237,10 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt, int idx)
|
||||
|
||||
IWL_ERR(fwrt, "TCM%d status:\n", idx + 1);
|
||||
IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm branchlink2\n", table.blink2);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm interruptlink1\n", table.ilink1);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm interruptlink2\n", table.ilink2);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm data1\n", table.data1);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm data2\n", table.data2);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm data3\n", table.data3);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm log PC\n", table.logpc);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm frame pointer\n", table.frame_pointer);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm stack pointer\n", table.stack_pointer);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm msg ID\n", table.msgid);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm ISR status\n", table.isr);
|
||||
for (i = 0; i < ARRAY_SIZE(table.hw_status); i++)
|
||||
IWL_ERR(fwrt, "0x%08X | tcm HW status[%d]\n",
|
||||
table.hw_status[i], i);
|
||||
for (i = 0; i < ARRAY_SIZE(table.sw_status); i++)
|
||||
IWL_ERR(fwrt, "0x%08X | tcm SW status[%d]\n",
|
||||
table.sw_status[i], i);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -338,26 +287,10 @@ static void iwl_fwrt_dump_rcm_error_log(struct iwl_fw_runtime *fwrt, int idx)
|
||||
|
||||
IWL_ERR(fwrt, "RCM%d status:\n", idx + 1);
|
||||
IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm branchlink2\n", table.blink2);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm interruptlink1\n", table.ilink1);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm interruptlink2\n", table.ilink2);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm data1\n", table.data1);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm data2\n", table.data2);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm data3\n", table.data3);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm log PC\n", table.logpc);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm frame pointer\n", table.frame_pointer);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm stack pointer\n", table.stack_pointer);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm msg ID\n", table.msgid);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm ISR status\n", table.isr);
|
||||
IWL_ERR(fwrt, "0x%08X | frame HW status\n", table.frame_hw_status);
|
||||
IWL_ERR(fwrt, "0x%08X | LMAC-to-RCM request mbox\n",
|
||||
table.mbx_lmac_to_rcm_req);
|
||||
IWL_ERR(fwrt, "0x%08X | RCM-to-LMAC request mbox\n",
|
||||
table.mbx_rcm_to_lmac_req);
|
||||
IWL_ERR(fwrt, "0x%08X | MAC header control\n", table.mh_ctl);
|
||||
IWL_ERR(fwrt, "0x%08X | MAC header addr1 low\n", table.mh_addr1_lo);
|
||||
IWL_ERR(fwrt, "0x%08X | MAC header info\n", table.mh_info);
|
||||
IWL_ERR(fwrt, "0x%08X | MAC header error\n", table.mh_err);
|
||||
}
|
||||
|
||||
static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
|
||||
|
||||
@@ -103,6 +103,7 @@ enum iwl_ucode_tlv_type {
|
||||
IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,
|
||||
IWL_UCODE_TLV_CURRENT_PC = 68,
|
||||
IWL_UCODE_TLV_FSEQ_BIN_VERSION = 72,
|
||||
IWL_UCODE_TLV_CMD_BIOS_TABLE = 73,
|
||||
|
||||
/* contains sub-sections like PNVM file does (did) */
|
||||
IWL_UCODE_TLV_PNVM_DATA = 74,
|
||||
@@ -1040,6 +1041,20 @@ struct iwl_fw_cmd_version {
|
||||
u8 notif_ver;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_cmd_bios_table - firmware command BIOS revision entry
|
||||
* @cmd: command ID
|
||||
* @group: group ID
|
||||
* @max_acpi_revision: max supported ACPI revision of command.
|
||||
* @max_uefi_revision: max supported UEFI revision of command.
|
||||
*/
|
||||
struct iwl_fw_cmd_bios_table {
|
||||
u8 cmd;
|
||||
u8 group;
|
||||
u8 max_acpi_revision;
|
||||
u8 max_uefi_revision;
|
||||
} __packed;
|
||||
|
||||
struct iwl_fw_tcm_error_addr {
|
||||
__le32 addr;
|
||||
}; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */
|
||||
|
||||
@@ -1,11 +1,41 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright(c) 2019 - 2021 Intel Corporation
|
||||
* Copyright(c) 2024 Intel Corporation
|
||||
* Copyright(c) 2024 - 2025 Intel Corporation
|
||||
*/
|
||||
#include <fw/api/commands.h>
|
||||
#include "img.h"
|
||||
|
||||
u8 iwl_fw_lookup_cmd_bios_supported_revision(const struct iwl_fw *fw,
|
||||
enum bios_source table_source,
|
||||
u32 cmd_id, u8 def)
|
||||
{
|
||||
const struct iwl_fw_cmd_bios_table *entry;
|
||||
/* prior to LONG_GROUP, we never used this CMD version API */
|
||||
u8 grp = iwl_cmd_groupid(cmd_id) ?: LONG_GROUP;
|
||||
u8 cmd = iwl_cmd_opcode(cmd_id);
|
||||
|
||||
if (table_source != BIOS_SOURCE_ACPI &&
|
||||
table_source != BIOS_SOURCE_UEFI)
|
||||
return def;
|
||||
|
||||
if (!fw->ucode_capa.cmd_bios_tables ||
|
||||
!fw->ucode_capa.n_cmd_bios_tables)
|
||||
return def;
|
||||
|
||||
entry = fw->ucode_capa.cmd_bios_tables;
|
||||
for (int i = 0; i < fw->ucode_capa.n_cmd_bios_tables; i++, entry++) {
|
||||
if (entry->group == grp && entry->cmd == cmd) {
|
||||
if (table_source == BIOS_SOURCE_ACPI)
|
||||
return entry->max_acpi_revision;
|
||||
return entry->max_uefi_revision;
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_fw_lookup_cmd_bios_supported_revision);
|
||||
|
||||
u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def)
|
||||
{
|
||||
const struct iwl_fw_cmd_version *entry;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "api/dbg-tlv.h"
|
||||
#include "api/nvm-reg.h"
|
||||
|
||||
#include "file.h"
|
||||
#include "error-dump.h"
|
||||
@@ -57,6 +58,9 @@ struct iwl_ucode_capabilities {
|
||||
|
||||
const struct iwl_fw_cmd_version *cmd_versions;
|
||||
u32 n_cmd_versions;
|
||||
|
||||
const struct iwl_fw_cmd_bios_table *cmd_bios_tables;
|
||||
u32 n_cmd_bios_tables;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
@@ -274,6 +278,10 @@ iwl_get_ucode_image(const struct iwl_fw *fw, enum iwl_ucode_type ucode_type)
|
||||
return &fw->img[ucode_type];
|
||||
}
|
||||
|
||||
u8 iwl_fw_lookup_cmd_bios_supported_revision(const struct iwl_fw *fw,
|
||||
enum bios_source table_source,
|
||||
u32 cmd_id, u8 def);
|
||||
|
||||
u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def);
|
||||
|
||||
u8 iwl_fw_lookup_notif_ver(const struct iwl_fw *fw, u8 grp, u8 cmd, u8 def);
|
||||
|
||||
@@ -241,6 +241,10 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
|
||||
int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b };
|
||||
int i, j;
|
||||
|
||||
if (WARN_ON_ONCE(n_subbands >
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands)))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) {
|
||||
struct iwl_sar_profile *prof;
|
||||
|
||||
@@ -300,132 +304,6 @@ int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_fill_profile);
|
||||
|
||||
static bool iwl_ppag_value_valid(struct iwl_fw_runtime *fwrt, int chain,
|
||||
int subband)
|
||||
{
|
||||
s8 ppag_val = fwrt->ppag_chains[chain].subbands[subband];
|
||||
|
||||
if ((subband == 0 &&
|
||||
(ppag_val > IWL_PPAG_MAX_LB || ppag_val < IWL_PPAG_MIN_LB)) ||
|
||||
(subband != 0 &&
|
||||
(ppag_val > IWL_PPAG_MAX_HB || ppag_val < IWL_PPAG_MIN_HB))) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Invalid PPAG value: %d\n", ppag_val);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Utility function for iwlmvm and iwlxvt */
|
||||
int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
union iwl_ppag_table_cmd *cmd, int *cmd_size)
|
||||
{
|
||||
u8 cmd_ver;
|
||||
int i, j, num_sub_bands;
|
||||
s8 *gain;
|
||||
bool send_ppag_always;
|
||||
|
||||
/* many firmware images for JF lie about this */
|
||||
if (CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG capability not supported by FW, command not sent.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
||||
WIDE_ID(PHY_OPS_GROUP,
|
||||
PER_PLATFORM_ANT_GAIN_CMD), 1);
|
||||
/*
|
||||
* Starting from ver 4, driver needs to send the PPAG CMD regardless
|
||||
* if PPAG is enabled/disabled or valid/invalid.
|
||||
*/
|
||||
send_ppag_always = cmd_ver > 3;
|
||||
|
||||
/* Don't send PPAG if it is disabled */
|
||||
if (!send_ppag_always && !fwrt->ppag_flags) {
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
|
||||
if (cmd_ver == 1) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
|
||||
gain = cmd->v1.gain[0];
|
||||
*cmd_size = sizeof(cmd->v1);
|
||||
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V1_MASK);
|
||||
if (fwrt->ppag_bios_rev >= 1) {
|
||||
/* in this case FW supports revision 0 */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table rev is %d, send truncated table\n",
|
||||
fwrt->ppag_bios_rev);
|
||||
}
|
||||
} else if (cmd_ver == 5) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
||||
gain = cmd->v5.gain[0];
|
||||
*cmd_size = sizeof(cmd->v5);
|
||||
cmd->v5.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V5_MASK);
|
||||
if (fwrt->ppag_bios_rev == 0) {
|
||||
/* in this case FW supports revisions 1,2 or 3 */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table rev is 0, send padded table\n");
|
||||
}
|
||||
} else if (cmd_ver == 7) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
||||
gain = cmd->v7.gain[0];
|
||||
*cmd_size = sizeof(cmd->v7);
|
||||
cmd->v7.ppag_config_info.hdr.table_source =
|
||||
fwrt->ppag_bios_source;
|
||||
cmd->v7.ppag_config_info.hdr.table_revision =
|
||||
fwrt->ppag_bios_rev;
|
||||
cmd->v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags);
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* ppag mode */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG MODE bits were read from bios: %d\n",
|
||||
fwrt->ppag_flags);
|
||||
|
||||
if (cmd_ver == 1 &&
|
||||
!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) {
|
||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
|
||||
IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
|
||||
}
|
||||
|
||||
/* The 'flags' field is the same in v1 and v5 so we can just
|
||||
* use v1 to access it.
|
||||
*/
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG MODE bits going to be sent: %d\n",
|
||||
(cmd_ver < 7) ? le32_to_cpu(cmd->v1.flags) :
|
||||
le32_to_cpu(cmd->v7.ppag_config_info.value));
|
||||
|
||||
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
|
||||
for (j = 0; j < num_sub_bands; j++) {
|
||||
if (!send_ppag_always &&
|
||||
!iwl_ppag_value_valid(fwrt, i, j))
|
||||
return -EINVAL;
|
||||
|
||||
gain[i * num_sub_bands + j] =
|
||||
fwrt->ppag_chains[i].subbands[j];
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table: chain[%d] band[%d]: gain = %d\n",
|
||||
i, j, gain[i * num_sub_bands + j]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fill_ppag_table);
|
||||
|
||||
bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
if (!dmi_check_system(dmi_ppag_approved_list)) {
|
||||
@@ -440,6 +318,27 @@ bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt)
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_is_ppag_approved);
|
||||
|
||||
/* Print the PPAG table as read from BIOS */
|
||||
void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG table as read from BIOS:\n");
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG revision = %d\n", fwrt->ppag_bios_rev);
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG flags = 0x%x\n", fwrt->ppag_flags);
|
||||
|
||||
if (WARN_ON_ONCE(n_subbands >
|
||||
ARRAY_SIZE(fwrt->ppag_chains[0].subbands)))
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fwrt->ppag_chains); i++)
|
||||
for (j = 0; j < n_subbands; j++)
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"ppag_chains[%d].subbands[%d] = %d\n",
|
||||
i, j,
|
||||
fwrt->ppag_chains[i].subbands[j]);
|
||||
}
|
||||
|
||||
bool iwl_is_tas_approved(void)
|
||||
{
|
||||
return dmi_check_system(dmi_tas_approved_list);
|
||||
|
||||
@@ -21,10 +21,11 @@
|
||||
*/
|
||||
#define BIOS_SAR_MAX_CHAINS_PER_PROFILE 4
|
||||
#define BIOS_SAR_NUM_CHAINS 2
|
||||
#define BIOS_SAR_MAX_SUB_BANDS_NUM 11
|
||||
#define BIOS_SAR_MAX_SUB_BANDS_NUM 12
|
||||
#define BIOS_PPAG_MAX_SUB_BANDS_NUM 12
|
||||
|
||||
#define BIOS_GEO_NUM_CHAINS 2
|
||||
#define BIOS_GEO_MAX_NUM_BANDS 3
|
||||
#define BIOS_GEO_MAX_NUM_BANDS 4
|
||||
#define BIOS_GEO_MAX_PROFILE_NUM 8
|
||||
#define BIOS_GEO_MIN_PROFILE_NUM 3
|
||||
|
||||
@@ -100,7 +101,7 @@ struct iwl_geo_profile {
|
||||
|
||||
/* Same thing as with SAR, all revisions fit in revision 2 */
|
||||
struct iwl_ppag_chain {
|
||||
s8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];
|
||||
s8 subbands[BIOS_PPAG_MAX_SUB_BANDS_NUM];
|
||||
};
|
||||
|
||||
struct iwl_tas_data {
|
||||
@@ -180,6 +181,9 @@ enum iwl_dsm_masks_reg {
|
||||
|
||||
struct iwl_fw_runtime;
|
||||
|
||||
/* Print the PPAG table as read from BIOS */
|
||||
void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands);
|
||||
|
||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
|
||||
@@ -190,10 +194,6 @@ int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
|
||||
__le16 *per_chain, u32 n_tables, u32 n_subbands,
|
||||
int prof_a, int prof_b);
|
||||
|
||||
int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
union iwl_ppag_table_cmd *cmd,
|
||||
int *cmd_size);
|
||||
|
||||
bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
bool iwl_is_tas_approved(void);
|
||||
|
||||
@@ -106,13 +106,14 @@ struct iwl_txf_iter_data {
|
||||
* @cur_fw_img: current firmware image, must be maintained by
|
||||
* the driver by calling &iwl_fw_set_current_image()
|
||||
* @dump: debug dump data
|
||||
* @uats_table: AP type table
|
||||
* @uats_valid: is AP type table valid
|
||||
* @ap_type_cmd: AP type tables (for enablement on 6 GHz)
|
||||
* @ap_type_cmd_valid: if &ap_type_cmd is valid
|
||||
* @uefi_tables_lock_status: The status of the WIFI GUID UEFI variables lock:
|
||||
* 0: Unlocked, 1 and 2: Locked.
|
||||
* Only read the UEFI variables if locked.
|
||||
* @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables
|
||||
* @geo_profiles: geographic profiles as read from WGDS BIOS table
|
||||
* @geo_bios_source: see &enum bios_source
|
||||
* @phy_filters: specific phy filters as read from WPFC BIOS table
|
||||
* @ppag_bios_rev: PPAG BIOS revision
|
||||
* @ppag_bios_source: see &enum bios_source
|
||||
@@ -204,6 +205,7 @@ struct iwl_fw_runtime {
|
||||
u8 sar_chain_b_profile;
|
||||
u8 reduced_power_flags;
|
||||
struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
|
||||
enum bios_source geo_bios_source;
|
||||
u32 geo_rev;
|
||||
u32 geo_num_profiles;
|
||||
bool geo_enabled;
|
||||
@@ -213,8 +215,8 @@ struct iwl_fw_runtime {
|
||||
u8 ppag_bios_source;
|
||||
struct iwl_sar_offset_mapping_cmd sgom_table;
|
||||
bool sgom_enabled;
|
||||
struct iwl_mcc_allowed_ap_type_cmd uats_table;
|
||||
bool uats_valid;
|
||||
struct iwl_mcc_allowed_ap_type_cmd ap_type_cmd;
|
||||
bool ap_type_cmd_valid;
|
||||
u8 uefi_tables_lock_status;
|
||||
struct iwl_phy_specific_cfg phy_filters;
|
||||
enum bios_source dsm_source;
|
||||
|
||||
@@ -402,11 +402,11 @@ static int iwl_uefi_uats_parse(struct uefi_cnv_wlan_uats_data *uats_data,
|
||||
if (uats_data->revision != 1)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(fwrt->uats_table.mcc_to_ap_type_map,
|
||||
memcpy(fwrt->ap_type_cmd.mcc_to_ap_type_map,
|
||||
uats_data->mcc_to_ap_type_map,
|
||||
sizeof(fwrt->uats_table.mcc_to_ap_type_map));
|
||||
sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_map));
|
||||
|
||||
fwrt->uats_valid = true;
|
||||
fwrt->ap_type_cmd_valid = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -429,12 +429,61 @@ void iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_uats_table);
|
||||
|
||||
static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt,
|
||||
struct uefi_sar_profile *uefi_sar_prof,
|
||||
u8 prof_index, bool enabled)
|
||||
void iwl_uefi_get_uneb_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
memcpy(&fwrt->sar_profiles[prof_index].chains, uefi_sar_prof,
|
||||
sizeof(struct uefi_sar_profile));
|
||||
struct uefi_cnv_wlan_uneb_data *data;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UNEB_NAME,
|
||||
"UNEB", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
|
||||
if (data->revision != 1) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Cannot read UNEB table. rev is invalid\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(sizeof(data->mcc_to_ap_type_map) !=
|
||||
sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_unii9_map));
|
||||
|
||||
memcpy(fwrt->ap_type_cmd.mcc_to_ap_type_unii9_map,
|
||||
data->mcc_to_ap_type_map,
|
||||
sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_unii9_map));
|
||||
|
||||
fwrt->ap_type_cmd_valid = true;
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_uneb_table);
|
||||
|
||||
static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt,
|
||||
const u8 *vals, u8 prof_index,
|
||||
u8 num_subbands, bool enabled)
|
||||
{
|
||||
struct iwl_sar_profile *sar_prof = &fwrt->sar_profiles[prof_index];
|
||||
|
||||
/*
|
||||
* Make sure fwrt has enough room to hold the data
|
||||
* coming from the UEFI table
|
||||
*/
|
||||
if (WARN_ON(ARRAY_SIZE(sar_prof->chains) *
|
||||
ARRAY_SIZE(sar_prof->chains[0].subbands) <
|
||||
UEFI_SAR_MAX_CHAINS_PER_PROFILE * num_subbands))
|
||||
return;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(sar_prof->chains) !=
|
||||
UEFI_SAR_MAX_CHAINS_PER_PROFILE);
|
||||
|
||||
for (int chain = 0;
|
||||
chain < UEFI_SAR_MAX_CHAINS_PER_PROFILE;
|
||||
chain++) {
|
||||
for (int subband = 0; subband < num_subbands; subband++)
|
||||
sar_prof->chains[chain].subbands[subband] =
|
||||
vals[chain * num_subbands + subband];
|
||||
}
|
||||
|
||||
fwrt->sar_profiles[prof_index].enabled = enabled & IWL_SAR_ENABLE_MSK;
|
||||
}
|
||||
@@ -442,24 +491,46 @@ static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt,
|
||||
int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_wrds *data;
|
||||
unsigned long size;
|
||||
unsigned long expected_size;
|
||||
int num_subbands;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WRDS_NAME,
|
||||
"WRDS", sizeof(*data), NULL);
|
||||
"WRDS",
|
||||
UEFI_SAR_WRDS_TABLE_SIZE_REV2,
|
||||
&size);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_WRDS_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WRDS revision:%d\n",
|
||||
switch (data->revision) {
|
||||
case 2:
|
||||
expected_size = UEFI_SAR_WRDS_TABLE_SIZE_REV2;
|
||||
num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV2;
|
||||
break;
|
||||
case 3:
|
||||
expected_size = UEFI_SAR_WRDS_TABLE_SIZE_REV3;
|
||||
num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV3;
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Unsupported UEFI WRDS revision:%d\n",
|
||||
data->revision);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (size != expected_size) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The profile from WRDS is officially profile 1, but goes
|
||||
* into sar_profiles[0] (because we don't have a profile 0).
|
||||
*/
|
||||
iwl_uefi_set_sar_profile(fwrt, &data->sar_profile, 0, data->mode);
|
||||
iwl_uefi_set_sar_profile(fwrt, data->vals, 0,
|
||||
num_subbands, data->mode);
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
@@ -468,21 +539,40 @@ out:
|
||||
int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_ewrd *data;
|
||||
unsigned long expected_size;
|
||||
int i, ret = 0;
|
||||
unsigned long size;
|
||||
int num_subbands;
|
||||
int profile_size;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_EWRD_NAME,
|
||||
"EWRD", sizeof(*data), NULL);
|
||||
"EWRD",
|
||||
UEFI_SAR_EWRD_TABLE_SIZE_REV2,
|
||||
&size);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_EWRD_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI EWRD revision:%d\n",
|
||||
switch (data->revision) {
|
||||
case 2:
|
||||
expected_size = UEFI_SAR_EWRD_TABLE_SIZE_REV2;
|
||||
num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV2;
|
||||
profile_size = UEFI_SAR_PROFILE_SIZE_REV2;
|
||||
break;
|
||||
case 3:
|
||||
expected_size = UEFI_SAR_EWRD_TABLE_SIZE_REV3;
|
||||
num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV3;
|
||||
profile_size = UEFI_SAR_PROFILE_SIZE_REV3;
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Unsupported UEFI EWRD revision:%d\n",
|
||||
data->revision);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (data->num_profiles >= BIOS_SAR_MAX_PROFILE_NUM) {
|
||||
if (size != expected_size ||
|
||||
data->num_profiles >= BIOS_SAR_MAX_PROFILE_NUM) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -492,8 +582,8 @@ int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
* save them in sar_profiles[1-3] (because we don't
|
||||
* have profile 0). So in the array we start from 1.
|
||||
*/
|
||||
iwl_uefi_set_sar_profile(fwrt, &data->sar_profiles[i], i + 1,
|
||||
data->mode);
|
||||
iwl_uefi_set_sar_profile(fwrt, &data->vals[i * profile_size],
|
||||
i + 1, num_subbands, data->mode);
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
@@ -503,20 +593,39 @@ out:
|
||||
int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_wgds *data;
|
||||
int i, ret = 0;
|
||||
unsigned long expected_size;
|
||||
unsigned long size;
|
||||
int profile_size;
|
||||
int n_subbands;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WGDS_NAME,
|
||||
"WGDS", sizeof(*data), NULL);
|
||||
"WGDS", UEFI_WGDS_TABLE_SIZE_REV3,
|
||||
&size);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_WGDS_REVISION) {
|
||||
switch (data->revision) {
|
||||
case 3:
|
||||
expected_size = UEFI_WGDS_TABLE_SIZE_REV3;
|
||||
n_subbands = UEFI_GEO_NUM_BANDS_REV3;
|
||||
break;
|
||||
case 4:
|
||||
expected_size = UEFI_WGDS_TABLE_SIZE_REV4;
|
||||
n_subbands = UEFI_GEO_NUM_BANDS_REV4;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WGDS revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (size != expected_size) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (data->num_profiles < BIOS_GEO_MIN_PROFILE_NUM ||
|
||||
data->num_profiles > BIOS_GEO_MAX_PROFILE_NUM) {
|
||||
ret = -EINVAL;
|
||||
@@ -525,10 +634,31 @@ int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (WARN_ON(BIOS_GEO_MAX_PROFILE_NUM >
|
||||
ARRAY_SIZE(fwrt->geo_profiles) ||
|
||||
n_subbands > ARRAY_SIZE(fwrt->geo_profiles[0].bands) ||
|
||||
BIOS_GEO_NUM_CHAINS >
|
||||
ARRAY_SIZE(fwrt->geo_profiles[0].bands[0].chains))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fwrt->geo_rev = data->revision;
|
||||
for (i = 0; i < data->num_profiles; i++)
|
||||
memcpy(&fwrt->geo_profiles[i], &data->geo_profiles[i],
|
||||
sizeof(struct iwl_geo_profile));
|
||||
fwrt->geo_bios_source = BIOS_SOURCE_UEFI;
|
||||
profile_size = 3 * n_subbands;
|
||||
for (int prof = 0; prof < data->num_profiles; prof++) {
|
||||
const u8 *val = &data->vals[profile_size * prof];
|
||||
struct iwl_geo_profile *geo_prof = &fwrt->geo_profiles[prof];
|
||||
|
||||
for (int subband = 0; subband < n_subbands; subband++) {
|
||||
geo_prof->bands[subband].max = *val++;
|
||||
|
||||
for (int chain = 0;
|
||||
chain < BIOS_GEO_NUM_CHAINS;
|
||||
chain++)
|
||||
geo_prof->bands[subband].chains[chain] = *val++;
|
||||
}
|
||||
}
|
||||
|
||||
fwrt->geo_num_profiles = data->num_profiles;
|
||||
fwrt->geo_enabled = true;
|
||||
@@ -540,28 +670,66 @@ out:
|
||||
int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_ppag *data;
|
||||
int n_subbands;
|
||||
u32 valid_rev;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_PPAG_NAME,
|
||||
"PPAG", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
"PPAG", UEFI_PPAG_DATA_SIZE_V5,
|
||||
NULL);
|
||||
if (!IS_ERR(data)) {
|
||||
n_subbands = UEFI_PPAG_SUB_BANDS_NUM_REV5;
|
||||
valid_rev = BIT(5);
|
||||
|
||||
if (data->revision < IWL_UEFI_MIN_PPAG_REV ||
|
||||
data->revision > IWL_UEFI_MAX_PPAG_REV) {
|
||||
goto parse_table;
|
||||
}
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans,
|
||||
IWL_UEFI_PPAG_NAME,
|
||||
"PPAG",
|
||||
UEFI_PPAG_DATA_SIZE_V4,
|
||||
NULL);
|
||||
if (!IS_ERR(data)) {
|
||||
n_subbands = UEFI_PPAG_SUB_BANDS_NUM_REV4;
|
||||
/* revisions 1-4 have all the same size */
|
||||
valid_rev = BIT(1) | BIT(2) | BIT(3) | BIT(4);
|
||||
|
||||
goto parse_table;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
||||
parse_table:
|
||||
if (!(BIT(data->revision) & valid_rev)) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI PPAG revision:%d\n",
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Unsupported UEFI PPAG revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure fwrt has enough room to hold
|
||||
* data coming from the UEFI table
|
||||
*/
|
||||
if (WARN_ON(ARRAY_SIZE(fwrt->ppag_chains) *
|
||||
ARRAY_SIZE(fwrt->ppag_chains[0].subbands) <
|
||||
UEFI_PPAG_NUM_CHAINS * n_subbands)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fwrt->ppag_bios_rev = data->revision;
|
||||
fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes,
|
||||
fwrt->ppag_bios_rev);
|
||||
|
||||
BUILD_BUG_ON(sizeof(fwrt->ppag_chains) != sizeof(data->ppag_chains));
|
||||
memcpy(&fwrt->ppag_chains, &data->ppag_chains,
|
||||
sizeof(data->ppag_chains));
|
||||
for (int chain = 0; chain < UEFI_PPAG_NUM_CHAINS; chain++) {
|
||||
for (int subband = 0; subband < n_subbands; subband++)
|
||||
fwrt->ppag_chains[chain].subbands[subband] =
|
||||
data->vals[chain * n_subbands + subband];
|
||||
}
|
||||
|
||||
iwl_bios_print_ppag(fwrt, n_subbands);
|
||||
fwrt->ppag_bios_source = BIOS_SOURCE_UEFI;
|
||||
out:
|
||||
kfree(data);
|
||||
|
||||
@@ -25,16 +25,12 @@
|
||||
#define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing"
|
||||
#define IWL_UEFI_DSBR_NAME L"UefiCnvCommonDSBR"
|
||||
#define IWL_UEFI_WPFC_NAME L"WPFC"
|
||||
#define IWL_UEFI_UNEB_NAME L"CnvUefiWlanUNEB"
|
||||
|
||||
|
||||
#define IWL_SGOM_MAP_SIZE 339
|
||||
#define IWL_UATS_MAP_SIZE 339
|
||||
|
||||
#define IWL_UEFI_WRDS_REVISION 2
|
||||
#define IWL_UEFI_EWRD_REVISION 2
|
||||
#define IWL_UEFI_WGDS_REVISION 3
|
||||
#define IWL_UEFI_MIN_PPAG_REV 1
|
||||
#define IWL_UEFI_MAX_PPAG_REV 4
|
||||
#define IWL_UEFI_MIN_WTAS_REVISION 1
|
||||
#define IWL_UEFI_MAX_WTAS_REVISION 2
|
||||
#define IWL_UEFI_SPLC_REVISION 0
|
||||
@@ -63,6 +59,9 @@ struct uefi_cnv_wlan_uats_data {
|
||||
u8 mcc_to_ap_type_map[IWL_UATS_MAP_SIZE - 1];
|
||||
} __packed;
|
||||
|
||||
/* UNEB's layout is identical to UATS's */
|
||||
#define uefi_cnv_wlan_uneb_data uefi_cnv_wlan_uats_data
|
||||
|
||||
struct uefi_cnv_common_step_data {
|
||||
u8 revision;
|
||||
u8 step_mode;
|
||||
@@ -72,68 +71,135 @@ struct uefi_cnv_common_step_data {
|
||||
u8 radio2;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct uefi_sar_profile - a SAR profile as defined in UEFI
|
||||
*
|
||||
* @chains: a per-chain table of SAR values
|
||||
*/
|
||||
struct uefi_sar_profile {
|
||||
struct iwl_sar_profile_chain chains[BIOS_SAR_MAX_CHAINS_PER_PROFILE];
|
||||
} __packed;
|
||||
#define UEFI_PPAG_SUB_BANDS_NUM_REV4 11
|
||||
#define UEFI_PPAG_SUB_BANDS_NUM_REV5 12
|
||||
#define UEFI_PPAG_NUM_CHAINS 2
|
||||
|
||||
/*
|
||||
#define UEFI_SAR_SUB_BANDS_NUM_REV2 11
|
||||
#define UEFI_SAR_SUB_BANDS_NUM_REV3 12
|
||||
|
||||
#define UEFI_SAR_MAX_CHAINS_PER_PROFILE 4
|
||||
|
||||
#define UEFI_GEO_NUM_BANDS_REV3 3
|
||||
#define UEFI_GEO_NUM_BANDS_REV4 4
|
||||
|
||||
/**
|
||||
* struct uefi_cnv_var_wrds - WRDS table as defined in UEFI
|
||||
*
|
||||
* @revision: the revision of the table
|
||||
* @mode: is WRDS enbaled/disabled
|
||||
* @sar_profile: sar profile #1
|
||||
* @vals: values for sar profile #1 as an array:
|
||||
* vals[chain * num_of_subbands + subband] will return the right value.
|
||||
* num_of_subbands depends on the revision. For revision 3, it is
|
||||
* %UEFI_SAR_SUB_BANDS_NUM_REV3, for earlier revision, it is
|
||||
* %UEFI_SAR_SUB_BANDS_NUM_REV2.
|
||||
* The max number of chains is currently 2
|
||||
*/
|
||||
struct uefi_cnv_var_wrds {
|
||||
u8 revision;
|
||||
u32 mode;
|
||||
struct uefi_sar_profile sar_profile;
|
||||
u8 vals[];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
#define UEFI_SAR_PROFILE_SIZE_REV2 \
|
||||
(sizeof(u8) * UEFI_SAR_MAX_CHAINS_PER_PROFILE * \
|
||||
UEFI_SAR_SUB_BANDS_NUM_REV2)
|
||||
|
||||
#define UEFI_SAR_PROFILE_SIZE_REV3 \
|
||||
(sizeof(u8) * UEFI_SAR_MAX_CHAINS_PER_PROFILE * \
|
||||
UEFI_SAR_SUB_BANDS_NUM_REV3)
|
||||
|
||||
#define UEFI_SAR_WRDS_TABLE_SIZE_REV2 \
|
||||
(offsetof(struct uefi_cnv_var_wrds, vals) + \
|
||||
UEFI_SAR_PROFILE_SIZE_REV2)
|
||||
|
||||
#define UEFI_SAR_WRDS_TABLE_SIZE_REV3 \
|
||||
(offsetof(struct uefi_cnv_var_wrds, vals) + \
|
||||
UEFI_SAR_PROFILE_SIZE_REV3)
|
||||
|
||||
/**
|
||||
* struct uefi_cnv_var_ewrd - EWRD table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @mode: is WRDS enbaled/disabled
|
||||
* @num_profiles: how many additional profiles we have in this table (0-3)
|
||||
* @sar_profiles: the additional SAR profiles (#2-#4)
|
||||
* @vals: the additional SAR profiles (#2-#4) as an array of SAR profiles.
|
||||
* A SAR profile is defined the &struct uefi_cnv_var_wrds::vals. The size
|
||||
* of each profile depends on the number of subbands which depends on the
|
||||
* revision. This is explained in &struct uefi_cnv_var_wrds.
|
||||
*/
|
||||
struct uefi_cnv_var_ewrd {
|
||||
u8 revision;
|
||||
u32 mode;
|
||||
u32 num_profiles;
|
||||
struct uefi_sar_profile sar_profiles[BIOS_SAR_MAX_PROFILE_NUM - 1];
|
||||
u8 vals[];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
#define UEFI_SAR_EWRD_TABLE_SIZE_REV2 \
|
||||
(offsetof(struct uefi_cnv_var_ewrd, vals) + \
|
||||
UEFI_SAR_PROFILE_SIZE_REV2 * (BIOS_SAR_MAX_PROFILE_NUM - 1))
|
||||
|
||||
#define UEFI_SAR_EWRD_TABLE_SIZE_REV3 \
|
||||
(offsetof(struct uefi_cnv_var_ewrd, vals) + \
|
||||
UEFI_SAR_PROFILE_SIZE_REV3 * (BIOS_SAR_MAX_PROFILE_NUM - 1))
|
||||
|
||||
/**
|
||||
* struct uefi_cnv_var_wgds - WGDS table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @num_profiles: the number of geo profiles we have in the table.
|
||||
* The first 3 are mandatory, and can have up to 8.
|
||||
* @geo_profiles: a per-profile table of the offsets to add to SAR values.
|
||||
* @vals: a per-profile table of the offsets to add to SAR values. This is an
|
||||
* array of profiles, each profile is an array of
|
||||
* &struct iwl_geo_profile_band, one for each subband.
|
||||
* There are %UEFI_GEO_NUM_BANDS_REV3 or %UEFI_GEO_NUM_BANDS_REV4 subbands
|
||||
* depending on the revision.
|
||||
*/
|
||||
struct uefi_cnv_var_wgds {
|
||||
u8 revision;
|
||||
u8 num_profiles;
|
||||
struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
|
||||
u8 vals[];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
/* struct iwl_geo_profile_band is 3 bytes-long, but since it is not packed,
|
||||
* we can't use sizeof()
|
||||
*/
|
||||
#define UEFI_WGDS_PROFILE_SIZE_REV3 (sizeof(u8) * 3 * UEFI_GEO_NUM_BANDS_REV3)
|
||||
|
||||
#define UEFI_WGDS_PROFILE_SIZE_REV4 (sizeof(u8) * 3 * UEFI_GEO_NUM_BANDS_REV4)
|
||||
|
||||
#define UEFI_WGDS_TABLE_SIZE_REV3 \
|
||||
(offsetof(struct uefi_cnv_var_wgds, vals) + \
|
||||
UEFI_WGDS_PROFILE_SIZE_REV3 * BIOS_GEO_MAX_PROFILE_NUM)
|
||||
|
||||
#define UEFI_WGDS_TABLE_SIZE_REV4 \
|
||||
(offsetof(struct uefi_cnv_var_wgds, vals) + \
|
||||
UEFI_WGDS_PROFILE_SIZE_REV4 * BIOS_GEO_MAX_PROFILE_NUM)
|
||||
|
||||
/**
|
||||
* struct uefi_cnv_var_ppag - PPAG table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @ppag_modes: values from &enum iwl_ppag_flags
|
||||
* @ppag_chains: the PPAG values per chain and band
|
||||
* @vals: the PPAG values per chain and band as an array.
|
||||
* vals[chain * num_of_subbands + subband] will return the right value.
|
||||
* num_of_subbands depends on the revision. For revision 5, it is
|
||||
* %UEFI_PPAG_SUB_BANDS_NUM_REV5, for earlier revision it is
|
||||
* %UEFI_PPAG_SUB_BANDS_NUM_REV4.
|
||||
* the max number of chains is currently 2
|
||||
*/
|
||||
struct uefi_cnv_var_ppag {
|
||||
u8 revision;
|
||||
u32 ppag_modes;
|
||||
struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
|
||||
s8 vals[];
|
||||
} __packed;
|
||||
|
||||
/* struct uefi_cnv_var_wtas - WTAS tabled as defined in UEFI
|
||||
#define UEFI_PPAG_DATA_SIZE_V4 \
|
||||
(offsetof(struct uefi_cnv_var_ppag, vals) + \
|
||||
sizeof(s8) * UEFI_PPAG_NUM_CHAINS * UEFI_PPAG_SUB_BANDS_NUM_REV4)
|
||||
#define UEFI_PPAG_DATA_SIZE_V5 \
|
||||
(offsetof(struct uefi_cnv_var_ppag, vals) + \
|
||||
sizeof(s8) * UEFI_PPAG_NUM_CHAINS * UEFI_PPAG_SUB_BANDS_NUM_REV5)
|
||||
|
||||
/**
|
||||
* struct uefi_cnv_var_wtas - WTAS tabled as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @tas_selection: different options of TAS enablement.
|
||||
* @black_list_size: the number of defined entried in the black list
|
||||
@@ -146,7 +212,8 @@ struct uefi_cnv_var_wtas {
|
||||
u16 black_list[IWL_WTAS_BLACK_LIST_MAX];
|
||||
} __packed;
|
||||
|
||||
/* struct uefi_cnv_var_splc - SPLC tabled as defined in UEFI
|
||||
/**
|
||||
* struct uefi_cnv_var_splc - SPLC tabled as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @default_pwr_limit: The default maximum power per device
|
||||
*/
|
||||
@@ -155,7 +222,8 @@ struct uefi_cnv_var_splc {
|
||||
u32 default_pwr_limit;
|
||||
} __packed;
|
||||
|
||||
/* struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI
|
||||
/**
|
||||
* struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @mcc: country identifier as defined in ISO/IEC 3166-1 Alpha 2 code
|
||||
*/
|
||||
@@ -164,7 +232,8 @@ struct uefi_cnv_var_wrdd {
|
||||
u32 mcc;
|
||||
} __packed;
|
||||
|
||||
/* struct uefi_cnv_var_eckv - ECKV table as defined in UEFI
|
||||
/**
|
||||
* struct uefi_cnv_var_eckv - ECKV table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @ext_clock_valid: indicates if external 32KHz clock is valid
|
||||
*/
|
||||
@@ -175,7 +244,8 @@ struct uefi_cnv_var_eckv {
|
||||
|
||||
#define UEFI_MAX_DSM_FUNCS 32
|
||||
|
||||
/* struct uefi_cnv_var_general_cfg - DSM-like table as defined in UEFI
|
||||
/**
|
||||
* struct uefi_cnv_var_general_cfg - DSM-like table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @functions: payload of the different DSM functions
|
||||
*/
|
||||
@@ -185,7 +255,9 @@ struct uefi_cnv_var_general_cfg {
|
||||
} __packed;
|
||||
|
||||
#define IWL_UEFI_WBEM_REV0_MASK (BIT(0) | BIT(1))
|
||||
/* struct uefi_cnv_wlan_wbem_data - Bandwidth enablement per MCC as defined
|
||||
|
||||
/**
|
||||
* struct uefi_cnv_wlan_wbem_data - Bandwidth enablement per MCC as defined
|
||||
* in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @wbem_320mhz_per_mcc: enablement of 320MHz bandwidth per MCC
|
||||
@@ -274,6 +346,8 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
|
||||
void iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt);
|
||||
void iwl_uefi_get_uneb_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt);
|
||||
@@ -373,6 +447,11 @@ iwl_uefi_get_uats_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
iwl_uefi_get_uneb_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
|
||||
@@ -85,7 +85,6 @@ enum iwl_nvm_type {
|
||||
#define IWL_WATCHDOG_DISABLED 0
|
||||
#define IWL_DEF_WD_TIMEOUT 2500
|
||||
#define IWL_LONG_WD_TIMEOUT 10000
|
||||
#define IWL_MAX_WD_TIMEOUT 120000
|
||||
|
||||
#define IWL_DEFAULT_MAX_TX_POWER 22
|
||||
#define IWL_TX_CSUM_NETIF_FLAGS (NETIF_F_IPV6_CSUM | NETIF_F_IP_CSUM |\
|
||||
|
||||
@@ -133,6 +133,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
|
||||
kfree(drv->fw.dbg.mem_tlv);
|
||||
kfree(drv->fw.iml);
|
||||
kfree(drv->fw.ucode_capa.cmd_versions);
|
||||
kfree(drv->fw.ucode_capa.cmd_bios_tables);
|
||||
kfree(drv->fw.phy_integration_ver);
|
||||
kfree(drv->trans->dbg.pc_data);
|
||||
drv->trans->dbg.pc_data = NULL;
|
||||
@@ -1314,7 +1315,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
if (le32_to_cpup((const __le32 *)tlv_data) >
|
||||
IWL_FW_MAX_LINK_ID + 1) {
|
||||
IWL_FW_MAX_LINKS) {
|
||||
IWL_ERR(drv,
|
||||
"%d is an invalid number of links\n",
|
||||
le32_to_cpup((const __le32 *)tlv_data));
|
||||
@@ -1426,6 +1427,26 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
return -ENOMEM;
|
||||
drv->fw.pnvm_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_CMD_BIOS_TABLE:
|
||||
if (tlv_len % sizeof(struct iwl_fw_cmd_bios_table)) {
|
||||
IWL_ERR(drv,
|
||||
"Invalid length for command bios table: %u\n",
|
||||
tlv_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (capa->cmd_bios_tables) {
|
||||
IWL_ERR(drv, "Duplicate TLV type 0x%02X detected\n",
|
||||
tlv_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
capa->cmd_bios_tables = kmemdup(tlv_data, tlv_len,
|
||||
GFP_KERNEL);
|
||||
if (!capa->cmd_bios_tables)
|
||||
return -ENOMEM;
|
||||
capa->n_cmd_bios_tables =
|
||||
tlv_len / sizeof(struct iwl_fw_cmd_bios_table);
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
|
||||
break;
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "fw/api/commands.h"
|
||||
#include "fw/api/cmdhdr.h"
|
||||
#include "fw/img.h"
|
||||
#include "fw/dbg.h"
|
||||
|
||||
#include "mei/iwl-mei.h"
|
||||
|
||||
/* NVM offsets (in words) definitions */
|
||||
@@ -1712,6 +1714,11 @@ iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
|
||||
band);
|
||||
new_rule = false;
|
||||
|
||||
if (IWL_FW_CHECK(trans, !center_freq,
|
||||
"Invalid channel %d (idx %d) in NVM\n",
|
||||
nvm_chan[ch_idx], ch_idx))
|
||||
continue;
|
||||
|
||||
if (!(ch_flags & NVM_CHANNEL_VALID)) {
|
||||
iwl_nvm_print_channel_flags(dev, IWL_DL_LAR,
|
||||
nvm_chan[ch_idx], ch_flags);
|
||||
@@ -2041,7 +2048,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
||||
if (empty_otp)
|
||||
IWL_INFO(trans, "OTP is empty\n");
|
||||
|
||||
nvm = kzalloc(struct_size(nvm, channels, IWL_NUM_CHANNELS), GFP_KERNEL);
|
||||
nvm = kzalloc(struct_size(nvm, channels, IWL_NUM_CHANNELS_V2), GFP_KERNEL);
|
||||
if (!nvm) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
|
||||
@@ -138,7 +138,7 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans)
|
||||
IWL_RESET_MODE_FUNC_RESET,
|
||||
IWL_RESET_MODE_PROD_RESET,
|
||||
};
|
||||
static const enum iwl_reset_mode escalation_list_sc[] = {
|
||||
static const enum iwl_reset_mode escalation_list_top[] = {
|
||||
IWL_RESET_MODE_SW_RESET,
|
||||
IWL_RESET_MODE_REPROBE,
|
||||
IWL_RESET_MODE_REPROBE,
|
||||
@@ -159,14 +159,14 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans)
|
||||
|
||||
if (trans->request_top_reset) {
|
||||
trans->request_top_reset = 0;
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC)
|
||||
if (iwl_trans_is_top_reset_supported(trans))
|
||||
return IWL_RESET_MODE_TOP_RESET;
|
||||
return IWL_RESET_MODE_PROD_RESET;
|
||||
}
|
||||
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) {
|
||||
escalation_list = escalation_list_sc;
|
||||
escalation_list_size = ARRAY_SIZE(escalation_list_sc);
|
||||
if (iwl_trans_is_top_reset_supported(trans)) {
|
||||
escalation_list = escalation_list_top;
|
||||
escalation_list_size = ARRAY_SIZE(escalation_list_top);
|
||||
} else {
|
||||
escalation_list = escalation_list_old;
|
||||
escalation_list_size = ARRAY_SIZE(escalation_list_old);
|
||||
|
||||
@@ -1092,7 +1092,7 @@ static inline void iwl_trans_schedule_reset(struct iwl_trans *trans,
|
||||
*/
|
||||
trans->restart.during_reset = test_bit(STATUS_IN_SW_RESET,
|
||||
&trans->status);
|
||||
queue_delayed_work(system_unbound_wq, &trans->restart.wk, 0);
|
||||
queue_delayed_work(system_dfl_wq, &trans->restart.wk, 0);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_fw_error(struct iwl_trans *trans,
|
||||
@@ -1262,4 +1262,22 @@ bool iwl_trans_is_pm_supported(struct iwl_trans *trans);
|
||||
|
||||
bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans);
|
||||
|
||||
static inline bool iwl_trans_is_top_reset_supported(struct iwl_trans *trans)
|
||||
{
|
||||
/* not supported before Sc family */
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC)
|
||||
return false;
|
||||
|
||||
/* for Sc family only supported for Sc2/Sc2f */
|
||||
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_SC &&
|
||||
CSR_HW_REV_TYPE(trans->info.hw_rev) == IWL_CFG_MAC_TYPE_SC)
|
||||
return false;
|
||||
|
||||
/* so far these numbers are increasing - not before Pe */
|
||||
if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) < IWL_CFG_RF_TYPE_PE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* __iwl_trans_h__ */
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "ap.h"
|
||||
#include "hcmd.h"
|
||||
#include "tx.h"
|
||||
#include "power.h"
|
||||
#include "key.h"
|
||||
#include "phy.h"
|
||||
#include "iwl-utils.h"
|
||||
@@ -273,9 +272,6 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
int ret;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
iwl_mld_send_ap_tx_power_constraint_cmd(mld, vif, link);
|
||||
|
||||
ret = iwl_mld_update_beacon_template(mld, vif, link);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_constants_h__
|
||||
#define __iwl_mld_constants_h__
|
||||
|
||||
#define IWL_MLD_MISSED_BEACONS_SINCE_RX_THOLD 4
|
||||
#define IWL_MLD_MISSED_BEACONS_SINCE_RX_THOLD 6
|
||||
#define IWL_MLD_MISSED_BEACONS_THRESHOLD 8
|
||||
#define IWL_MLD_MISSED_BEACONS_THRESHOLD_LONG 19
|
||||
#define IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5
|
||||
@@ -36,7 +36,6 @@
|
||||
#define IWL_MLD_PS_HEAVY_RX_THLD_PACKETS 8
|
||||
|
||||
#define IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC 30
|
||||
#define IWL_MLD_SCAN_EXPIRE_TIME_SEC 20
|
||||
|
||||
#define IWL_MLD_TPT_COUNT_WINDOW (5 * HZ)
|
||||
|
||||
|
||||
@@ -1933,12 +1933,12 @@ int iwl_mld_wowlan_suspend(struct iwl_mld *mld, struct cfg80211_wowlan *wowlan)
|
||||
if (WARN_ON(!wowlan))
|
||||
return 1;
|
||||
|
||||
IWL_DEBUG_WOWLAN(mld, "Starting the wowlan suspend flow\n");
|
||||
|
||||
bss_vif = iwl_mld_get_bss_vif(mld);
|
||||
if (WARN_ON(!bss_vif))
|
||||
if (!bss_vif)
|
||||
return 1;
|
||||
|
||||
IWL_DEBUG_WOWLAN(mld, "Starting the wowlan suspend flow\n");
|
||||
|
||||
if (!bss_vif->cfg.assoc) {
|
||||
int ret;
|
||||
/* If we're not associated, this must be netdetect */
|
||||
|
||||
@@ -513,7 +513,7 @@ static int iwl_mld_config_fw(struct iwl_mld *mld)
|
||||
return ret;
|
||||
|
||||
iwl_mld_init_tas(mld);
|
||||
iwl_mld_init_uats(mld);
|
||||
iwl_mld_init_ap_type_tables(mld);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -61,20 +61,27 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
static int iwl_mld_send_mac_cmd(struct iwl_mld *mld,
|
||||
struct iwl_mac_config_cmd *cmd)
|
||||
{
|
||||
u16 cmd_id = WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD);
|
||||
int len = sizeof(*cmd);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
ret = iwl_mld_send_cmd_pdu(mld,
|
||||
WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD),
|
||||
cmd);
|
||||
if (iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0) < 4) {
|
||||
if (WARN_ON(cmd->mac_type == cpu_to_le32(FW_MAC_TYPE_NAN)))
|
||||
return -EINVAL;
|
||||
|
||||
len = sizeof(struct iwl_mac_config_cmd_v3);
|
||||
}
|
||||
|
||||
ret = iwl_mld_send_cmd_pdu(mld, cmd_id, cmd, len);
|
||||
if (ret)
|
||||
IWL_ERR(mld, "Failed to send MAC_CONFIG_CMD ret = %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif)
|
||||
static int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif)
|
||||
{
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
@@ -423,7 +430,7 @@ static void iwl_mld_mlo_scan_start_wk(struct wiphy *wiphy,
|
||||
iwl_mld_int_mlo_scan(mld, iwl_mld_vif_to_mac80211(mld_vif));
|
||||
}
|
||||
|
||||
IWL_MLD_ALLOC_FN(vif, vif)
|
||||
static IWL_MLD_ALLOC_FN(vif, vif)
|
||||
|
||||
/* Constructor function for struct iwl_mld_vif */
|
||||
static void
|
||||
@@ -434,6 +441,7 @@ iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
mld_vif->mld = mld;
|
||||
mld_vif->fw_id = IWL_MLD_INVALID_FW_ID;
|
||||
mld_vif->roc_activity = ROC_NUM_ACTIVITIES;
|
||||
|
||||
if (!mld->fw_status.in_hw_restart) {
|
||||
@@ -481,6 +489,10 @@ void iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
/* NAN interface type is not known to FW */
|
||||
if (vif->type == NL80211_IFTYPE_NAN)
|
||||
return;
|
||||
|
||||
iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE);
|
||||
|
||||
if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->fw_id_to_vif)))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_iface_h__
|
||||
#define __iwl_mld_iface_h__
|
||||
@@ -33,6 +33,7 @@ enum iwl_mld_cca_40mhz_wa_status {
|
||||
* there is an indication that a non-BSS interface is to be added.
|
||||
* @IWL_MLD_EMLSR_BLOCKED_TPT: throughput is too low to make EMLSR worthwhile
|
||||
* @IWL_MLD_EMLSR_BLOCKED_NAN: NAN is preventing EMLSR.
|
||||
* @IWL_MLD_EMLSR_BLOCKED_TDLS: TDLS connection is preventing EMLSR.
|
||||
*/
|
||||
enum iwl_mld_emlsr_blocked {
|
||||
IWL_MLD_EMLSR_BLOCKED_PREVENTION = 0x1,
|
||||
@@ -42,6 +43,7 @@ enum iwl_mld_emlsr_blocked {
|
||||
IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS = 0x10,
|
||||
IWL_MLD_EMLSR_BLOCKED_TPT = 0x20,
|
||||
IWL_MLD_EMLSR_BLOCKED_NAN = 0x40,
|
||||
IWL_MLD_EMLSR_BLOCKED_TDLS = 0x80,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -201,6 +203,15 @@ iwl_mld_vif_to_mac80211(struct iwl_mld_vif *mld_vif)
|
||||
return container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
|
||||
}
|
||||
|
||||
/* Call only for interfaces that were added to the driver! */
|
||||
static inline bool iwl_mld_vif_fw_id_valid(struct iwl_mld_vif *mld_vif)
|
||||
{
|
||||
if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld_vif->mld->fw_id_to_vif)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define iwl_mld_link_dereference_check(mld_vif, link_id) \
|
||||
rcu_dereference_check((mld_vif)->link[link_id], \
|
||||
lockdep_is_held(&mld_vif->mld->wiphy->mtx))
|
||||
@@ -219,8 +230,6 @@ iwl_mld_link_from_mac80211(struct ieee80211_bss_conf *bss_conf)
|
||||
return iwl_mld_link_dereference_check(mld_vif, bss_conf->link_id);
|
||||
}
|
||||
|
||||
int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif);
|
||||
|
||||
/* Cleanup function for struct iwl_mld_vif, will be called in restart */
|
||||
void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
|
||||
int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "constants.h"
|
||||
@@ -437,7 +437,7 @@ iwl_mld_rm_link_from_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link)
|
||||
iwl_mld_send_link_cmd(mld, &cmd, FW_CTXT_ACTION_REMOVE);
|
||||
}
|
||||
|
||||
IWL_MLD_ALLOC_FN(link, bss_conf)
|
||||
static IWL_MLD_ALLOC_FN(link, bss_conf)
|
||||
|
||||
/* Constructor function for struct iwl_mld_link */
|
||||
static int
|
||||
@@ -504,7 +504,6 @@ void iwl_mld_remove_link(struct iwl_mld *mld,
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(bss_conf->vif);
|
||||
struct iwl_mld_link *link = iwl_mld_link_from_mac80211(bss_conf);
|
||||
bool is_deflink = link == &mld_vif->deflink;
|
||||
u8 fw_id = link->fw_id;
|
||||
|
||||
if (WARN_ON(!link || link->active))
|
||||
return;
|
||||
@@ -512,15 +511,15 @@ void iwl_mld_remove_link(struct iwl_mld *mld,
|
||||
iwl_mld_rm_link_from_fw(mld, bss_conf);
|
||||
/* Continue cleanup on failure */
|
||||
|
||||
if (!is_deflink)
|
||||
kfree_rcu(link, rcu_head);
|
||||
|
||||
RCU_INIT_POINTER(mld_vif->link[bss_conf->link_id], NULL);
|
||||
|
||||
if (WARN_ON(fw_id >= mld->fw->ucode_capa.num_links))
|
||||
if (WARN_ON(link->fw_id >= mld->fw->ucode_capa.num_links))
|
||||
return;
|
||||
|
||||
RCU_INIT_POINTER(mld->fw_id_to_bss_conf[fw_id], NULL);
|
||||
RCU_INIT_POINTER(mld->fw_id_to_bss_conf[link->fw_id], NULL);
|
||||
|
||||
if (!is_deflink)
|
||||
kfree_rcu(link, rcu_head);
|
||||
}
|
||||
|
||||
void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
|
||||
|
||||
@@ -40,6 +40,7 @@ struct iwl_probe_resp_data {
|
||||
* @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS.
|
||||
* @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS.
|
||||
* @mon_sta: station used for TX injection in monitor interface.
|
||||
* @last_cqm_rssi_event: rssi of the last cqm rssi event
|
||||
* @average_beacon_energy: average beacon energy for beacons received during
|
||||
* client connections
|
||||
* @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs,
|
||||
@@ -66,6 +67,7 @@ struct iwl_mld_link {
|
||||
struct iwl_mld_int_sta bcast_sta;
|
||||
struct iwl_mld_int_sta mcast_sta;
|
||||
struct iwl_mld_int_sta mon_sta;
|
||||
int last_cqm_rssi_event;
|
||||
|
||||
/* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */
|
||||
struct ieee80211_key_conf *ap_early_keys[6];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
#include "mld.h"
|
||||
#include "iface.h"
|
||||
@@ -77,9 +77,12 @@ static void iwl_mld_low_latency_iter(void *_data, u8 *mac,
|
||||
bool prev = mld_vif->low_latency_causes & LOW_LATENCY_TRAFFIC;
|
||||
bool low_latency;
|
||||
|
||||
if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->low_latency.result)))
|
||||
if (!iwl_mld_vif_fw_id_valid(mld_vif))
|
||||
return;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(mld->fw_id_to_vif) !=
|
||||
ARRAY_SIZE(mld->low_latency.result));
|
||||
|
||||
low_latency = mld->low_latency.result[mld_vif->fw_id];
|
||||
|
||||
if (prev != low_latency)
|
||||
@@ -272,8 +275,10 @@ void iwl_mld_low_latency_update_counters(struct iwl_mld *mld,
|
||||
if (WARN_ON_ONCE(!mld->low_latency.pkts_counters))
|
||||
return;
|
||||
|
||||
if (WARN_ON_ONCE(fw_id >= ARRAY_SIZE(counters->vo_vi) ||
|
||||
queue >= mld->trans->info.num_rxqs))
|
||||
if (!iwl_mld_vif_fw_id_valid(mld_vif))
|
||||
return;
|
||||
|
||||
if (WARN_ON_ONCE(queue >= mld->trans->info.num_rxqs))
|
||||
return;
|
||||
|
||||
if (mld->low_latency.stopped)
|
||||
|
||||
@@ -754,6 +754,30 @@ void iwl_mld_mac80211_remove_interface(struct ieee80211_hw *hw,
|
||||
mld->monitor.phy.valid = false;
|
||||
}
|
||||
|
||||
static
|
||||
int iwl_mld_mac80211_change_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum nl80211_iftype new_type, bool p2p)
|
||||
{
|
||||
enum nl80211_iftype old_type = vif->type;
|
||||
bool old_p2p = vif->p2p;
|
||||
int ret;
|
||||
|
||||
iwl_mld_mac80211_remove_interface(hw, vif);
|
||||
|
||||
/* set the new type for adding it cleanly */
|
||||
vif->type = new_type;
|
||||
vif->p2p = p2p;
|
||||
|
||||
ret = iwl_mld_mac80211_add_interface(hw, vif);
|
||||
|
||||
/* restore for mac80211, it will change it again */
|
||||
vif->type = old_type;
|
||||
vif->p2p = old_p2p;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct iwl_mld_mc_iter_data {
|
||||
struct iwl_mld *mld;
|
||||
int port_id;
|
||||
@@ -1124,6 +1148,15 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
|
||||
/* Now activate the link */
|
||||
if (iwl_mld_can_activate_link(mld, vif, link)) {
|
||||
iwl_mld_tlc_update_phy(mld, vif, link);
|
||||
|
||||
/* FW requires AP_TX_POWER_CONSTRAINTS_CMD before link
|
||||
* activation for AP and after link activation for STA,
|
||||
* for an unknown reason.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
iwl_mld_send_ap_tx_power_constraint_cmd(mld, vif, link);
|
||||
|
||||
ret = iwl_mld_activate_link(mld, link);
|
||||
if (ret)
|
||||
goto err;
|
||||
@@ -1185,6 +1218,8 @@ void iwl_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
|
||||
RCU_INIT_POINTER(mld_link->chan_ctx, NULL);
|
||||
|
||||
iwl_mld_tlc_update_phy(mld, vif, link);
|
||||
|
||||
/* in the non-MLO case, remove/re-add the link to clean up FW state.
|
||||
* In MLO, it'll be done in drv_change_vif_link
|
||||
*/
|
||||
@@ -1727,14 +1762,23 @@ static int iwl_mld_move_sta_state_up(struct iwl_mld *mld,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ret = iwl_mld_add_sta(mld, sta, vif, STATION_TYPE_PEER);
|
||||
ret = iwl_mld_add_sta(mld, sta, vif);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* just added first TDLS STA, so disable PM */
|
||||
if (sta->tdls && tdls_count == 0)
|
||||
/* just added first TDLS STA, so disable PM and block EMLSR */
|
||||
if (sta->tdls && tdls_count == 0) {
|
||||
iwl_mld_update_mac_power(mld, vif, false);
|
||||
|
||||
/* TDLS requires single-link operation with
|
||||
* direct peer communication.
|
||||
* Block and exit EMLSR when TDLS is established.
|
||||
*/
|
||||
iwl_mld_block_emlsr(mld, vif,
|
||||
IWL_MLD_EMLSR_BLOCKED_TDLS,
|
||||
iwl_mld_get_primary_link(vif));
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
|
||||
mld_vif->ap_sta = sta;
|
||||
|
||||
@@ -1880,8 +1924,14 @@ static int iwl_mld_move_sta_state_down(struct iwl_mld *mld,
|
||||
iwl_mld_remove_sta(mld, sta);
|
||||
|
||||
if (sta->tdls && iwl_mld_tdls_sta_count(mld) == 0) {
|
||||
/* just removed last TDLS STA, so enable PM */
|
||||
/* just removed last TDLS STA, so enable PM
|
||||
* and unblock EMLSR
|
||||
*/
|
||||
iwl_mld_update_mac_power(mld, vif, false);
|
||||
|
||||
/* Unblock EMLSR when TDLS connection is torn down */
|
||||
iwl_mld_unblock_emlsr(mld, vif,
|
||||
IWL_MLD_EMLSR_BLOCKED_TDLS);
|
||||
}
|
||||
|
||||
if (sta->tdls) {
|
||||
@@ -2736,6 +2786,7 @@ const struct ieee80211_ops iwl_mld_hw_ops = {
|
||||
.get_antenna = iwl_mld_get_antenna,
|
||||
.set_antenna = iwl_mld_set_antenna,
|
||||
.add_interface = iwl_mld_mac80211_add_interface,
|
||||
.change_interface = iwl_mld_mac80211_change_interface,
|
||||
.remove_interface = iwl_mld_mac80211_remove_interface,
|
||||
.conf_tx = iwl_mld_mac80211_conf_tx,
|
||||
.prepare_multicast = iwl_mld_mac80211_prepare_multicast,
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
struct iwl_mld {
|
||||
/* Add here fields that need clean up on restart */
|
||||
struct_group(zeroed_on_hw_restart,
|
||||
struct ieee80211_bss_conf __rcu *fw_id_to_bss_conf[IWL_FW_MAX_LINK_ID + 1];
|
||||
struct ieee80211_bss_conf __rcu *fw_id_to_bss_conf[IWL_FW_MAX_LINKS];
|
||||
struct ieee80211_vif __rcu *fw_id_to_vif[NUM_MAC_INDEX_DRIVER];
|
||||
struct ieee80211_txq __rcu *fw_id_to_txq[IWL_MAX_TVQM_QUEUES];
|
||||
u8 used_phy_ids: NUM_PHY_CTX;
|
||||
@@ -530,9 +530,9 @@ void iwl_construct_mld(struct iwl_mld *mld, struct iwl_trans *trans,
|
||||
#define IWL_MLD_INVALID_FW_ID 0xff
|
||||
|
||||
#define IWL_MLD_ALLOC_FN(_type, _mac80211_type) \
|
||||
static int \
|
||||
int \
|
||||
iwl_mld_allocate_##_type##_fw_id(struct iwl_mld *mld, \
|
||||
u8 *fw_id, \
|
||||
u8 *fw_id, \
|
||||
struct ieee80211_##_mac80211_type *mac80211_ptr) \
|
||||
{ \
|
||||
u8 rand = IWL_MLD_DIS_RANDOM_FW_ID ? 0 : get_random_u8(); \
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
HOW(NON_BSS) \
|
||||
HOW(TMP_NON_BSS) \
|
||||
HOW(TPT) \
|
||||
HOW(NAN)
|
||||
HOW(NAN) \
|
||||
HOW(TDLS)
|
||||
|
||||
static const char *
|
||||
iwl_mld_get_emlsr_blocked_string(enum iwl_mld_emlsr_blocked blocked)
|
||||
@@ -110,7 +111,6 @@ void iwl_mld_emlsr_tmp_non_bss_done_wk(struct wiphy *wiphy,
|
||||
}
|
||||
|
||||
#define IWL_MLD_TRIGGER_LINK_SEL_TIME (HZ * IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC)
|
||||
#define IWL_MLD_SCAN_EXPIRE_TIME (HZ * IWL_MLD_SCAN_EXPIRE_TIME_SEC)
|
||||
|
||||
/* Exit reasons that can cause longer EMLSR prevention */
|
||||
#define IWL_MLD_PREVENT_EMLSR_REASONS (IWL_MLD_EMLSR_EXIT_MISSED_BEACON | \
|
||||
|
||||
@@ -54,9 +54,8 @@ static int iwl_mld_nan_config(struct iwl_mld *mld,
|
||||
ether_addr_copy(cmd.nmi_addr, vif->addr);
|
||||
cmd.master_pref = conf->master_pref;
|
||||
|
||||
if (conf->cluster_id)
|
||||
memcpy(cmd.cluster_id, conf->cluster_id + 4,
|
||||
sizeof(cmd.cluster_id));
|
||||
memcpy(cmd.cluster_id, conf->cluster_id + 4,
|
||||
sizeof(cmd.cluster_id));
|
||||
|
||||
cmd.scan_period = conf->scan_period < 255 ? conf->scan_period : 255;
|
||||
cmd.dwell_time =
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user