ath.git patches for v6.10

ath drivers now have no remaining sparse warnings, otherwise smaller
 fixes and some refactoring.
 
 ath11k
 
 * P2P support for QCA6390, WCN6855 and QCA2066
 -----BEGIN PGP SIGNATURE-----
 
 iQFLBAABCgA1FiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmYMOQsXHHF1aWNfa3Zh
 bG9AcXVpY2luYy5jb20ACgkQbhckVSbrbZvycgf+PVR1nswT+ZMYWfbGoDYe04Ah
 Kvccpordskt9A6GmasZlxQmzCik2dyGAOI5JJ/LPDhs/uYcRIu59DSkLlDz93EFk
 n6jiaDi6Y3HQpAULn1u1CHow5gkBWYnfIQH7aTP7H1nuD+ApBYhPIkYTQmZkMewi
 unz4VwaBNJZhQPfM4DDKr/FQ0OMyNtv1EDFNVhX/HU/JB1EvGPT6key4HSFXDGFy
 fkHt2pj3TMlK530AbRwEVZ0D+6uNtT1Qmon5MWtSqzjTt1TmI4TLv1nrINVdg5qD
 yVc+iQ7myCL7cbX0bI6HDHSIqJUvycx191jxLOk7TzkfsKL0oeR+fFeEpledng==
 =+Ku3
 -----END PGP SIGNATURE-----

Merge tag 'ath-next-20240402' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath

ath.git patches for v6.10

ath drivers now have no remaining sparse warnings, otherwise smaller
fixes and some refactoring.

ath11k

* P2P support for QCA6390, WCN6855 and QCA2066
This commit is contained in:
Kalle Valo 2024-04-02 21:19:58 +03:00
commit 0ccf50df61
34 changed files with 660 additions and 218 deletions

View File

@ -100,7 +100,7 @@ static ssize_t ath10k_thermal_show_temp(struct device *dev,
spin_unlock_bh(&ar->data_lock);
/* display in millidegree celsius */
ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000);
ret = sysfs_emit(buf, "%d\n", temperature * 1000);
out:
mutex_unlock(&ar->conf_mutex);
return ret;

View File

@ -1763,12 +1763,32 @@ void ath10k_wmi_put_wmi_channel(struct ath10k *ar, struct wmi_channel *ch,
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
{
unsigned long time_left;
unsigned long time_left, i;
time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
WMI_SERVICE_READY_TIMEOUT_HZ);
if (!time_left)
return -ETIMEDOUT;
if (!time_left) {
/* Sometimes the PCI HIF doesn't receive interrupt
* for the service ready message even if the buffer
* was completed. PCIe sniffer shows that it's
* because the corresponding CE ring doesn't fires
* it. Workaround here by polling CE rings once.
*/
ath10k_warn(ar, "failed to receive service ready completion, polling..\n");
for (i = 0; i < CE_COUNT; i++)
ath10k_hif_send_complete_check(ar, i, 1);
time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
WMI_SERVICE_READY_TIMEOUT_HZ);
if (!time_left) {
ath10k_warn(ar, "polling timed out\n");
return -ETIMEDOUT;
}
ath10k_warn(ar, "service ready completion received, continuing normally\n");
}
return 0;
}

View File

@ -18,7 +18,8 @@ ath11k-y += core.o \
dbring.o \
hw.o \
pcic.o \
fw.o
fw.o \
p2p.o
ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o

View File

@ -247,7 +247,10 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = false,
.full_monitor_mode = false,
.supports_shadow_regs = true,
@ -416,7 +419,10 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = false,
.full_monitor_mode = false,
.supports_shadow_regs = true,
@ -501,7 +507,10 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = false,
.supports_shadow_regs = true,
.idle_ps = true,
@ -750,7 +759,10 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = false,
.full_monitor_mode = false,
.supports_shadow_regs = true,

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/vmalloc.h>
@ -980,7 +980,7 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
&fops_simulate_fw_crash);
debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
debugfs_create_file("soc_dp_stats", 0400, ab->debugfs_soc, ab,
&fops_soc_dp_stats);
if (ab->hw_params.sram_dump.start != 0)

View File

