mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-05 01:32:47 -04:00
wifi: ath11k: MBSSID beacon support
- Split ath11k_mac_setup_bcn_tmpl() to move the beacon retrieval and WMI command to a new function, ath11k_mac_setup_bcn_tmpl_legacy(). In the original function add checks to use the transmitting interface when MBSSID is enabled. - Set rsnie_present and wpaie_present fields for the non-transmitting interfaces when MBSSID is enabled. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com> Co-developed-by: John Crispin <john@phrozen.org> Signed-off-by: John Crispin <john@phrozen.org> Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> Link: https://lore.kernel.org/r/20230405221648.17950-7-quic_alokad@quicinc.com
This commit is contained in:
@@ -1351,6 +1351,84 @@ static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif,
|
||||
bool tx_arvif_rsnie_present,
|
||||
const u8 *profile, u8 profile_len)
|
||||
{
|
||||
if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) {
|
||||
arvif->rsnie_present = true;
|
||||
} else if (tx_arvif_rsnie_present) {
|
||||
int i;
|
||||
u8 nie_len;
|
||||
const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE,
|
||||
profile, profile_len);
|
||||
if (!nie)
|
||||
return;
|
||||
|
||||
nie_len = nie[1];
|
||||
nie += 2;
|
||||
for (i = 0; i < nie_len; i++) {
|
||||
if (nie[i] == WLAN_EID_RSN) {
|
||||
arvif->rsnie_present = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif,
|
||||
struct ath11k_vif *arvif,
|
||||
struct sk_buff *bcn)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
const u8 *ies, *profile, *next_profile;
|
||||
int ies_len;
|
||||
|
||||
ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
|
||||
mgmt = (struct ieee80211_mgmt *)bcn->data;
|
||||
ies += sizeof(mgmt->u.beacon);
|
||||
ies_len = skb_tail_pointer(bcn) - ies;
|
||||
|
||||
ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len);
|
||||
arvif->rsnie_present = tx_arvif->rsnie_present;
|
||||
|
||||
while (ies) {
|
||||
u8 mbssid_len;
|
||||
|
||||
ies_len -= (2 + ies[1]);
|
||||
mbssid_len = ies[1] - 1;
|
||||
profile = &ies[3];
|
||||
|
||||
while (mbssid_len) {
|
||||
u8 profile_len;
|
||||
|
||||
profile_len = profile[1];
|
||||
next_profile = profile + (2 + profile_len);
|
||||
mbssid_len -= (2 + profile_len);
|
||||
|
||||
profile += 2;
|
||||
profile_len -= (2 + profile[1]);
|
||||
profile += (2 + profile[1]); /* nontx capabilities */
|
||||
profile_len -= (2 + profile[1]);
|
||||
profile += (2 + profile[1]); /* SSID */
|
||||
if (profile[2] == arvif->vif->bss_conf.bssid_index) {
|
||||
profile_len -= 5;
|
||||
profile = profile + 5;
|
||||
ath11k_mac_setup_nontx_vif_rsnie(arvif,
|
||||
tx_arvif->rsnie_present,
|
||||
profile,
|
||||
profile_len);
|
||||
return true;
|
||||
}
|
||||
profile = next_profile;
|
||||
}
|
||||
ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile,
|
||||
ies_len);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
|
||||
struct sk_buff *bcn)
|
||||
{
|
||||
@@ -1374,18 +1452,26 @@ static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
|
||||
arvif->wpaie_present = false;
|
||||
}
|
||||
|
||||
static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
||||
static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_vif *tx_arvif = arvif;
|
||||
struct ieee80211_hw *hw = ar->hw;
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
struct ieee80211_mutable_offsets offs = {};
|
||||
struct sk_buff *bcn;
|
||||
int ret;
|
||||
|
||||
if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
|
||||
return 0;
|
||||
if (arvif->vif->mbssid_tx_vif) {
|
||||
tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
|
||||
if (tx_arvif != arvif) {
|
||||
ar = tx_arvif->ar;
|
||||
ab = ar->ab;
|
||||
hw = ar->hw;
|
||||
vif = tx_arvif->vif;
|
||||
}
|
||||
}
|
||||
|
||||
bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
|
||||
if (!bcn) {
|
||||
@@ -1393,9 +1479,12 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ath11k_mac_set_vif_params(arvif, bcn);
|
||||
ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
|
||||
if (tx_arvif == arvif)
|
||||
ath11k_mac_set_vif_params(tx_arvif, bcn);
|
||||
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);
|
||||
kfree_skb(bcn);
|
||||
|
||||
if (ret)
|
||||
@@ -1405,6 +1494,23 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
|
||||
if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
|
||||
return 0;
|
||||
|
||||
/* Target does not expect beacon templates for the already up
|
||||
* non-transmitting interfaces, and results in a crash if sent.
|
||||
*/
|
||||
if (vif->mbssid_tx_vif &&
|
||||
arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up)
|
||||
return 0;
|
||||
|
||||
return ath11k_mac_setup_bcn_tmpl_mbssid(arvif);
|
||||
}
|
||||
|
||||
void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
|
||||
@@ -1737,6 +1737,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
|
||||
}
|
||||
|
||||
cmd->buf_len = bcn->len;
|
||||
cmd->mbssid_ie_offset = offs->mbssid_off;
|
||||
|
||||
ptr = skb->data + sizeof(*cmd);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user