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:
CKI KWF Bot
2026-08-10 08:11:25 +00:00
344 changed files with 17024 additions and 4476 deletions
@@ -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
- |
+10 -3
View File
@@ -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)
+3
View File
@@ -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)
+1
View File
@@ -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;
+2 -6
View File
@@ -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,
+8 -9
View File
@@ -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);
-1
View File
@@ -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
+3 -7
View File
@@ -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) {
-2
View File
@@ -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);
}
+12 -57
View File
@@ -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;
+11 -3
View File
@@ -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;
+1 -4
View File
@@ -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: {
+21 -15
View File
@@ -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,
-1
View File
@@ -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;
}
+112 -19
View File
@@ -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)
-1
View File
@@ -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
+1
View File
@@ -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)
+22 -14
View File
@@ -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)
+3 -2
View File
@@ -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 {
+9 -4
View File
@@ -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
+72 -32
View File
@@ -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;
}
+12 -6
View File
@@ -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)
+24 -5
View File
@@ -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
-2
View File
@@ -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);
}
+13 -11
View File
@@ -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];
+5 -52
View File
@@ -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
View File
@@ -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);
+19 -12
View File
@@ -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,
+62 -33
View File
@@ -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;
}
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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);
+124
View File
@@ -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;
}
}
}
+40
View File
@@ -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;
+60 -16
View File
@@ -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;
+14 -18
View File
@@ -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;
+97 -6
View File
@@ -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() */
+142 -78
View File
@@ -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)
+9 -5
View File
@@ -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 {
+14 -11
View File
@@ -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;
+2 -2
View File
@@ -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) {
+4 -12
View File
@@ -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,
+1 -1
View File
@@ -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++)
-4
View File
@@ -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
+16 -17
View File
@@ -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;
+1 -2
View File
@@ -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;
+3 -2
View File
@@ -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;
}
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+117 -15
View File
@@ -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;
+19 -9
View File
@@ -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 */
+2 -2
View File
@@ -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 -68
View File
@@ -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 */
+31 -1
View File
@@ -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;
+203 -35
View File
@@ -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);
+110 -31
View File
@@ -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 |\
+22 -1
View File
@@ -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);
+19 -1
View File
@@ -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)
+3 -3
View File
@@ -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 */
+1 -1
View File
@@ -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;
}
+17 -5
View File
@@ -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)))
+12 -3
View File
@@ -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,
+3 -3
View File
@@ -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(); \
+2 -2
View File
@@ -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 | \
+2 -3
View File
@@ -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