@ -1231,14 +1231,7 @@ static int ath11k_mac_vif_setup_ps(struct ath11k_vif *arvif)
enable_ps = arvif->ps;
if (!arvif->is_started) {
/* mac80211 can update vif powersave state while disconnected.
* Firmware doesn't behave nicely and consumes more power than
* necessary if PS is disabled on a non-started vdev. Hence
* force-enable PS for non-running vdevs.
*/
psmode = WMI_STA_PS_MODE_ENABLED;
} else if (enable_ps) {
if (enable_ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
@ -1430,10 +1423,67 @@ static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif,
return false;
}
static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
struct sk_buff *bcn)
static int ath11k_mac_setup_bcn_p2p_ie(struct ath11k_vif *arvif,
struct sk_buff *bcn)
{
struct ath11k *ar = arvif->ar;
struct ieee80211_mgmt *mgmt;
const u8 *p2p_ie;
int ret;
mgmt = (void *)bcn->data;
p2p_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,
mgmt->u.beacon.variable,
bcn->len - (mgmt->u.beacon.variable -
bcn->data));
if (!p2p_ie)
return -ENOENT;
ret = ath11k_wmi_p2p_go_bcn_ie(ar, arvif->vdev_id, p2p_ie);
if (ret) {
ath11k_warn(ar->ab, "failed to submit P2P GO bcn ie for vdev %i: %d\n",
arvif->vdev_id, ret);
return ret;
}
return ret;
}
static int ath11k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,
u8 oui_type, size_t ie_offset)
{
size_t len;
const u8 *next, *end;
u8 *ie;
if (WARN_ON(skb->len < ie_offset))
return -EINVAL;
ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type,
skb->data + ie_offset,
skb->len - ie_offset);
if (!ie)
return -ENOENT;
len = ie[1] + 2;
end = skb->data + skb->len;
next = ie + len;
if (WARN_ON(next > end))
return -EINVAL;
memmove(ie, next, end - next);
skb_trim(skb, skb->len - len);
return 0;
}
static int ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
struct sk_buff *bcn)
{
struct ath11k_base *ab = arvif->ar->ab;
struct ieee80211_mgmt *mgmt;
int ret = 0;
u8 *ies;
ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
@ -1451,6 +1501,32 @@ static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
arvif->wpaie_present = true;
else
arvif->wpaie_present = false;
if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO)
return ret;
ret = ath11k_mac_setup_bcn_p2p_ie(arvif, bcn);
if (ret) {
ath11k_warn(ab, "failed to setup P2P GO bcn ie: %d\n",
ret);
return ret;
}
/* P2P IE is inserted by firmware automatically (as
* configured above) so remove it from the base beacon
* template to avoid duplicate P2P IEs in beacon frames.
*/
ret = ath11k_mac_remove_vendor_ie(bcn, WLAN_OUI_WFA,
WLAN_OUI_TYPE_WFA_P2P,
offsetof(struct ieee80211_mgmt,
u.beacon.variable));
if (ret) {
ath11k_warn(ab, "failed to remove P2P vendor ie: %d\n",
ret);
return ret;
}
return ret;
}
static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
@ -1472,10 +1548,12 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
return -EPERM;
}
if (tx_arvif == arvif)
ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb);
else
if (tx_arvif == arvif) {
if (ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb))
return -EINVAL;
} else {
arvif->wpaie_present = tx_arvif->wpaie_present;
}
for (i = 0; i < beacons->cnt; i++) {
if (tx_arvif != arvif && !nontx_vif_params_set)
@ -1534,10 +1612,12 @@ static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif)
return -EPERM;
}
if (tx_arvif == arvif)
ath11k_mac_set_vif_params(tx_arvif, bcn);
else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn))
if (tx_arvif == arvif) {
if (ath11k_mac_set_vif_params(tx_arvif, bcn))
return -EINVAL;
} else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn)) {
return -EINVAL;
}
ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
kfree_skb(bcn);
@ -3996,6 +4076,9 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
arg->vdev_id = arvif->vdev_id;
arg->scan_id = ATH11K_SCAN_ID;
if (ar->ab->hw_params.single_pdev_only)
arg->scan_f_filter_prb_req = 1;
if (req->ie_len) {
arg->extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
if (!arg->extraie.ptr) {
@ -6570,17 +6653,26 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
if (vif->p2p)
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT;
break;
case NL80211_IFTYPE_MESH_POINT:
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
fallthrough;
case NL80211_IFTYPE_AP:
arvif->vdev_type = WMI_VDEV_TYPE_AP;
if (vif->p2p)
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO;
break;
case NL80211_IFTYPE_MONITOR:
arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
ar->monitor_vdev_id = bit;
break;
case NL80211_IFTYPE_P2P_DEVICE:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
break;
default:
WARN_ON(1);
break;
@ -9253,9 +9345,11 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
arg->dwell_time_passive = scan_time_msec;
arg->max_scan_time = scan_time_msec;
arg->scan_f_passive = 1;
arg->scan_f_filter_prb_req = 1;
arg->burst_duration = duration;
if (!ar->ab->hw_params.single_pdev_only)
arg->scan_f_filter_prb_req = 1;
ret = ath11k_start_scan(ar, arg);
if (ret) {
ath11k_warn(ar->ab, "failed to start roc scan: %d\n", ret);
@ -9857,12 +9951,18 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
struct ieee80211_iface_combination *combinations;
struct ieee80211_iface_limit *limits;
int n_limits;
bool p2p;
p2p = ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_P2P_DEVICE);
combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
if (!combinations)
return -ENOMEM;
n_limits = 2;
if (p2p)
n_limits = 3;
else
n_limits = 2;
limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);
if (!limits) {
@ -9870,39 +9970,29 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
return -ENOMEM;
}
limits[0].types |= BIT(NL80211_IFTYPE_STATION);
limits[1].types |= BIT(NL80211_IFTYPE_AP);
if (IS_ENABLED(CONFIG_MAC80211_MESH) &&
ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
combinations[0].limits = limits;
combinations[0].n_limits = n_limits;
combinations[0].beacon_int_infra_match = true;
combinations[0].beacon_int_min_gcd = 100;
if (ab->hw_params.support_dual_stations) {
limits[0].max = 2;
limits[0].types |= BIT(NL80211_IFTYPE_STATION);
limits[1].max = 1;
limits[1].types |= BIT(NL80211_IFTYPE_AP);
if (IS_ENABLED(CONFIG_MAC80211_MESH) &&
ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
combinations[0].limits = limits;
combinations[0].n_limits = 2;
combinations[0].max_interfaces = ab->hw_params.num_vdevs;
combinations[0].num_different_channels = 2;
combinations[0].beacon_int_infra_match = true;
combinations[0].beacon_int_min_gcd = 100;
} else {
limits[0].max = 1;
limits[0].types |= BIT(NL80211_IFTYPE_STATION);
limits[1].max = 16;
limits[1].types |= BIT(NL80211_IFTYPE_AP);
if (IS_ENABLED(CONFIG_MAC80211_MESH) &&
ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
combinations[0].limits = limits;
combinations[0].n_limits = 2;
combinations[0].max_interfaces = 16;
combinations[0].num_different_channels = 1;
combinations[0].beacon_int_infra_match = true;
combinations[0].beacon_int_min_gcd = 100;
combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
@ -9911,6 +10001,13 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
BIT(NL80211_CHAN_WIDTH_160);
}
if (p2p) {
limits[1].types |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
limits[2].max = 1;
limits[2].types |= BIT(NL80211_IFTYPE_P2P_DEVICE);
}
ar->hw->wiphy->iface_combinations = combinations;
ar->hw->wiphy->n_iface_combinations = 1;

View File

@ -19,6 +19,7 @@
#define MHI_TIMEOUT_DEFAULT_MS 20000
#define RDDM_DUMP_SIZE 0x420000
#define MHI_CB_INVALID 0xff
static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
{
@ -158,9 +159,8 @@ void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab)
ath11k_dbg(ab, ATH11K_DBG_PCI, "mhistatus 0x%x\n", val);
/* Observed on QCA6390 that after SOC_GLOBAL_RESET, MHISTATUS
* has SYSERR bit set and thus need to set MHICTRL_RESET
* to clear SYSERR.
/* After SOC_GLOBAL_RESET, MHISTATUS may still have SYSERR bit set
* and thus need to set MHICTRL_RESET to clear SYSERR.
*/
ath11k_pcic_write32(ab, MHICTRL, MHICTRL_RESET_MASK);
@ -269,6 +269,7 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
enum mhi_callback cb)
{
struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev);
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
ath11k_dbg(ab, ATH11K_DBG_BOOT, "notify status reason %s\n",
ath11k_mhi_op_callback_to_str(cb));
@ -279,12 +280,21 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
break;
case MHI_CB_EE_RDDM:
ath11k_warn(ab, "firmware crashed: MHI_CB_EE_RDDM\n");
if (ab_pci->mhi_pre_cb == MHI_CB_EE_RDDM) {
ath11k_dbg(ab, ATH11K_DBG_BOOT,
"do not queue again for consecutive RDDM event\n");
break;
}
if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)))
queue_work(ab->workqueue_aux, &ab->reset_work);
break;
default:
break;
}
ab_pci->mhi_pre_cb = cb;
}
static int ath11k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl,
@ -397,6 +407,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
goto free_controller;
}
ab_pci->mhi_pre_cb = MHI_CB_INVALID;
ret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config);
if (ret) {
ath11k_err(ab, "failed to register to mhi bus, err = %d\n", ret);

View File

@ -0,0 +1,149 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
#include "wmi.h"
#include "mac.h"
#include "p2p.h"
static void ath11k_p2p_noa_ie_fill(u8 *data, size_t len,
const struct ath11k_wmi_p2p_noa_info *noa)
{
struct ieee80211_p2p_noa_attr *noa_attr;
u8 noa_descriptors, ctwindow;
bool oppps;
__le16 *noa_attr_len;
u16 attr_len;
int i;
ctwindow = u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_CTWIN_TU);
oppps = u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS);
noa_descriptors = u32_get_bits(noa->noa_attr,
WMI_P2P_NOA_INFO_DESC_NUM);
/* P2P IE */
data[0] = WLAN_EID_VENDOR_SPECIFIC;
data[1] = len - 2;
data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
data[5] = WLAN_OUI_TYPE_WFA_P2P;
/* NOA ATTR */
data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */
noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9];
noa_attr->index = u32_get_bits(noa->noa_attr,
WMI_P2P_NOA_INFO_INDEX);
noa_attr->oppps_ctwindow = ctwindow;
if (oppps)
noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT;
for (i = 0; i < noa_descriptors; i++) {
noa_attr->desc[i].count = noa->descriptors[i].type_count;
noa_attr->desc[i].duration =
cpu_to_le32(noa->descriptors[i].duration);
noa_attr->desc[i].interval =
cpu_to_le32(noa->descriptors[i].interval);
noa_attr->desc[i].start_time =
cpu_to_le32(noa->descriptors[i].start_time);
}
attr_len = 2; /* index + oppps_ctwindow */
attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
*noa_attr_len = __cpu_to_le16(attr_len);
}
static size_t
ath11k_p2p_noa_ie_len_compute(const struct ath11k_wmi_p2p_noa_info *noa)
{
size_t len = 0;
u8 noa_descriptors = u32_get_bits(noa->noa_attr,
WMI_P2P_NOA_INFO_DESC_NUM);
if (!(noa_descriptors) &&
!(u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS)))
return 0;
len += 1 + 1 + 4; /* EID + len + OUI */
len += 1 + 2; /* noa attr + attr len */
len += 1 + 1; /* index + oppps_ctwindow */
len += noa_descriptors *
sizeof(struct ieee80211_p2p_noa_desc);
return len;
}
static void ath11k_p2p_noa_ie_assign(struct ath11k_vif *arvif, void *ie,
size_t len)
{
struct ath11k *ar = arvif->ar;
lockdep_assert_held(&ar->data_lock);
kfree(arvif->u.ap.noa_data);
arvif->u.ap.noa_data = ie;
arvif->u.ap.noa_len = len;
}
static void __ath11k_p2p_noa_update(struct ath11k_vif *arvif,
const struct ath11k_wmi_p2p_noa_info *noa)
{
struct ath11k *ar = arvif->ar;
void *ie;
size_t len;
lockdep_assert_held(&ar->data_lock);
ath11k_p2p_noa_ie_assign(arvif, NULL, 0);
len = ath11k_p2p_noa_ie_len_compute(noa);
if (!len)
return;
ie = kmalloc(len, GFP_ATOMIC);
if (!ie)
return;
ath11k_p2p_noa_ie_fill(ie, len, noa);
ath11k_p2p_noa_ie_assign(arvif, ie, len); }
void ath11k_p2p_noa_update(struct ath11k_vif *arvif,
const struct ath11k_wmi_p2p_noa_info *noa)
{
struct ath11k *ar = arvif->ar;
spin_lock_bh(&ar->data_lock);
__ath11k_p2p_noa_update(arvif, noa);
spin_unlock_bh(&ar->data_lock);
}
static void ath11k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
struct ath11k_p2p_noa_arg *arg = data;
if (arvif->vdev_id != arg->vdev_id)
return;
ath11k_p2p_noa_update(arvif, arg->noa);
}
void ath11k_p2p_noa_update_by_vdev_id(struct ath11k *ar, u32 vdev_id,
const struct ath11k_wmi_p2p_noa_info *noa)
{
struct ath11k_p2p_noa_arg arg = {
.vdev_id = vdev_id,
.noa = noa,
};
ieee80211_iterate_active_interfaces_atomic(ar->hw,
IEEE80211_IFACE_ITER_NORMAL,
ath11k_p2p_noa_update_vdev_iter,
&arg);
}

