mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
ath.git patches for v7.2 (PR #3)
In ath12k, add driver support for WDS mode. In ath11k and ath12k, a number of cleanups and minor bug fixes. -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQ/mtSHzPUi16IfDEksFbugiYzLewUCah7oAwAKCRAsFbugiYzL e4FRAQDP7XeGi3lDh02TlRthSY1z1fw8dTnUoHrok3MozxwGrQEAztgSQg1wjERh PAKcUibVH/ebQf5MHziPl+/ZR24RCwM= =iZG5 -----END PGP SIGNATURE----- Merge tag 'ath-next-20260602' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath Jeff Johnson says: ================== ath.git patches for v7.2 (PR #3) In ath12k, add driver support for WDS mode. In ath11k and ath12k, a number of cleanups and minor bug fixes. ================== Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
commit
d03291b8c7
|
|
@ -267,7 +267,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_vdevs = 4,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
|
||||
|
|
@ -445,7 +445,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_vdevs = 4,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
|
|
@ -535,7 +535,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_vdevs = 4,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
|
|
@ -797,7 +797,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_vdevs = 4,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
|
|
@ -886,7 +886,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_vdevs = 4,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
|
|
|
|||
|
|
@ -2503,6 +2503,29 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap
|
|||
ieee80211_rx_napi(ar->hw, pubsta, msdu, napi);
|
||||
}
|
||||
|
||||
static bool ath11k_dp_rx_check_nwifi_hdr_len_valid(struct ath11k_base *ab,
|
||||
struct hal_rx_desc *rx_desc,
|
||||
struct sk_buff *msdu)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
u8 decap_type;
|
||||
u32 hdr_len;
|
||||
|
||||
decap_type = ath11k_dp_rx_h_msdu_start_decap_type(ab, rx_desc);
|
||||
if (decap_type != DP_RX_DECAP_TYPE_NATIVE_WIFI)
|
||||
return true;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (likely(hdr_len <= DP_MAX_NWIFI_HDR_LEN))
|
||||
return true;
|
||||
|
||||
ab->soc_stats.invalid_rbm++;
|
||||
WARN_ON_ONCE(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ath11k_dp_rx_process_msdu(struct ath11k *ar,
|
||||
struct sk_buff *msdu,
|
||||
struct sk_buff_head *msdu_list,
|
||||
|
|
@ -2573,6 +2596,11 @@ static int ath11k_dp_rx_process_msdu(struct ath11k *ar,
|
|||
}
|
||||
}
|
||||
|
||||
if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu))) {
|
||||
ret = -EINVAL;
|
||||
goto free_out;
|
||||
}
|
||||
|
||||
ath11k_dp_rx_h_ppdu(ar, rx_desc, rx_status);
|
||||
ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status);
|
||||
|
||||
|
|
@ -3262,6 +3290,12 @@ static int ath11k_dp_rx_h_verify_tkip_mic(struct ath11k *ar, struct ath11k_peer
|
|||
RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED;
|
||||
skb_pull(msdu, hal_rx_desc_sz);
|
||||
|
||||
if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ar->ab, rx_desc,
|
||||
msdu))) {
|
||||
dev_kfree_skb_any(msdu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ath11k_dp_rx_h_ppdu(ar, rx_desc, rxs);
|
||||
ath11k_dp_rx_h_undecap(ar, msdu, rx_desc,
|
||||
HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true);
|
||||
|
|
@ -3954,6 +3988,10 @@ static int ath11k_dp_rx_h_null_q_desc(struct ath11k *ar, struct sk_buff *msdu,
|
|||
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
|
||||
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
|
||||
}
|
||||
|
||||
if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ar->ab, desc, msdu)))
|
||||
return -EINVAL;
|
||||
|
||||
ath11k_dp_rx_h_ppdu(ar, desc, status);
|
||||
|
||||
ath11k_dp_rx_h_mpdu(ar, msdu, desc, status);
|
||||
|
|
@ -3998,7 +4036,7 @@ static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu,
|
|||
return drop;
|
||||
}
|
||||
|
||||
static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
|
||||
static bool ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status)
|
||||
{
|
||||
u16 msdu_len;
|
||||
|
|
@ -4006,15 +4044,28 @@ static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
|
|||
u8 l3pad_bytes;
|
||||
struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu);
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
|
||||
rxcb->is_first_msdu = ath11k_dp_rx_h_msdu_end_first_msdu(ar->ab, desc);
|
||||
rxcb->is_last_msdu = ath11k_dp_rx_h_msdu_end_last_msdu(ar->ab, desc);
|
||||
|
||||
l3pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(ar->ab, desc);
|
||||
msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(ar->ab, desc);
|
||||
|
||||
if (unlikely(hal_rx_desc_sz + l3pad_bytes + msdu_len > DP_RX_BUFFER_SIZE)) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_DATA,
|
||||
"invalid msdu len in tkip mic err %u\n", msdu_len);
|
||||
ath11k_dbg_dump(ab, ATH11K_DBG_DATA, NULL, "", desc,
|
||||
sizeof(*desc));
|
||||
return true;
|
||||
}
|
||||
|
||||
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
|
||||
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
|
||||
|
||||
if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
|
||||
return true;
|
||||
|
||||
ath11k_dp_rx_h_ppdu(ar, desc, status);
|
||||
|
||||
status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
|
||||
|
|
@ -4022,19 +4073,21 @@ static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
|
|||
|
||||
ath11k_dp_rx_h_undecap(ar, msdu, desc,
|
||||
HAL_ENCRYPT_TYPE_TKIP_MIC, status, false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ath11k_dp_rx_h_rxdma_err(struct ath11k *ar, struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status)
|
||||
{
|
||||
struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu);
|
||||
bool drop = false;
|
||||
bool drop;
|
||||
|
||||
ar->ab->soc_stats.rxdma_error[rxcb->err_code]++;
|
||||
|
||||
switch (rxcb->err_code) {
|
||||
case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
|
||||
ath11k_dp_rx_h_tkip_mic_err(ar, msdu, status);
|
||||
drop = ath11k_dp_rx_h_tkip_mic_err(ar, msdu, status);
|
||||
break;
|
||||
default:
|
||||
/* TODO: Review other rxdma error code to check if anything is
|
||||
|
|
|
|||
|
|
@ -4227,13 +4227,14 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
goto exit;
|
||||
|
||||
arg = kzalloc_obj(*arg);
|
||||
arg = kzalloc_flex(*arg, chan_list, req->n_channels);
|
||||
|
||||
if (!arg) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
arg->num_chan = req->n_channels;
|
||||
ath11k_wmi_start_scan_init(ar, arg);
|
||||
arg->vdev_id = arvif->vdev_id;
|
||||
arg->scan_id = ATH11K_SCAN_ID;
|
||||
|
|
@ -4261,38 +4262,27 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
|||
arg->scan_f_passive = 1;
|
||||
}
|
||||
|
||||
if (req->n_channels) {
|
||||
arg->num_chan = req->n_channels;
|
||||
arg->chan_list = kcalloc(arg->num_chan, sizeof(*arg->chan_list),
|
||||
GFP_KERNEL);
|
||||
for (i = 0; i < arg->num_chan; i++) {
|
||||
if (test_bit(WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL,
|
||||
ar->ab->wmi_ab.svc_map)) {
|
||||
arg->chan_list[i] =
|
||||
u32_encode_bits(req->channels[i]->center_freq,
|
||||
WMI_SCAN_CONFIG_PER_CHANNEL_MASK);
|
||||
|
||||
if (!arg->chan_list) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < arg->num_chan; i++) {
|
||||
if (test_bit(WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL,
|
||||
ar->ab->wmi_ab.svc_map)) {
|
||||
arg->chan_list[i] =
|
||||
u32_encode_bits(req->channels[i]->center_freq,
|
||||
WMI_SCAN_CONFIG_PER_CHANNEL_MASK);
|
||||
|
||||
/* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is set in scan
|
||||
* flags, then scan all PSC channels in 6 GHz band and
|
||||
* those non-PSC channels where RNR IE is found during
|
||||
* the legacy 2.4/5 GHz scan.
|
||||
* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set,
|
||||
* then all channels in 6 GHz will be scanned.
|
||||
*/
|
||||
if (req->channels[i]->band == NL80211_BAND_6GHZ &&
|
||||
req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ &&
|
||||
!cfg80211_channel_is_psc(req->channels[i]))
|
||||
arg->chan_list[i] |=
|
||||
WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND;
|
||||
} else {
|
||||
arg->chan_list[i] = req->channels[i]->center_freq;
|
||||
}
|
||||
/* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is set in scan
|
||||
* flags, then scan all PSC channels in 6 GHz band and
|
||||
* those non-PSC channels where RNR IE is found during
|
||||
* the legacy 2.4/5 GHz scan.
|
||||
* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set,
|
||||
* then all channels in 6 GHz will be scanned.
|
||||
*/
|
||||
if (req->channels[i]->band == NL80211_BAND_6GHZ &&
|
||||
req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ &&
|
||||
!cfg80211_channel_is_psc(req->channels[i]))
|
||||
arg->chan_list[i] |=
|
||||
WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND;
|
||||
} else {
|
||||
arg->chan_list[i] = req->channels[i]->center_freq;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4335,7 +4325,6 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
|||
|
||||
exit:
|
||||
if (arg) {
|
||||
kfree(arg->chan_list);
|
||||
kfree(arg->extraie.ptr);
|
||||
kfree(arg);
|
||||
}
|
||||
|
|
@ -9735,19 +9724,14 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
|
|||
|
||||
scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2;
|
||||
|
||||
arg = kzalloc_obj(*arg);
|
||||
arg = kzalloc_flex(*arg, chan_list, 1);
|
||||
if (!arg) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
ath11k_wmi_start_scan_init(ar, arg);
|
||||
|
||||
arg->num_chan = 1;
|
||||
arg->chan_list = kcalloc(arg->num_chan, sizeof(*arg->chan_list),
|
||||
GFP_KERNEL);
|
||||
if (!arg->chan_list) {
|
||||
ret = -ENOMEM;
|
||||
goto free_arg;
|
||||
}
|
||||
ath11k_wmi_start_scan_init(ar, arg);
|
||||
|
||||
arg->vdev_id = arvif->vdev_id;
|
||||
arg->scan_id = ATH11K_SCAN_ID;
|
||||
|
|
@ -9768,7 +9752,7 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
|
|||
spin_lock_bh(&ar->data_lock);
|
||||
ar->scan.state = ATH11K_SCAN_IDLE;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
goto free_chan_list;
|
||||
goto free_arg;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ);
|
||||
|
|
@ -9778,7 +9762,7 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
ath11k_warn(ar->ab, "failed to stop scan: %d\n", ret);
|
||||
ret = -ETIMEDOUT;
|
||||
goto free_chan_list;
|
||||
goto free_arg;
|
||||
}
|
||||
|
||||
ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
|
||||
|
|
@ -9786,8 +9770,6 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
|
|||
|
||||
ret = 0;
|
||||
|
||||
free_chan_list:
|
||||
kfree(arg->chan_list);
|
||||
free_arg:
|
||||
kfree(arg);
|
||||
exit:
|
||||
|
|
|
|||
|
|
@ -3423,7 +3423,6 @@ struct scan_req_params {
|
|||
u32 num_bssid;
|
||||
u32 num_ssids;
|
||||
u32 n_probes;
|
||||
u32 *chan_list;
|
||||
u32 notify_scan_events;
|
||||
struct wlan_ssid ssid[WLAN_SCAN_PARAMS_MAX_SSID];
|
||||
struct wmi_mac_addr bssid_list[WLAN_SCAN_PARAMS_MAX_BSSID];
|
||||
|
|
@ -3436,6 +3435,7 @@ struct scan_req_params {
|
|||
struct hint_bssid hint_bssid[WLAN_SCAN_MAX_HINT_BSSID];
|
||||
struct wmi_mac_addr mac_addr;
|
||||
struct wmi_mac_addr mac_mask;
|
||||
u32 chan_list[] __counted_by(num_chan);
|
||||
};
|
||||
|
||||
struct wmi_ssid_arg {
|
||||
|
|
|
|||
|
|
@ -353,6 +353,9 @@ struct ath12k_link_vif {
|
|||
u16 num_stations;
|
||||
bool is_csa_in_progress;
|
||||
struct wiphy_work bcn_tx_work;
|
||||
|
||||
bool set_wds_vdev_param;
|
||||
bool nawds_enabled;
|
||||
};
|
||||
|
||||
struct ath12k_vif {
|
||||
|
|
@ -492,6 +495,10 @@ struct ath12k_link_sta {
|
|||
/* link address similar to ieee80211_link_sta */
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
u16 tcl_metadata;
|
||||
u16 ast_hash;
|
||||
u16 ast_idx;
|
||||
|
||||
/* the following are protected by ar->data_lock */
|
||||
u32 changed; /* IEEE80211_RC_* */
|
||||
u32 bw;
|
||||
|
|
@ -527,6 +534,8 @@ struct ath12k_sta {
|
|||
u16 free_logical_link_idx_map;
|
||||
|
||||
enum ieee80211_sta_state state;
|
||||
|
||||
bool enable_4addr;
|
||||
};
|
||||
|
||||
#define ATH12K_HALF_20MHZ_BW 10
|
||||
|
|
|
|||
|
|
@ -115,13 +115,14 @@ ath12k_dp_mon_fill_rx_rate(struct ath12k_pdev_dp *dp_pdev,
|
|||
bool is_cck;
|
||||
|
||||
pkt_type = ppdu_info->preamble_type;
|
||||
rate_mcs = ppdu_info->rate;
|
||||
rate_mcs = ppdu_info->mcs;
|
||||
nss = ppdu_info->nss;
|
||||
sgi = ppdu_info->gi;
|
||||
|
||||
switch (pkt_type) {
|
||||
case RX_MSDU_START_PKT_TYPE_11A:
|
||||
case RX_MSDU_START_PKT_TYPE_11B:
|
||||
rate_mcs = ppdu_info->rate;
|
||||
is_cck = (pkt_type == RX_MSDU_START_PKT_TYPE_11B);
|
||||
if (rx_status->band < NUM_NL80211_BANDS) {
|
||||
struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
|
||||
|
|
@ -471,13 +472,10 @@ void ath12k_dp_mon_update_radiotap(struct ath12k_pdev_dp *dp_pdev,
|
|||
rxs->encoding = RX_ENC_HE;
|
||||
ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he));
|
||||
ath12k_dp_mon_rx_update_radiotap_he(ppduinfo, ptr);
|
||||
rxs->rate_idx = ppduinfo->rate;
|
||||
} else if (ppduinfo->vht_flags) {
|
||||
rxs->encoding = RX_ENC_VHT;
|
||||
rxs->rate_idx = ppduinfo->rate;
|
||||
} else if (ppduinfo->ht_flags) {
|
||||
rxs->encoding = RX_ENC_HT;
|
||||
rxs->rate_idx = ppduinfo->rate;
|
||||
} else {
|
||||
struct ath12k *ar;
|
||||
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@ struct ath12k_dp_peer *ath12k_dp_peer_find_by_peerid(struct ath12k_pdev_dp *dp_p
|
|||
RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
|
||||
"ath12k dp peer find by peerid index called without rcu lock");
|
||||
|
||||
if (!peer_id || peer_id >= ATH12K_DP_PEER_ID_INVALID)
|
||||
if (peer_id >= ATH12K_DP_PEER_ID_INVALID)
|
||||
return NULL;
|
||||
|
||||
index = ath12k_dp_peer_get_peerid_index(dp, peer_id);
|
||||
|
|
|
|||
|
|
@ -143,6 +143,8 @@ struct ath12k_dp_peer {
|
|||
struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS];
|
||||
struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
|
||||
struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
|
||||
|
||||
bool use_4addr;
|
||||
};
|
||||
|
||||
struct ath12k_dp_link_peer *
|
||||
|
|
|
|||
|
|
@ -1142,7 +1142,8 @@ 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,
|
||||
enum hal_encrypt_type enctype,
|
||||
bool decrypted,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
struct hal_rx_desc_data *rx_info,
|
||||
struct ath12k_dp_peer *peer)
|
||||
{
|
||||
enum ath12k_dp_rx_decap_type decap_type = rx_info->decap_type;
|
||||
struct ethhdr *ehdr;
|
||||
|
|
@ -1166,6 +1167,13 @@ void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu
|
|||
break;
|
||||
}
|
||||
|
||||
if (peer && !peer->use_4addr &&
|
||||
rx_info->is_from_ds && rx_info->is_to_ds) {
|
||||
ath12k_dp_rx_h_undecap_eth(dp_pdev, msdu, enctype, rx_info,
|
||||
decap_type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* PN for mcast packets will be validated in mac80211;
|
||||
* remove eth header and add 802.11 header.
|
||||
*/
|
||||
|
|
@ -1202,8 +1210,7 @@ ath12k_dp_rx_h_find_link_peer(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *ms
|
|||
|
||||
lockdep_assert_held(&dp->dp_lock);
|
||||
|
||||
if (rxcb->peer_id)
|
||||
peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
|
||||
peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
|
||||
|
||||
if (peer)
|
||||
return peer;
|
||||
|
|
|
|||
|
|
@ -190,7 +190,8 @@ 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,
|
||||
enum hal_encrypt_type enctype,
|
||||
bool decrypted,
|
||||
struct hal_rx_desc_data *rx_info);
|
||||
struct hal_rx_desc_data *rx_info,
|
||||
struct ath12k_dp_peer *peer);
|
||||
void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struct *napi,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info);
|
||||
|
|
|
|||
|
|
@ -738,7 +738,9 @@ struct hal_rx_desc_data {
|
|||
addr2_present:1,
|
||||
is_mcbc:1,
|
||||
seq_ctl_valid:1,
|
||||
fc_valid:1;
|
||||
fc_valid:1,
|
||||
is_to_ds:1,
|
||||
is_from_ds:1;
|
||||
u16 msdu_len;
|
||||
u16 peer_id;
|
||||
u16 seq_no;
|
||||
|
|
|
|||
|
|
@ -19,14 +19,28 @@
|
|||
#define TARGET_NUM_VDEVS(ab) ((ab)->profile_param->num_vdevs)
|
||||
|
||||
/* Max num of stations for Single Radio mode */
|
||||
#define TARGET_NUM_STATIONS_SINGLE(ab) ((ab)->profile_param->max_client_single)
|
||||
#define TARGET_NUM_STATIONS_SINGLE(ab) \
|
||||
({ \
|
||||
typeof(ab) _ab = (ab); \
|
||||
min_not_zero(_ab->hw_params->client.max_client_single, \
|
||||
_ab->profile_param->max_client_single); \
|
||||
})
|
||||
|
||||
/* Max num of stations for DBS */
|
||||
#define TARGET_NUM_STATIONS_DBS(ab) ((ab)->profile_param->max_client_dbs)
|
||||
#define TARGET_NUM_STATIONS_DBS(ab) \
|
||||
({ \
|
||||
typeof(ab) _ab = (ab); \
|
||||
min_not_zero(_ab->hw_params->client.max_client_dbs, \
|
||||
_ab->profile_param->max_client_dbs); \
|
||||
})
|
||||
|
||||
/* Max num of stations for DBS_SBS */
|
||||
#define TARGET_NUM_STATIONS_DBS_SBS(ab) \
|
||||
((ab)->profile_param->max_client_dbs_sbs)
|
||||
({ \
|
||||
typeof(ab) _ab = (ab); \
|
||||
min_not_zero(_ab->hw_params->client.max_client_dbs_sbs, \
|
||||
_ab->profile_param->max_client_dbs_sbs); \
|
||||
})
|
||||
|
||||
#define TARGET_NUM_STATIONS(ab, x) TARGET_NUM_STATIONS_##x(ab)
|
||||
|
||||
|
|
@ -213,6 +227,11 @@ struct ath12k_hw_params {
|
|||
|
||||
/* setup REO queue, frag etc only for primary link peer */
|
||||
bool dp_primary_link_only:1;
|
||||
struct {
|
||||
u32 max_client_single;
|
||||
u32 max_client_dbs;
|
||||
u32 max_client_dbs_sbs;
|
||||
} client;
|
||||
};
|
||||
|
||||
struct ath12k_hw_ops {
|
||||
|
|
|
|||
|
|
@ -6571,6 +6571,79 @@ static int ath12k_mac_station_disassoc(struct ath12k *ar,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_mac_sta_set_4addr(struct wiphy *wiphy, struct ath12k_sta *ahsta)
|
||||
{
|
||||
struct ath12k_dp_link_peer *peer;
|
||||
struct ath12k_link_vif *arvif;
|
||||
struct ath12k_link_sta *arsta;
|
||||
struct ath12k_vif *ahvif;
|
||||
struct ath12k_dp *dp;
|
||||
unsigned long links;
|
||||
struct ath12k *ar;
|
||||
u8 link_id;
|
||||
int ret;
|
||||
|
||||
links = ahsta->links_map;
|
||||
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
arsta = wiphy_dereference(wiphy, ahsta->link[link_id]);
|
||||
if (!arsta)
|
||||
continue;
|
||||
|
||||
arvif = arsta->arvif;
|
||||
ahvif = arvif->ahvif;
|
||||
ar = arvif->ar;
|
||||
|
||||
if (arvif->set_wds_vdev_param)
|
||||
goto skip_nawds;
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
|
||||
"setting USE_4ADDR for peer %pM\n", arsta->addr);
|
||||
|
||||
ret = ath12k_wmi_set_peer_param(ar, arsta->addr,
|
||||
arvif->vdev_id,
|
||||
WMI_PEER_USE_4ADDR,
|
||||
WMI_PEER_4ADDR_ALLOW_EAPOL_DATA_FRAME);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to set peer %pM 4addr capability: %d\n",
|
||||
arsta->addr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ahvif->dp_vif.tx_encap_type != ATH12K_HW_TXRX_ETHERNET)
|
||||
goto skip_nawds;
|
||||
|
||||
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
WMI_VDEV_PARAM_AP_ENABLE_NAWDS,
|
||||
WDS_EXT_ENABLE);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to set vdev %d nawds parameter: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
arvif->nawds_enabled = true;
|
||||
|
||||
skip_nawds:
|
||||
dp = ath12k_ab_to_dp(ar->ab);
|
||||
spin_lock_bh(&dp->dp_lock);
|
||||
peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id,
|
||||
arsta->addr);
|
||||
if (peer && peer->dp_peer) {
|
||||
peer->dp_peer->ucast_ra_only = true;
|
||||
peer->dp_peer->use_4addr = true;
|
||||
} else {
|
||||
spin_unlock_bh(&dp->dp_lock);
|
||||
ath12k_warn(ar->ab, "failed to find DP peer for %pM\n",
|
||||
arsta->addr);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&dp->dp_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
|
||||
{
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
|
|
@ -7865,6 +7938,28 @@ int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
|
|||
}
|
||||
EXPORT_SYMBOL(ath12k_mac_op_sta_set_txpwr);
|
||||
|
||||
void ath12k_mac_op_sta_set_4addr(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool enabled)
|
||||
{
|
||||
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
|
||||
|
||||
lockdep_assert_wiphy(hw->wiphy);
|
||||
|
||||
/*
|
||||
* 4-address mode disabled option is available only for station
|
||||
* interface from mac80211, and we have wds_vdev_param for station
|
||||
* interface and target will not allow to disable the wds_vdev_param
|
||||
* during run time. So, add support only for enable case, for
|
||||
* disable case station interface needs to be reconnect.
|
||||
*/
|
||||
if (enabled && !ahsta->enable_4addr) {
|
||||
if (!ath12k_mac_sta_set_4addr(hw->wiphy, ahsta))
|
||||
ahsta->enable_4addr = true;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath12k_mac_op_sta_set_4addr);
|
||||
|
||||
void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
|
|
@ -8049,16 +8144,16 @@ int ath12k_mac_op_change_sta_links(struct ieee80211_hw *hw,
|
|||
continue;
|
||||
|
||||
arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
|
||||
arsta = ath12k_mac_alloc_assign_link_sta(ah, ahsta, ahvif, link_id);
|
||||
if (!arvif || !arvif->is_created)
|
||||
continue;
|
||||
|
||||
if (!arvif || !arsta) {
|
||||
arsta = ath12k_mac_alloc_assign_link_sta(ah, ahsta, ahvif, link_id);
|
||||
if (!arsta) {
|
||||
ath12k_hw_warn(ah, "Failed to alloc/assign link sta");
|
||||
continue;
|
||||
}
|
||||
|
||||
ar = arvif->ar;
|
||||
if (!ar)
|
||||
continue;
|
||||
|
||||
ret = ath12k_mac_station_add(ar, arvif, arsta);
|
||||
if (ret) {
|
||||
|
|
@ -10020,12 +10115,14 @@ static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif)
|
|||
vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED |
|
||||
IEEE80211_OFFLOAD_DECAP_ENABLED);
|
||||
|
||||
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
|
||||
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) {
|
||||
ahvif->dp_vif.tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
|
||||
else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
|
||||
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
|
||||
} else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
|
||||
ahvif->dp_vif.tx_encap_type = ATH12K_HW_TXRX_RAW;
|
||||
else
|
||||
} else {
|
||||
ahvif->dp_vif.tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
|
||||
}
|
||||
|
||||
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param_id, ahvif->dp_vif.tx_encap_type);
|
||||
|
|
@ -10235,6 +10332,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
|
|||
struct ieee80211_hw *hw = ah->hw;
|
||||
struct ath12k_vif *ahvif = arvif->ahvif;
|
||||
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
|
||||
struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif);
|
||||
struct ath12k_wmi_vdev_create_arg vdev_arg = {};
|
||||
struct ath12k_wmi_peer_create_arg peer_param = {};
|
||||
struct ieee80211_bss_conf *link_conf = NULL;
|
||||
|
|
@ -10302,7 +10400,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
|
|||
if (ret) {
|
||||
ath12k_warn(ab, "failed to create WMI vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ar->num_created_vdevs++;
|
||||
|
|
@ -10403,6 +10501,26 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
|
|||
goto err_peer_del;
|
||||
}
|
||||
|
||||
/*
|
||||
* There could be race condition in firmware for the station
|
||||
* interface between enabling 4-address peer WMI param and
|
||||
* sending 4-address frame (NULL or EAPOL via TCL).
|
||||
* Make the station as WDS while bringup itself
|
||||
* to avoid the race condition
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
(wdev && wdev->use_4addr)) {
|
||||
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
WMI_VDEV_PARAM_WDS,
|
||||
1);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to set WDS vdev param: %d\n",
|
||||
ret);
|
||||
goto err_peer_del;
|
||||
}
|
||||
arvif->set_wds_vdev_param = true;
|
||||
}
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map) &&
|
||||
ahvif->vdev_type == WMI_VDEV_TYPE_STA &&
|
||||
ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
|
||||
|
|
@ -10449,13 +10567,13 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
|
|||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
|
||||
arvif->vdev_id, arvif->bssid);
|
||||
goto err;
|
||||
goto err_dp_peer_del;
|
||||
}
|
||||
|
||||
ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id,
|
||||
arvif->bssid);
|
||||
if (ret)
|
||||
goto err_vdev_del;
|
||||
goto err_dp_peer_del;
|
||||
|
||||
ar->num_peers--;
|
||||
}
|
||||
|
|
@ -10472,8 +10590,6 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
|
|||
|
||||
ath12k_wmi_vdev_delete(ar, arvif->vdev_id);
|
||||
ar->num_created_vdevs--;
|
||||
arvif->is_created = false;
|
||||
arvif->ar = NULL;
|
||||
ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
|
||||
ab->free_vdev_map |= 1LL << arvif->vdev_id;
|
||||
ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id);
|
||||
|
|
@ -10482,6 +10598,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
|
|||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
err:
|
||||
arvif->is_created = false;
|
||||
arvif->ar = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -11480,6 +11597,9 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (WARN_ON(!arvif))
|
||||
continue;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_MAC,
|
||||
"mac chanctx switch vdev_id %i freq %u->%u width %d->%d\n",
|
||||
arvif->vdev_id,
|
||||
|
|
@ -12271,23 +12391,85 @@ ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
|
|||
int n_vifs,
|
||||
enum ieee80211_chanctx_switch_mode mode)
|
||||
{
|
||||
struct ath12k *ar;
|
||||
struct ath12k *curr_ar, *new_ar, *group_ar;
|
||||
struct ieee80211_vif_chanctx_switch *v;
|
||||
int i, j, count = 0;
|
||||
|
||||
lockdep_assert_wiphy(hw->wiphy);
|
||||
|
||||
ar = ath12k_get_ar_by_ctx(hw, vifs->old_ctx);
|
||||
if (!ar)
|
||||
return -EINVAL;
|
||||
if (n_vifs == 0)
|
||||
return 0;
|
||||
|
||||
/* Switching channels across radio is not allowed */
|
||||
if (ar != ath12k_get_ar_by_ctx(hw, vifs->new_ctx))
|
||||
return -EINVAL;
|
||||
struct ath12k **ar_map __free(kfree) = kzalloc_objs(*ar_map, n_vifs);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
|
||||
"mac chanctx switch n_vifs %d mode %d\n",
|
||||
n_vifs, mode);
|
||||
ath12k_mac_update_vif_chan(ar, vifs, n_vifs);
|
||||
if (!ar_map)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
v = &vifs[i];
|
||||
|
||||
if (v->old_ctx->def.chan->band != v->new_ctx->def.chan->band) {
|
||||
ath12k_generic_dbg(ATH12K_DBG_MAC,
|
||||
"mac chanctx switch band change not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
curr_ar = ath12k_get_ar_by_ctx(hw, v->old_ctx);
|
||||
new_ar = ath12k_get_ar_by_ctx(hw, v->new_ctx);
|
||||
|
||||
if (!curr_ar || !new_ar) {
|
||||
ath12k_generic_dbg(ATH12K_DBG_MAC,
|
||||
"unable to determine device for the passed channel ctx\n");
|
||||
ath12k_generic_dbg(ATH12K_DBG_MAC,
|
||||
"Old freq %d MHz (device %s) to new freq %d MHz (device %s)\n",
|
||||
v->old_ctx->def.chan->center_freq,
|
||||
curr_ar ? "valid" : "invalid",
|
||||
v->new_ctx->def.chan->center_freq,
|
||||
new_ar ? "valid" : "invalid");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Switching a vif between two radios is not allowed */
|
||||
if (curr_ar != new_ar) {
|
||||
ath12k_dbg(curr_ar->ab, ATH12K_DBG_MAC,
|
||||
"mac chanctx switch to another radio not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ar_map[i] = curr_ar;
|
||||
}
|
||||
|
||||
/* Group vifs by radio (ar) and process each group independently. */
|
||||
bool *processed __free(kfree) = kzalloc_objs(*processed, n_vifs);
|
||||
|
||||
if (!processed)
|
||||
return -ENOMEM;
|
||||
|
||||
struct ieee80211_vif_chanctx_switch *group_vifs __free(kfree) =
|
||||
kzalloc_objs(*group_vifs, n_vifs);
|
||||
|
||||
if (!group_vifs)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
if (processed[i])
|
||||
continue;
|
||||
|
||||
group_ar = ar_map[i];
|
||||
|
||||
count = 0;
|
||||
for (j = 0; j < n_vifs; j++) {
|
||||
if (!processed[j] && ar_map[j] == group_ar) {
|
||||
group_vifs[count++] = vifs[j];
|
||||
processed[j] = true;
|
||||
}
|
||||
}
|
||||
|
||||
ath12k_dbg(group_ar->ab, ATH12K_DBG_MAC,
|
||||
"mac chanctx switch n_vifs %d mode %d\n",
|
||||
count, mode);
|
||||
ath12k_mac_update_vif_chan(group_ar, group_vifs, count);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath12k_mac_op_switch_vif_chanctx);
|
||||
|
|
|
|||
|
|
@ -255,6 +255,9 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
|
|||
int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void ath12k_mac_op_sta_set_4addr(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool enabled);
|
||||
void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
|
|
|
|||
|
|
@ -218,7 +218,13 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
|||
ahsta = ath12k_sta_to_ahsta(sta);
|
||||
arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
|
||||
ahsta->link[link_id]);
|
||||
|
||||
/* TODO: Split DP related field usage to DP peer structure */
|
||||
arsta->tcl_metadata = u16_encode_bits(0, HTT_TCL_META_DATA_TYPE) |
|
||||
u16_encode_bits(peer->peer_id,
|
||||
HTT_TCL_META_DATA_PEER_ID) |
|
||||
u16_encode_bits(0, HTT_TCL_META_DATA_VALID_HTT);
|
||||
arsta->ast_hash = peer->ast_hash;
|
||||
arsta->ast_idx = peer->hw_peer_id;
|
||||
peer->link_id = arsta->link_id;
|
||||
|
||||
/* Fill ML info into created peer */
|
||||
|
|
@ -249,6 +255,9 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
|||
ar->hw_link_id);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP && peer->dp_peer)
|
||||
peer->dp_peer->ucast_ra_only = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1779,8 +1779,7 @@ ath12k_wifi7_dp_mon_rx_parse_status_tlv(struct ath12k_pdev_dp *dp_pdev,
|
|||
|
||||
info[1] = __le32_to_cpu(mpdu_start->info1);
|
||||
peer_id = u32_get_bits(info[1], HAL_RX_MPDU_START_INFO1_PEERID);
|
||||
if (peer_id)
|
||||
ppdu_info->peer_id = peer_id;
|
||||
ppdu_info->peer_id = peer_id;
|
||||
|
||||
ppdu_info->mpdu_len += u32_get_bits(info[1],
|
||||
HAL_RX_MPDU_START_INFO2_MPDU_LEN);
|
||||
|
|
|
|||
|
|
@ -323,9 +323,9 @@ static void ath12k_wifi7_dp_rx_h_csum_offload(struct sk_buff *msdu,
|
|||
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
|
||||
static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
static int ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
{
|
||||
struct ath12k_skb_rxcb *rxcb;
|
||||
enum hal_encrypt_type enctype;
|
||||
|
|
@ -347,6 +347,18 @@ static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
|
|||
|
||||
peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
|
||||
if (peer) {
|
||||
/*
|
||||
* Drop the 3-address multicast packet from 4-address
|
||||
* peer To avoid receiving the duplicate multicast packet
|
||||
* Specifically from AP interface in 3-address format
|
||||
*/
|
||||
if (rxcb->is_mcbc &&
|
||||
rx_info->decap_type == DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
|
||||
if (peer->use_4addr &&
|
||||
!(rx_info->is_from_ds && rx_info->is_to_ds))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* resetting mcbc bit because mcbc packets are unicast
|
||||
* packets only for AP as STA sends unicast packets.
|
||||
*/
|
||||
|
|
@ -387,15 +399,18 @@ 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, enctype, is_decrypted, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, enctype, is_decrypted, rx_info,
|
||||
peer);
|
||||
|
||||
if (!is_decrypted || rx_info->is_mcbc)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (rx_info->decap_type != DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
|
||||
hdr = (void *)msdu->data;
|
||||
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_wifi7_dp_rx_msdu_coalesce(struct ath12k_hal *hal,
|
||||
|
|
@ -554,7 +569,9 @@ static int ath12k_wifi7_dp_rx_process_msdu(struct ath12k_pdev_dp *dp_pdev,
|
|||
}
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
ret = ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
if (ret)
|
||||
goto free_out;
|
||||
|
||||
rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
|
||||
|
||||
|
|
@ -1028,12 +1045,14 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
|
|||
skb_pull(msdu, hal_rx_desc_sz);
|
||||
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, msdu,
|
||||
rx_info)))
|
||||
rx_info))) {
|
||||
dev_kfree_skb_any(msdu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, HAL_ENCRYPT_TYPE_TKIP_MIC, true,
|
||||
rx_info);
|
||||
rx_info, NULL);
|
||||
ieee80211_rx(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1588,6 +1607,7 @@ static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
|
|||
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;
|
||||
int ret;
|
||||
|
||||
if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
|
||||
/* First buffer will be freed by the caller, so deduct it's length */
|
||||
|
|
@ -1632,7 +1652,9 @@ static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
|
|||
return -EINVAL;
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
ret = ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rxcb->tid = rx_info->tid;
|
||||
|
||||
|
|
@ -1678,7 +1700,57 @@ static bool ath12k_wifi7_dp_rx_h_tkip_mic_err(struct ath12k_pdev_dp *dp_pdev,
|
|||
RX_FLAG_DECRYPTED);
|
||||
|
||||
ath12k_dp_rx_h_undecap(dp_pdev, msdu, HAL_ENCRYPT_TYPE_TKIP_MIC, false,
|
||||
rx_info);
|
||||
rx_info, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ath12k_wifi7_dp_rx_h_unauth_wds_err(struct ath12k_pdev_dp *dp_pdev,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc_data *rx_info)
|
||||
{
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
struct ath12k_dp *dp = dp_pdev->dp;
|
||||
u32 hdr_len, hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
|
||||
u8 l3pad_bytes = rx_info->l3_pad_bytes;
|
||||
struct ath12k_dp_rx_rfc1042_hdr *llc;
|
||||
u16 msdu_len = rx_info->msdu_len;
|
||||
struct ath12k_dp_peer *peer;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int ret;
|
||||
|
||||
guard(rcu)();
|
||||
peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
|
||||
if (!peer) {
|
||||
ath12k_dbg(dp->ab, ATH12K_DBG_DATA,
|
||||
"failed to find the peer to process unauth wds err handling peer_id %d\n",
|
||||
rxcb->peer_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE)
|
||||
return true;
|
||||
|
||||
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, msdu,
|
||||
rx_info)))
|
||||
return true;
|
||||
|
||||
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
|
||||
|
||||
ret = ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_info);
|
||||
if (ret)
|
||||
return true;
|
||||
|
||||
rxcb->tid = rx_info->tid;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
||||
llc = (struct ath12k_dp_rx_rfc1042_hdr *)(msdu->data + hdr_len);
|
||||
if (llc->snap_type != cpu_to_be16(ETH_P_PAE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1693,6 +1765,9 @@ static bool ath12k_wifi7_dp_rx_h_rxdma_err(struct ath12k_pdev_dp *dp_pdev,
|
|||
dp->device_stats.rxdma_error[rxcb->err_code]++;
|
||||
|
||||
switch (rxcb->err_code) {
|
||||
case HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR:
|
||||
drop = ath12k_wifi7_dp_rx_h_unauth_wds_err(dp_pdev, msdu, rx_info);
|
||||
break;
|
||||
case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR:
|
||||
case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
|
||||
if (rx_info->err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) {
|
||||
|
|
|
|||
|
|
@ -57,10 +57,12 @@ static int ath12k_wifi7_dp_prepare_htt_metadata(struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define ATH12K_AST_HASH_MASK 0xF
|
||||
|
||||
/* TODO: Remove the export once this file is built with wifi7 ko */
|
||||
int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *arvif,
|
||||
struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
|
||||
bool is_mcast)
|
||||
struct ath12k_link_sta *arsta, struct sk_buff *skb,
|
||||
bool gsn_valid, int mcbc_gsn, bool is_mcast)
|
||||
{
|
||||
struct ath12k_dp *dp = dp_pdev->dp;
|
||||
struct ath12k_hal *hal = dp->hal;
|
||||
|
|
@ -78,6 +80,7 @@ int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *a
|
|||
struct ath12k_dp_vif *dp_vif = &ahvif->dp_vif;
|
||||
struct ath12k_dp_link_vif *dp_link_vif;
|
||||
struct dp_tx_ring *tx_ring;
|
||||
struct ethhdr *eth = NULL;
|
||||
u8 pool_id;
|
||||
u8 hal_ring_id;
|
||||
int ret;
|
||||
|
|
@ -96,6 +99,9 @@ int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *a
|
|||
!ieee80211_is_data(hdr->frame_control))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP)
|
||||
eth = (struct ethhdr *)skb->data;
|
||||
|
||||
pool_id = skb_get_queue_mapping(skb) & (ATH12K_HW_MAX_QUEUES - 1);
|
||||
|
||||
/* Let the default ring selection be based on current processor
|
||||
|
|
@ -124,6 +130,19 @@ int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *a
|
|||
|
||||
ti.bank_id = dp_link_vif->bank_id;
|
||||
ti.meta_data_flags = dp_link_vif->tcl_metadata;
|
||||
ti.bss_ast_hash = dp_link_vif->ast_hash;
|
||||
ti.bss_ast_idx = dp_link_vif->ast_idx;
|
||||
|
||||
if (eth && is_multicast_ether_addr(eth->h_dest) && arsta) {
|
||||
ti.meta_data_flags = arsta->tcl_metadata;
|
||||
ti.bss_ast_hash = arsta->ast_hash & ATH12K_AST_HASH_MASK;
|
||||
ti.bss_ast_idx = arsta->ast_idx;
|
||||
ti.lookup_override = true;
|
||||
} else if (!eth && ieee80211_has_a4(hdr->frame_control) &&
|
||||
is_multicast_ether_addr(hdr->addr3) && arsta) {
|
||||
ti.meta_data_flags = arsta->tcl_metadata;
|
||||
ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TO_FW);
|
||||
}
|
||||
|
||||
if (dp_vif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
|
||||
test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags)) {
|
||||
|
|
@ -140,7 +159,7 @@ int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *a
|
|||
msdu_ext_desc = true;
|
||||
}
|
||||
|
||||
if (gsn_valid) {
|
||||
if (gsn_valid && !ti.lookup_override) {
|
||||
/* Reset and Initialize meta_data_flags with Global Sequence
|
||||
* Number (GSN) info.
|
||||
*/
|
||||
|
|
@ -148,6 +167,14 @@ int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *a
|
|||
u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM,
|
||||
HTT_TCL_META_DATA_TYPE) |
|
||||
u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM);
|
||||
|
||||
/*
|
||||
* Since NAWDS enabled for this vdev firmware expects
|
||||
* this flag to be set for sending 3-address multicast frame.
|
||||
*/
|
||||
ti.meta_data_flags |=
|
||||
u32_encode_bits(arvif->nawds_enabled,
|
||||
HTT_TCL_META_DATA_GLOBAL_SEQ_HOST_INSPECTED);
|
||||
}
|
||||
|
||||
ti.encap_type = ath12k_dp_tx_get_encap_type(ab, skb);
|
||||
|
|
@ -158,11 +185,13 @@ int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *a
|
|||
ti.lmac_id = dp_link_vif->lmac_id;
|
||||
|
||||
ti.vdev_id = dp_link_vif->vdev_id;
|
||||
if (gsn_valid)
|
||||
ti.vdev_id += HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID;
|
||||
|
||||
ti.bss_ast_hash = dp_link_vif->ast_hash;
|
||||
ti.bss_ast_idx = dp_link_vif->ast_idx;
|
||||
if (gsn_valid && !ti.lookup_override)
|
||||
ti.vdev_id += HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID;
|
||||
else if (arvif->nawds_enabled && is_mcast && !ti.lookup_override)
|
||||
ti.meta_data_flags |=
|
||||
u32_encode_bits(1, HTT_TCL_META_DATA_HOST_INSPECTED_MISSION);
|
||||
|
||||
ti.dscp_tid_tbl_idx = 0;
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL &&
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
#define ATH12K_DP_TX_WIFI7_H
|
||||
|
||||
int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *arvif,
|
||||
struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
|
||||
bool is_mcast);
|
||||
struct ath12k_link_sta *arsta, struct sk_buff *skb,
|
||||
bool gsn_valid, int mcbc_gsn, bool is_mcast);
|
||||
void ath12k_wifi7_dp_tx_completion_handler(struct ath12k_dp *dp, int ring_id);
|
||||
u32 ath12k_wifi7_dp_tx_get_vdev_bank_config(struct ath12k_base *ab,
|
||||
struct ath12k_link_vif *arvif);
|
||||
|
|
|
|||
|
|
@ -184,6 +184,20 @@ static u8 ath12k_hal_rx_desc_get_l3_pad_bytes_qcc2072(struct hal_rx_desc *desc)
|
|||
RX_MSDU_END_INFO5_L3_HDR_PADDING);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_from_ds_qcc2072(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcc2072.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_FROM_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_to_ds_qcc2072(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcc2072.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_TO_DS);
|
||||
}
|
||||
|
||||
static u32 ath12k_hal_rx_desc_get_mpdu_start_tag_qcc2072(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcc2072.mpdu_start_tag,
|
||||
|
|
@ -397,6 +411,8 @@ static void ath12k_hal_extract_rx_desc_data_qcc2072(struct hal_rx_desc_data *rx_
|
|||
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcc2072(rx_desc);
|
||||
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_qcc2072(ldesc);
|
||||
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_qcc2072(rx_desc);
|
||||
rx_desc_data->is_from_ds = ath12k_wifi7_hal_rx_h_from_ds_qcc2072(rx_desc);
|
||||
rx_desc_data->is_to_ds = ath12k_wifi7_hal_rx_h_to_ds_qcc2072(rx_desc);
|
||||
rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_qcc2072(rx_desc);
|
||||
rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_qcc2072(rx_desc);
|
||||
rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_qcc2072(rx_desc);
|
||||
|
|
|
|||
|
|
@ -699,6 +699,20 @@ u8 ath12k_hal_rx_desc_get_mpdu_tid_qcn9274(struct hal_rx_desc *desc)
|
|||
RX_MSDU_END_INFO5_TID);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_from_ds_qcn9274(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_FROM_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_to_ds_qcn9274(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_TO_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
u16 ath12k_hal_rx_desc_get_mpdu_peer_id_qcn9274(struct hal_rx_desc *desc)
|
||||
{
|
||||
|
|
@ -914,6 +928,8 @@ void ath12k_hal_extract_rx_desc_data_qcn9274(struct hal_rx_desc_data *rx_desc_da
|
|||
rx_desc_data->seq_ctl_valid =
|
||||
ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_qcn9274(rx_desc);
|
||||
rx_desc_data->fc_valid = ath12k_hal_rx_desc_get_mpdu_fc_valid_qcn9274(rx_desc);
|
||||
rx_desc_data->is_from_ds = ath12k_wifi7_hal_rx_h_from_ds_qcn9274(rx_desc);
|
||||
rx_desc_data->is_to_ds = ath12k_wifi7_hal_rx_h_to_ds_qcn9274(rx_desc);
|
||||
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcn9274(rx_desc);
|
||||
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_qcn9274(ldesc);
|
||||
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_qcn9274(rx_desc);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,9 @@ void ath12k_wifi7_hal_tx_cmd_desc_setup(struct ath12k_base *ab,
|
|||
le32_encode_bits(ti->lmac_id, HAL_TCL_DATA_CMD_INFO3_PMAC_ID) |
|
||||
le32_encode_bits(ti->vdev_id, HAL_TCL_DATA_CMD_INFO3_VDEV_ID);
|
||||
|
||||
tcl_cmd->info4 = le32_encode_bits(ti->bss_ast_idx,
|
||||
tcl_cmd->info4 = le32_encode_bits(ti->lookup_override,
|
||||
HAL_TCL_DATA_CMD_INFO4_IDX_LOOKUP_OVERRIDE) |
|
||||
le32_encode_bits(ti->bss_ast_idx,
|
||||
HAL_TCL_DATA_CMD_INFO4_SEARCH_INDEX) |
|
||||
le32_encode_bits(ti->bss_ast_hash,
|
||||
HAL_TCL_DATA_CMD_INFO4_CACHE_SET_NUM);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ struct hal_tx_info {
|
|||
u8 dscp_tid_tbl_idx;
|
||||
bool enable_mesh;
|
||||
int bank_id;
|
||||
bool lookup_override;
|
||||
};
|
||||
|
||||
/* TODO: Check if the actual desc macros can be used instead */
|
||||
|
|
|
|||
|
|
@ -280,6 +280,20 @@ u8 ath12k_hal_rx_desc_get_l3_pad_bytes_wcn7850(struct hal_rx_desc *desc)
|
|||
RX_MSDU_END_INFO5_L3_HDR_PADDING);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_from_ds_wcn7850(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.wcn7850.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_FROM_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath12k_wifi7_hal_rx_h_to_ds_wcn7850(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.wcn7850.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_TO_DS);
|
||||
}
|
||||
|
||||
static inline
|
||||
bool ath12k_hal_rx_desc_encrypt_valid_wcn7850(struct hal_rx_desc *desc)
|
||||
{
|
||||
|
|
@ -599,6 +613,8 @@ void ath12k_hal_extract_rx_desc_data_wcn7850(struct hal_rx_desc_data *rx_desc_da
|
|||
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_wcn7850(rx_desc);
|
||||
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_wcn7850(ldesc);
|
||||
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_wcn7850(rx_desc);
|
||||
rx_desc_data->is_from_ds = ath12k_wifi7_hal_rx_h_from_ds_wcn7850(rx_desc);
|
||||
rx_desc_data->is_to_ds = ath12k_wifi7_hal_rx_h_to_ds_wcn7850(rx_desc);
|
||||
rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_wcn7850(rx_desc);
|
||||
rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_wcn7850(rx_desc);
|
||||
rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_wcn7850(rx_desc);
|
||||
|
|
|
|||
|
|
@ -434,6 +434,11 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
|||
.current_cc_support = false,
|
||||
|
||||
.dp_primary_link_only = true,
|
||||
.client = {
|
||||
.max_client_single = 512,
|
||||
.max_client_dbs = 128,
|
||||
.max_client_dbs_sbs = 128,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "wcn7850 hw2.0",
|
||||
|
|
@ -520,6 +525,11 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
|||
.current_cc_support = true,
|
||||
|
||||
.dp_primary_link_only = false,
|
||||
.client = {
|
||||
.max_client_single = 512,
|
||||
.max_client_dbs = 128,
|
||||
.max_client_dbs_sbs = 128,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "qcn9274 hw2.0",
|
||||
|
|
@ -602,6 +612,11 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
|||
.current_cc_support = false,
|
||||
|
||||
.dp_primary_link_only = true,
|
||||
.client = {
|
||||
.max_client_single = 512,
|
||||
.max_client_dbs = 128,
|
||||
.max_client_dbs_sbs = 128,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "ipq5332 hw1.0",
|
||||
|
|
@ -677,6 +692,11 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
|||
.bdf_addr_offset = 0xC00000,
|
||||
|
||||
.dp_primary_link_only = true,
|
||||
.client = {
|
||||
.max_client_single = 256,
|
||||
.max_client_dbs = 128,
|
||||
.max_client_dbs_sbs = 128,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "qcc2072 hw1.0",
|
||||
|
|
@ -764,6 +784,11 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
|||
.current_cc_support = true,
|
||||
|
||||
.dp_primary_link_only = false,
|
||||
.client = {
|
||||
.max_client_single = 512,
|
||||
.max_client_dbs = 128,
|
||||
.max_client_dbs_sbs = 128,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "ipq5424 hw1.0",
|
||||
|
|
@ -843,6 +868,11 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
|
|||
.current_cc_support = false,
|
||||
|
||||
.dp_primary_link_only = true,
|
||||
.client = {
|
||||
.max_client_single = 512,
|
||||
.max_client_dbs = 128,
|
||||
.max_client_dbs_sbs = 128,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -859,7 +889,9 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
|||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
struct ieee80211_sta *sta = control->sta;
|
||||
struct ath12k_link_sta *arsta = NULL;
|
||||
struct ath12k_link_vif *tmp_arvif;
|
||||
struct ath12k_sta *ahsta = NULL;
|
||||
u32 info_flags = info->flags;
|
||||
struct sk_buff *msdu_copied;
|
||||
struct ath12k *ar, *tmp_ar;
|
||||
|
|
@ -941,6 +973,12 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
|||
if (!(info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
|
||||
is_mcast = is_multicast_ether_addr(hdr->addr1);
|
||||
|
||||
if (sta) {
|
||||
ahsta = ath12k_sta_to_ahsta(control->sta);
|
||||
if (ahsta && ahsta->enable_4addr)
|
||||
arsta = rcu_dereference(ahsta->link[link_id]);
|
||||
}
|
||||
|
||||
/* This is case only for P2P_GO */
|
||||
if (vif->type == NL80211_IFTYPE_AP && vif->p2p)
|
||||
ath12k_mac_add_p2p_noa_ie(ar, vif, skb, is_prb_rsp);
|
||||
|
|
@ -961,7 +999,7 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
|||
if (!vif->valid_links || !is_mcast || is_dvlan ||
|
||||
(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) ||
|
||||
test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags)) {
|
||||
ret = ath12k_wifi7_dp_tx(dp_pdev, arvif, skb, false, 0, is_mcast);
|
||||
ret = ath12k_wifi7_dp_tx(dp_pdev, arvif, arsta, skb, false, 0, is_mcast);
|
||||
if (unlikely(ret)) {
|
||||
ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret);
|
||||
ieee80211_free_txskb(ar->ah->hw, skb);
|
||||
|
|
@ -999,6 +1037,11 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
|||
skb_cb->vif = vif;
|
||||
skb_cb->ar = tmp_ar;
|
||||
|
||||
if (ahsta && ahsta->enable_4addr)
|
||||
arsta = rcu_dereference(ahsta->link[link_id]);
|
||||
else
|
||||
arsta = NULL;
|
||||
|
||||
/* For open mode, skip peer find logic */
|
||||
if (unlikely(!ahvif->dp_vif.key_cipher))
|
||||
goto skip_peer_find;
|
||||
|
|
@ -1030,7 +1073,7 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
|
|||
spin_unlock_bh(&tmp_dp->dp_lock);
|
||||
|
||||
skip_peer_find:
|
||||
ret = ath12k_wifi7_dp_tx(tmp_dp_pdev, tmp_arvif,
|
||||
ret = ath12k_wifi7_dp_tx(tmp_dp_pdev, tmp_arvif, arsta,
|
||||
msdu_copied, true, mcbc_gsn, is_mcast);
|
||||
if (unlikely(ret)) {
|
||||
if (ret == -ENOMEM) {
|
||||
|
|
@ -1075,6 +1118,7 @@ static const struct ieee80211_ops ath12k_ops_wifi7 = {
|
|||
.sta_state = ath12k_mac_op_sta_state,
|
||||
.sta_set_txpwr = ath12k_mac_op_sta_set_txpwr,
|
||||
.link_sta_rc_update = ath12k_mac_op_link_sta_rc_update,
|
||||
.sta_set_4addr = ath12k_mac_op_sta_set_4addr,
|
||||
.conf_tx = ath12k_mac_op_conf_tx,
|
||||
.set_antenna = ath12k_mac_op_set_antenna,
|
||||
.get_antenna = ath12k_mac_op_get_antenna,
|
||||
|
|
|
|||
|
|
@ -4192,7 +4192,12 @@ ath12k_wmi_copy_resource_config(struct ath12k_base *ab,
|
|||
cpu_to_le32(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT);
|
||||
wmi_cfg->ema_max_vap_cnt = cpu_to_le32(tg_cfg->ema_max_vap_cnt);
|
||||
wmi_cfg->ema_max_profile_period = cpu_to_le32(tg_cfg->ema_max_profile_period);
|
||||
wmi_cfg->flags2 |= cpu_to_le32(WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET);
|
||||
wmi_cfg->flags2 |= cpu_to_le32(WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET |
|
||||
WMI_RSRC_CFG_FLAGS2_FW_AST_INDICATION_DISABLE);
|
||||
|
||||
if (tg_cfg->is_wds_null_frame_supported)
|
||||
wmi_cfg->flags2 |=
|
||||
cpu_to_le32(WMI_RSRC_CFG_FLAGS2_WDS_NULL_FRAME_SUPPORT);
|
||||
}
|
||||
|
||||
static int ath12k_init_cmd_send(struct ath12k_wmi_pdev *wmi,
|
||||
|
|
@ -4402,6 +4407,9 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab)
|
|||
ab->wmi_ab.svc_map))
|
||||
arg.res_cfg.is_reg_cc_ext_event_supported = true;
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_WDS_NULL_FRAME_SUPPORT, ab->wmi_ab.svc_map))
|
||||
arg.res_cfg.is_wds_null_frame_supported = true;
|
||||
|
||||
ab->hw_params->wmi_init(ab, &arg.res_cfg);
|
||||
ab->wow.wmi_conf_rx_decap_mode = arg.res_cfg.rx_decap_mode;
|
||||
|
||||
|
|
@ -7223,7 +7231,11 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
struct ath12k_wmi_mgmt_rx_arg rx_ev = {};
|
||||
struct ath12k *ar;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_sta *pubsta = NULL;
|
||||
struct ath12k_dp_link_peer *peer;
|
||||
struct ieee80211_hdr *hdr;
|
||||
bool is_4addr_null_pkt;
|
||||
struct ath12k_dp *dp;
|
||||
u16 fc;
|
||||
struct ieee80211_supported_band *sband;
|
||||
s32 noise_floor;
|
||||
|
|
@ -7298,6 +7310,38 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_control);
|
||||
|
||||
is_4addr_null_pkt = (ieee80211_is_nullfunc(hdr->frame_control) ||
|
||||
ieee80211_is_qos_nullfunc(hdr->frame_control)) &&
|
||||
ieee80211_has_a4(hdr->frame_control);
|
||||
|
||||
/*
|
||||
* Add check to drop frames other than 4-address NULL frame. Since
|
||||
* firmware sends all NULL frames in this path (3-address and 4-address)
|
||||
*/
|
||||
if (ieee80211_is_data(hdr->frame_control) && !is_4addr_null_pkt) {
|
||||
dev_kfree_skb(skb);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (is_4addr_null_pkt) {
|
||||
dp = ath12k_ab_to_dp(ar->ab);
|
||||
spin_lock_bh(&dp->dp_lock);
|
||||
peer = ath12k_dp_link_peer_find_by_pdev_and_addr(dp, ar->pdev_idx,
|
||||
hdr->addr2);
|
||||
if (!peer) {
|
||||
spin_unlock_bh(&dp->dp_lock);
|
||||
dev_kfree_skb(skb);
|
||||
goto exit;
|
||||
}
|
||||
pubsta = peer->sta;
|
||||
if (pubsta && pubsta->valid_links) {
|
||||
status->link_valid = 1;
|
||||
status->link_id = peer->link_id;
|
||||
}
|
||||
spin_unlock_bh(&dp->dp_lock);
|
||||
goto send_rx;
|
||||
}
|
||||
|
||||
/* Firmware is guaranteed to report all essential management frames via
|
||||
* WMI while it can deliver some extra via HTT. Since there can be
|
||||
* duplicates split the reporting wrt monitor/sniffing.
|
||||
|
|
@ -7321,6 +7365,7 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
if (ieee80211_is_beacon(hdr->frame_control))
|
||||
ath12k_mac_handle_beacon(ar, skb);
|
||||
|
||||
send_rx:
|
||||
ath12k_dbg(ab, ATH12K_DBG_MGMT,
|
||||
"event mgmt rx skb %p len %d ftype %02x stype %02x\n",
|
||||
skb, skb->len,
|
||||
|
|
|
|||
|
|
@ -2278,6 +2278,7 @@ enum wmi_tlv_service {
|
|||
|
||||
WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT = 365,
|
||||
WMI_TLV_SERVICE_THERM_THROT_POUT_REDUCTION = 410,
|
||||
WMI_TLV_SERVICE_WDS_NULL_FRAME_SUPPORT = 421,
|
||||
WMI_TLV_SERVICE_IS_TARGET_IPA = 425,
|
||||
WMI_TLV_SERVICE_THERM_THROT_TX_CHAIN_MASK = 426,
|
||||
WMI_TLV_SERVICE_THERM_THROT_5_LEVELS = 429,
|
||||
|
|
@ -2334,6 +2335,19 @@ enum wmi_preamble {
|
|||
WMI_VDEV_PREAMBLE_SHORT = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* This will be used to set for WMI_VDEV_PARAM_AP_ENABLE_NAWDS
|
||||
* whenever 4addr station connects in wds offload case.
|
||||
* This is for enabling multicast to unicast conversion support in
|
||||
* firmware
|
||||
*/
|
||||
#define WDS_EXT_ENABLE 1
|
||||
|
||||
enum wmi_peer_4addr_allow_frame {
|
||||
WMI_PEER_4ADDR_ALLOW_DATA_FRAME = 1,
|
||||
WMI_PEER_4ADDR_ALLOW_EAPOL_DATA_FRAME = 2,
|
||||
};
|
||||
|
||||
enum wmi_peer_smps_state {
|
||||
WMI_PEER_SMPS_PS_NONE = 0,
|
||||
WMI_PEER_SMPS_STATIC = 1,
|
||||
|
|
@ -2498,6 +2512,7 @@ struct ath12k_wmi_resource_config_arg {
|
|||
u32 ema_max_vap_cnt;
|
||||
u32 ema_max_profile_period;
|
||||
bool is_reg_cc_ext_event_supported;
|
||||
bool is_wds_null_frame_supported;
|
||||
};
|
||||
|
||||
struct ath12k_wmi_init_cmd_arg {
|
||||
|
|
@ -2554,6 +2569,8 @@ struct wmi_init_cmd {
|
|||
#define WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION GENMASK(5, 4)
|
||||
#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
|
||||
#define WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET BIT(9)
|
||||
#define WMI_RSRC_CFG_FLAGS2_FW_AST_INDICATION_DISABLE BIT(18)
|
||||
#define WMI_RSRC_CFG_FLAGS2_WDS_NULL_FRAME_SUPPORT BIT(22)
|
||||
#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18)
|
||||
|
||||
struct ath12k_wmi_resource_config_params {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user