View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_P2P_H
#define ATH11K_P2P_H
#include "wmi.h"
struct ath11k_wmi_p2p_noa_info;
struct ath11k_p2p_noa_arg {
u32 vdev_id;
const struct ath11k_wmi_p2p_noa_info *noa;
};
void ath11k_p2p_noa_update(struct ath11k_vif *arvif,
const struct ath11k_wmi_p2p_noa_info *noa);
void ath11k_p2p_noa_update_by_vdev_id(struct ath11k *ar, u32 vdev_id,
const struct ath11k_wmi_p2p_noa_info *noa);
#endif

View File

@ -64,6 +64,7 @@ struct ath11k_pci {
char amss_path[100];
struct mhi_controller *mhi_ctrl;
const struct ath11k_msi_config *msi_config;
enum mhi_callback mhi_pre_cb;
u32 register_window;
/* protects register_window above */

View File

@ -101,7 +101,7 @@ static ssize_t ath11k_thermal_show_temp(struct device *dev,
spin_unlock_bh(&ar->data_lock);
/* display in millidegree Celsius */
ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000);
ret = sysfs_emit(buf, "%d\n", temperature * 1000);
out:
mutex_unlock(&ar->conf_mutex);
return ret;

View File

@ -20,6 +20,7 @@
#include "hw.h"
#include "peer.h"
#include "testmode.h"
#include "p2p.h"
struct wmi_tlv_policy {
size_t min_len;
@ -154,6 +155,10 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
.min_len = sizeof(struct wmi_per_chain_rssi_stats) },
[WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT] = {
.min_len = sizeof(struct wmi_twt_add_dialog_event) },
[WMI_TAG_P2P_NOA_INFO] = {
.min_len = sizeof(struct ath11k_wmi_p2p_noa_info) },
[WMI_TAG_P2P_NOA_EVENT] = {
.min_len = sizeof(struct wmi_p2p_noa_event) },
};
#define PRIMAP(_hw_mode_) \
@ -981,7 +986,7 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
FIELD_PREP(WMI_TLV_LEN, 0);
/* Note: This is a nested TLV containing:
* [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
* [wmi_tlv][ath11k_wmi_p2p_noa_descriptor][wmi_tlv]..
*/
ptr += sizeof(*tlv);
@ -1704,6 +1709,45 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
return ret;
}
int ath11k_wmi_p2p_go_bcn_ie(struct ath11k *ar, u32 vdev_id,
const u8 *p2p_ie)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct wmi_p2p_go_set_beacon_ie_cmd *cmd;
size_t p2p_ie_len, aligned_len;
struct wmi_tlv *tlv;
struct sk_buff *skb;
int ret, len;
p2p_ie_len = p2p_ie[1] + 2;
aligned_len = roundup(p2p_ie_len, 4);
len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len;
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_p2p_go_set_beacon_ie_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_P2P_GO_SET_BEACON_IE) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->vdev_id = vdev_id;
cmd->ie_buf_len = p2p_ie_len;
tlv = (struct wmi_tlv *)cmd->tlv;
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
FIELD_PREP(WMI_TLV_LEN, aligned_len);
memcpy(tlv->value, p2p_ie, p2p_ie_len);
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_P2P_GO_SET_BEACON_IE);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_P2P_GO_SET_BEACON_IE\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
struct ieee80211_mutable_offsets *offs,
struct sk_buff *bcn, u32 ema_params)
@ -8606,6 +8650,64 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab,
kfree(tb);
}
static int ath11k_wmi_p2p_noa_event(struct ath11k_base *ab,
struct sk_buff *skb)
{
const void **tb;
const struct wmi_p2p_noa_event *ev;
const struct ath11k_wmi_p2p_noa_info *noa;
struct ath11k *ar;
int ret, vdev_id;
u8 noa_descriptors;
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
return ret;
}
ev = tb[WMI_TAG_P2P_NOA_EVENT];
noa = tb[WMI_TAG_P2P_NOA_INFO];
if (!ev || !noa) {
ret = -EPROTO;
goto out;
}
vdev_id = ev->vdev_id;
noa_descriptors = u32_get_bits(noa->noa_attr,
WMI_P2P_NOA_INFO_DESC_NUM);
if (noa_descriptors > WMI_P2P_MAX_NOA_DESCRIPTORS) {
ath11k_warn(ab, "invalid descriptor num %d in P2P NoA event\n",
noa_descriptors);
return -EINVAL;
goto out;
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
"wmi tlv p2p noa vdev_id %i descriptors %u\n",
vdev_id, noa_descriptors);
rcu_read_lock();
ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id);
if (!ar) {
ath11k_warn(ab, "invalid vdev id %d in P2P NoA event\n",
vdev_id);
ret = -EINVAL;
goto unlock;
}
ath11k_p2p_noa_update_by_vdev_id(ar, vdev_id, noa);
unlock:
rcu_read_unlock();
out:
kfree(tb);
return 0;
}
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
@ -8733,6 +8835,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_GTK_OFFLOAD_STATUS_EVENTID:
ath11k_wmi_gtk_offload_status_event(ab, skb);
break;
case WMI_P2P_NOA_EVENTID:
ath11k_wmi_p2p_noa_event(ab, skb);
break;
default:
ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id);
break;

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_WMI_H
@ -60,13 +60,9 @@ struct wmi_tlv {
#define WLAN_SCAN_MAX_HINT_BSSID 10
#define MAX_RNR_BSS 5
#define WLAN_SCAN_MAX_HINT_S_SSID 10
#define WLAN_SCAN_MAX_HINT_BSSID 10
#define MAX_RNR_BSS 5
#define WLAN_SCAN_PARAMS_MAX_SSID 16
#define WLAN_SCAN_PARAMS_MAX_BSSID 4
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 256
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 512
#define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1
@ -3444,34 +3440,6 @@ struct wmi_bssid_arg {
const u8 *bssid;
};
struct wmi_start_scan_arg {
u32 scan_id;
u32 scan_req_id;
u32 vdev_id;
u32 scan_priority;
u32 notify_scan_events;
u32 dwell_time_active;
u32 dwell_time_passive;
u32 min_rest_time;
u32 max_rest_time;
u32 repeat_probe_time;
u32 probe_spacing_time;
u32 idle_time;
u32 max_scan_time;
u32 probe_delay;
u32 scan_ctrl_flags;
u32 ie_len;
u32 n_channels;
u32 n_ssids;
u32 n_bssids;
u8 ie[WLAN_SCAN_PARAMS_MAX_IE_LEN];
u32 channels[64];
struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID];
struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID];
};
#define WMI_SCAN_STOP_ONE 0x00000000
#define WMI_SCN_STOP_VAP_ALL 0x01000000
#define WMI_SCAN_STOP_ALL 0x04000000
@ -3630,6 +3598,37 @@ struct wmi_ftm_event_msg {
u8 data[];
} __packed;
#define WMI_P2P_MAX_NOA_DESCRIPTORS 4
struct wmi_p2p_noa_event {
u32 vdev_id;
} __packed;
struct ath11k_wmi_p2p_noa_descriptor {
u32 type_count; /* 255: continuous schedule, 0: reserved */
u32 duration; /* Absent period duration in micro seconds */
u32 interval; /* Absent period interval in micro seconds */
u32 start_time; /* 32 bit tsf time when in starts */
} __packed;
#define WMI_P2P_NOA_INFO_CHANGED_FLAG BIT(0)
#define WMI_P2P_NOA_INFO_INDEX GENMASK(15, 8)
#define WMI_P2P_NOA_INFO_OPP_PS BIT(16)
#define WMI_P2P_NOA_INFO_CTWIN_TU GENMASK(23, 17)
#define WMI_P2P_NOA_INFO_DESC_NUM GENMASK(31, 24)
struct ath11k_wmi_p2p_noa_info {
/* Bit 0 - Flag to indicate an update in NOA schedule
* Bits 7-1 - Reserved
* Bits 15-8 - Index (identifies the instance of NOA sub element)
* Bit 16 - Opp PS state of the AP
* Bits 23-17 - Ctwindow in TUs
* Bits 31-24 - Number of NOA descriptors
*/
u32 noa_attr;
struct ath11k_wmi_p2p_noa_descriptor descriptors[WMI_P2P_MAX_NOA_DESCRIPTORS];
} __packed;
#define WMI_BEACON_TX_BUFFER_SIZE 512
#define WMI_EMA_TMPL_IDX_SHIFT 8
@ -3653,6 +3652,13 @@ struct wmi_bcn_tmpl_cmd {
u32 ema_params;
} __packed;
struct wmi_p2p_go_set_beacon_ie_cmd {
u32 tlv_header;
u32 vdev_id;
u32 ie_buf_len;
u8 tlv[];
} __packed;
struct wmi_key_seq_counter {
u32 key_seq_counter_l;
u32 key_seq_counter_h;
@ -5740,8 +5746,6 @@ struct wmi_debug_log_config_cmd_fixed_param {
u32 value;
} __packed;
#define WMI_MAX_MEM_REQS 32
#define MAX_RADIOS 3
#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)
@ -6349,6 +6353,8 @@ int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len);
int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
struct sk_buff *frame);
int ath11k_wmi_p2p_go_bcn_ie(struct ath11k *ar, u32 vdev_id,
const u8 *p2p_ie);
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
struct ieee80211_mutable_offsets *offs,
struct sk_buff *bcn, u32 ema_param);

View File

@ -960,8 +960,9 @@ int ath12k_dp_service_srng(struct ath12k_base *ab,
if (ab->hw_params->ring_mask->host2rxdma[grp_id]) {
struct ath12k_dp *dp = &ab->dp;
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
LIST_HEAD(list);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, 0);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &list, 0);
}
/* TODO: Implement handler for other interrupts */
@ -1146,11 +1147,11 @@ void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif)
static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
{
struct ath12k_rx_desc_info *desc_info, *tmp;
struct ath12k_rx_desc_info *desc_info;
struct ath12k_tx_desc_info *tx_desc_info, *tmp1;
struct ath12k_dp *dp = &ab->dp;
struct sk_buff *skb;
int i;
int i, j;
u32 pool_id, tx_spt_page;
if (!dp->spt_info)
@ -1159,16 +1160,23 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
/* RX Descriptor cleanup */
spin_lock_bh(&dp->rx_desc_lock);
list_for_each_entry_safe(desc_info, tmp, &dp->rx_desc_used_list, list) {
list_del(&desc_info->list);
skb = desc_info->skb;
for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
desc_info = dp->spt_info->rxbaddr[i];
if (!skb)
continue;
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
if (!desc_info[j].in_use) {
list_del(&desc_info[j].list);
continue;
}
dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr,
skb->len + skb_tailroom(skb), DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
skb = desc_info[j].skb;
if (!skb)
continue;
dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr,
skb->len + skb_tailroom(skb), DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
}
}
for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
@ -1444,7 +1452,6 @@ static int ath12k_dp_cc_init(struct ath12k_base *ab)
u32 cmem_base;
INIT_LIST_HEAD(&dp->rx_desc_free_list);
INIT_LIST_HEAD(&dp->rx_desc_used_list);
spin_lock_init(&dp->rx_desc_lock);
for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) {

View File

@ -282,6 +282,8 @@ struct ath12k_rx_desc_info {
struct sk_buff *skb;
u32 cookie;
u32 magic;
u8 in_use : 1,
reserved : 7;
};
struct ath12k_tx_desc_info {
@ -347,8 +349,7 @@ struct ath12k_dp {
struct ath12k_spt_info *spt_info;
u32 num_spt_pages;
struct list_head rx_desc_free_list;
struct list_head rx_desc_used_list;
/* protects the free and used desc list */
/* protects the free desc list */
spinlock_t rx_desc_lock;
struct list_head tx_desc_free_list[ATH12K_HW_MAX_QUEUES];
@ -377,8 +378,6 @@ struct ath12k_dp {
/* peer meta data */
#define HTT_TCL_META_DATA_PEER_ID GENMASK(15, 2)
#define HTT_TX_WBM_COMP_STATUS_OFFSET 8
/* HTT tx completion is overlaid in wbm_release_ring */
#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(16, 13)
#define HTT_TX_WBM_COMP_INFO1_REINJECT_REASON GENMASK(3, 0)

View File

@ -261,9 +261,53 @@ static int ath12k_dp_purge_mon_ring(struct ath12k_base *ab)
return -ETIMEDOUT;
}
static size_t ath12k_dp_list_cut_nodes(struct list_head *list,
struct list_head *head,
size_t count)
{
struct list_head *cur;
struct ath12k_rx_desc_info *rx_desc;
size_t nodes = 0;
if (!count) {
INIT_LIST_HEAD(list);
goto out;
}
list_for_each(cur, head) {
if (!count)
break;
rx_desc = list_entry(cur, struct ath12k_rx_desc_info, list);
rx_desc->in_use = true;
count--;
nodes++;
}
list_cut_before(list, head, cur);
out:
return nodes;
}
static void ath12k_dp_rx_enqueue_free(struct ath12k_dp *dp,
struct list_head *used_list)
{
struct ath12k_rx_desc_info *rx_desc, *safe;
/* Reset the use flag */
list_for_each_entry_safe(rx_desc, safe, used_list, list)
rx_desc->in_use = false;
spin_lock_bh(&dp->rx_desc_lock);
list_splice_tail(used_list, &dp->rx_desc_free_list);
spin_unlock_bh(&dp->rx_desc_lock);
}
/* Returns number of Rx buffers replenished */
int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
struct dp_rxdma_ring *rx_ring,
struct list_head *used_list,
int req_entries)
{
struct ath12k_buffer_addr *desc;
@ -292,6 +336,19 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
req_entries = min(num_free, req_entries);
num_remain = req_entries;
if (!num_remain)
goto out;
/* Get the descriptor from free list */
if (list_empty(used_list)) {
spin_lock_bh(&dp->rx_desc_lock);
req_entries = ath12k_dp_list_cut_nodes(used_list,
&dp->rx_desc_free_list,
num_remain);
spin_unlock_bh(&dp->rx_desc_lock);
num_remain = req_entries;
}
while (num_remain > 0) {
skb = dev_alloc_skb(DP_RX_BUFFER_SIZE +
DP_RX_BUFFER_ALIGN_SIZE);
@ -311,33 +368,20 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
if (dma_mapping_error(ab->dev, paddr))
goto fail_free_skb;
spin_lock_bh(&dp->rx_desc_lock);
/* Get desc from free list and store in used list
* for cleanup purposes
*
* TODO: pass the removed descs rather than
* add/read to optimize
*/
rx_desc = list_first_entry_or_null(&dp->rx_desc_free_list,
rx_desc = list_first_entry_or_null(used_list,
struct ath12k_rx_desc_info,
list);
if (!rx_desc) {
spin_unlock_bh(&dp->rx_desc_lock);
if (!rx_desc)
goto fail_dma_unmap;
}
rx_desc->skb = skb;
cookie = rx_desc->cookie;
list_del(&rx_desc->list);
list_add_tail(&rx_desc->list, &dp->rx_desc_used_list);
spin_unlock_bh(&dp->rx_desc_lock);
desc = ath12k_hal_srng_src_get_next_entry(ab, srng);
if (!desc)
goto fail_buf_unassign;
goto fail_dma_unmap;
list_del(&rx_desc->list);
ATH12K_SKB_RXCB(skb)->paddr = paddr;
num_remain--;
@ -345,26 +389,19 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
ath12k_hal_rx_buf_addr_info_set(desc, paddr, cookie, mgr);
}
ath12k_hal_srng_access_end(ab, srng);
goto out;
spin_unlock_bh(&srng->lock);
return req_entries - num_remain;
fail_buf_unassign:
spin_lock_bh(&dp->rx_desc_lock);
list_del(&rx_desc->list);
list_add_tail(&rx_desc->list, &dp->rx_desc_free_list);
rx_desc->skb = NULL;
spin_unlock_bh(&dp->rx_desc_lock);
fail_dma_unmap:
dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
fail_free_skb:
dev_kfree_skb_any(skb);
out:
ath12k_hal_srng_access_end(ab, srng);
if (!list_empty(used_list))
ath12k_dp_rx_enqueue_free(dp, used_list);
spin_unlock_bh(&srng->lock);
return req_entries - num_remain;
@ -422,13 +459,12 @@ static int ath12k_dp_rxdma_mon_ring_buf_setup(struct ath12k_base *ab,
static int ath12k_dp_rxdma_ring_buf_setup(struct ath12k_base *ab,
struct dp_rxdma_ring *rx_ring)
{
int num_entries;
LIST_HEAD(list);
num_entries = rx_ring->refill_buf_ring.size /
ath12k_hal_srng_get_entrysize(ab, HAL_RXDMA_BUF);
rx_ring->bufs_max = rx_ring->refill_buf_ring.size /
ath12k_hal_srng_get_entrysize(ab, HAL_RXDMA_BUF);
rx_ring->bufs_max = num_entries;
ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_entries);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &list, 0);
return 0;
}
@ -2585,6 +2621,7 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
struct napi_struct *napi, int budget)
{
LIST_HEAD(rx_desc_used_list);
struct ath12k_rx_desc_info *desc_info;
struct ath12k_dp *dp = &ab->dp;
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
@ -2637,9 +2674,7 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
msdu = desc_info->skb;
desc_info->skb = NULL;
spin_lock_bh(&dp->rx_desc_lock);
list_move_tail(&desc_info->list, &dp->rx_desc_free_list);
spin_unlock_bh(&dp->rx_desc_lock);
list_add_tail(&desc_info->list, &rx_desc_used_list);
rxcb = ATH12K_SKB_RXCB(msdu);
dma_unmap_single(ab->dev, rxcb->paddr,
@ -2700,7 +2735,8 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
if (!total_msdu_reaped)
goto exit;
ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_buffs_reaped);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &rx_desc_used_list,
num_buffs_reaped);
ath12k_dp_rx_process_received_packets(ab, napi, &msdu_list,
ring_id);
@ -3021,9 +3057,9 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar,
}
desc_info->skb = defrag_skb;
desc_info->in_use = true;
list_del(&desc_info->list);
list_add_tail(&desc_info->list, &dp->rx_desc_used_list);
spin_unlock_bh(&dp->rx_desc_lock);
ATH12K_SKB_RXCB(defrag_skb)->paddr = buf_paddr;
@ -3085,9 +3121,9 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar,
err_free_desc:
spin_lock_bh(&dp->rx_desc_lock);
list_del(&desc_info->list);
list_add_tail(&desc_info->list, &dp->rx_desc_free_list);
desc_info->in_use = false;
desc_info->skb = NULL;
list_add_tail(&desc_info->list, &dp->rx_desc_free_list);
spin_unlock_bh(&dp->rx_desc_lock);
err_unmap_dma:
dma_unmap_single(ab->dev, buf_paddr, defrag_skb->len + skb_tailroom(defrag_skb),
@ -3304,6 +3340,7 @@ static int ath12k_dp_rx_frag_h_mpdu(struct ath12k *ar,
static int
ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
struct list_head *used_list,
bool drop, u32 cookie)
{
struct ath12k_base *ab = ar->ab;
@ -3333,9 +3370,8 @@ ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
msdu = desc_info->skb;
desc_info->skb = NULL;
spin_lock_bh(&ab->dp.rx_desc_lock);
list_move_tail(&desc_info->list, &ab->dp.rx_desc_free_list);
spin_unlock_bh(&ab->dp.rx_desc_lock);
list_add_tail(&desc_info->list, used_list);
rxcb = ATH12K_SKB_RXCB(msdu);
dma_unmap_single(ar->ab->dev, rxcb->paddr,
@ -3391,6 +3427,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
struct hal_reo_dest_ring *reo_desc;
struct dp_rxdma_ring *rx_ring;
struct dp_srng *reo_except;
LIST_HEAD(rx_desc_used_list);
u32 desc_bank, num_msdus;
struct hal_srng *srng;
struct ath12k_dp *dp;
@ -3458,7 +3495,9 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
ar = ab->pdevs[pdev_id].ar;
if (!ath12k_dp_process_rx_err_buf(ar, reo_desc, drop,
if (!ath12k_dp_process_rx_err_buf(ar, reo_desc,
&rx_desc_used_list,
drop,
msdu_cookies[i]))
tot_n_bufs_reaped++;
}
@ -3478,7 +3517,8 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
rx_ring = &dp->rx_refill_buf_ring;
ath12k_dp_rx_bufs_replenish(ab, rx_ring, tot_n_bufs_reaped);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &rx_desc_used_list,
tot_n_bufs_reaped);
return tot_n_bufs_reaped;
}
@ -3695,6 +3735,7 @@ static void ath12k_dp_rx_wbm_err(struct ath12k *ar,
int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
struct napi_struct *napi, int budget)
{
LIST_HEAD(rx_desc_used_list);
struct ath12k *ar;
struct ath12k_dp *dp = &ab->dp;
struct dp_rxdma_ring *rx_ring;
@ -3748,9 +3789,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
msdu = desc_info->skb;
desc_info->skb = NULL;
spin_lock_bh(&dp->rx_desc_lock);
list_move_tail(&desc_info->list, &dp->rx_desc_free_list);
spin_unlock_bh(&dp->rx_desc_lock);
list_add_tail(&desc_info->list, &rx_desc_used_list);
rxcb = ATH12K_SKB_RXCB(msdu);
dma_unmap_single(ab->dev, rxcb->paddr,
@ -3786,7 +3825,8 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
if (!num_buffs_reaped)
goto done;
ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_buffs_reaped);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &rx_desc_used_list,
num_buffs_reaped);
rcu_read_lock();
while ((msdu = __skb_dequeue(&msdu_list))) {

View File

@ -118,6 +118,7 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int mac_id,
int budget);
int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
struct dp_rxdma_ring *rx_ring,
struct list_head *used_list,
int req_entries);
int ath12k_dp_rx_pdev_mon_attach(struct ath12k *ar);
int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id);

View File

@ -414,7 +414,7 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab,
struct ath12k_dp_htt_wbm_tx_status ts = {0};
enum hal_wbm_htt_tx_comp_status wbm_status;
status_desc = desc + HTT_TX_WBM_COMP_STATUS_OFFSET;
status_desc = desc;
wbm_status = le32_get_bits(status_desc->info0,
HTT_TX_WBM_COMP_INFO0_STATUS);

View File

@ -1900,7 +1900,7 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
if (arg->bw_160)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ);
if (arg->bw_320)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_EXT_320MHZ);
cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_320MHZ);
/* Typically if STBC is enabled for VHT it should be enabled
* for HT as well

View File

@ -164,10 +164,6 @@ struct wmi_tlv {
#define WLAN_SCAN_MAX_HINT_BSSID 10
#define MAX_RNR_BSS 5
#define WLAN_SCAN_MAX_HINT_S_SSID 10
#define WLAN_SCAN_MAX_HINT_BSSID 10
#define MAX_RNR_BSS 5
#define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1
#define WMI_BA_MODE_BUFFER_SIZE_256 3
@ -3357,34 +3353,6 @@ struct wmi_bssid_arg {
const u8 *bssid;
};
struct wmi_start_scan_arg {
u32 scan_id;
u32 scan_req_id;
u32 vdev_id;
u32 scan_priority;
u32 notify_scan_events;
u32 dwell_time_active;
u32 dwell_time_passive;
u32 min_rest_time;
u32 max_rest_time;
u32 repeat_probe_time;
u32 probe_spacing_time;
u32 idle_time;
u32 max_scan_time;
u32 probe_delay;
u32 scan_ctrl_flags;
u32 ie_len;
u32 n_channels;
u32 n_ssids;
u32 n_bssids;
u8 ie[WLAN_SCAN_PARAMS_MAX_IE_LEN];
u32 channels[64];
struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID];
struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID];
};
#define WMI_SCAN_STOP_ONE 0x00000000
#define WMI_SCAN_STOP_VAP_ALL 0x01000000
#define WMI_SCAN_STOP_ALL 0x04000000
@ -4776,8 +4744,6 @@ struct wmi_probe_tmpl_cmd {
__le32 buf_len;
} __packed;
#define WMI_MAX_MEM_REQS 32
#define MAX_RADIOS 3
#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)

View File

@ -364,8 +364,7 @@ static void ath6kl_htc_tx_prep_pkt(struct htc_packet *packet, u8 flags,
packet->buf -= HTC_HDR_LENGTH;
hdr = (struct htc_frame_hdr *)packet->buf;
/* Endianess? */
put_unaligned((u16)packet->act_len, &hdr->payld_len);
put_unaligned_le16(packet->act_len, &hdr->payld_len);
hdr->flags = flags;
hdr->eid = packet->endpoint;
hdr->ctrl[0] = ctrl0;

View File

@ -237,8 +237,7 @@ static int htc_issue_packets(struct htc_target *target,
packet->info.tx.flags |= HTC_FLAGS_TX_FIXUP_NETBUF;
/* Endianess? */
put_unaligned((u16) payload_len, &htc_hdr->payld_len);
put_unaligned_le16(payload_len, &htc_hdr->payld_len);
htc_hdr->flags = packet->info.tx.flags;
htc_hdr->eid = (u8) packet->endpoint;
htc_hdr->ctrl[0] = 0;

View File

@ -39,6 +39,7 @@ extern int ath9k_modparam_nohwcrypt;
extern int ath9k_led_blink;
extern bool is_ath9k_unloaded;
extern int ath9k_use_chanctx;
extern int ath9k_use_msi;
/*************************/
/* Descriptor Management */

View File

@ -76,7 +76,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_4k_header *modal_hdr)
{
PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain0 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
PR_EEP("Switch Settle", modal_hdr->switchSettling);

View File

@ -79,8 +79,8 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_ar9287_header *modal_hdr)
{
PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Chain0 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);

View File

@ -135,9 +135,9 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_header *modal_hdr)
{
PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2]));
PR_EEP("Chain0 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Chain2 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[2]));
PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);

View File

@ -21,8 +21,6 @@
#include <linux/module.h>
#include "ath9k.h"
extern int ath9k_use_msi;
static const struct pci_device_id ath_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */

View File

@ -1674,8 +1674,14 @@ static void
ath9k_set_moredata(struct ath_softc *sc, struct ath_buf *bf, bool val)
{
struct ieee80211_hdr *hdr;
u16 mask = cpu_to_le16(IEEE80211_FCTL_MOREDATA);
u16 mask_val = mask * val;
__le16 mask, mask_val;
mask = cpu_to_le16(IEEE80211_FCTL_MOREDATA);
if (val)
mask_val = mask;
else
mask_val = 0;
hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
if ((hdr->frame_control & mask) != mask_val) {

View File

@ -756,9 +756,9 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
if (sta->deflink.vht_cap.vht_supported) {
sta_priv->supported_rates.op_rate_mode = STA_11ac;
sta_priv->supported_rates.vht_rx_mcs_map =
sta->deflink.vht_cap.vht_mcs.rx_mcs_map;
le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);
sta_priv->supported_rates.vht_tx_mcs_map =
sta->deflink.vht_cap.vht_mcs.tx_mcs_map;
le16_to_cpu(sta->deflink.vht_cap.vht_mcs.tx_mcs_map);
}
}

View File

@ -318,7 +318,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
memset(&status, 0, sizeof(status));
bd = (struct wcn36xx_rx_bd *)skb->data;
buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
buff_to_be(bd, sizeof(*bd)/sizeof(u32));
wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP,
"BD <<< ", (char *)bd,
sizeof(struct wcn36xx_rx_bd));
@ -692,7 +692,7 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
/* MGMT and CTRL frames are handeld here*/
wcn36xx_set_tx_mgmt(&bd, wcn, &vif_priv, skb, bcast);
buff_to_be((u32 *)&bd, sizeof(bd)/sizeof(u32));
buff_to_be(&bd, sizeof(bd)/sizeof(u32));
bd.tx_bd_sign = 0xbdbdbdbd;
ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low);

View File

@ -100,11 +100,14 @@ enum wcn36xx_ampdu_state {
#define RF_IRIS_WCN3660 0x3660
#define RF_IRIS_WCN3680 0x3680
static inline void buff_to_be(u32 *buf, size_t len)
static inline void buff_to_be(void *buf, size_t len)
{
__be32 *to = buf;
u32 *from = buf;
int i;
for (i = 0; i < len; i++)
buf[i] = cpu_to_be32(buf[i]);
to[i] = cpu_to_be32(from[i]);
}
struct nv_data {

View File

@ -2735,7 +2735,7 @@ int wil_cfg80211_iface_combinations_from_fw(
return 0;
}
combo = conc->combos;
combo = (const struct wil_fw_concurrency_combo *)(conc + 1);
n_combos = le16_to_cpu(conc->n_combos);
for (i = 0; i < n_combos; i++) {
total_limits += combo->n_limits;
@ -2751,7 +2751,7 @@ int wil_cfg80211_iface_combinations_from_fw(
return -ENOMEM;
iface_limit = (struct ieee80211_iface_limit *)(iface_combinations +
n_combos);
combo = conc->combos;
combo = (const struct wil_fw_concurrency_combo *)(conc + 1);
for (i = 0; i < n_combos; i++) {
iface_combinations[i].max_interfaces = combo->max_interfaces;
iface_combinations[i].num_different_channels =

View File

@ -93,7 +93,6 @@ struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */
/* number of concurrency combinations that follow */
__le16 n_combos;
/* keep last - combinations, variable size by n_combos */
struct wil_fw_concurrency_combo combos[];
} __packed;
/* brd file info encoded inside a comment record */

View File

@ -212,8 +212,8 @@ fw_handle_concurrency(struct wil6210_priv *wil, const void *data,
}
n_combos = le16_to_cpu(rec->n_combos);
remain = size - offsetof(struct wil_fw_record_concurrency, combos);
combo = rec->combos;
remain = size - sizeof(struct wil_fw_record_concurrency);
combo = (const struct wil_fw_concurrency_combo *)(rec + 1);
for (i = 0; i < n_combos; i++) {
if (remain < sizeof(*combo))
goto out_short;