mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
wifi: ath12k: add MBSSID beacon support
- A single beacon template is used for one multiple BSSID group as only one interface from group transmits the beacons. But firmware requires the host to send this template each time a nontransmitted interface is brought up. Hence, modify existing logic to retrieve the template from vif context of the transmitting interface. Also, firmware crashes if host sends a template for a nontransmitted interface which is already up, add a check to avoid this. - Set rsnie_present and wpaie_present fields for nontransmitted VAPs. - Send offset to the multiple BSSID element in the beacon template firmware. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com> Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> Link: https://msgid.link/20240508202912.11902-8-quic_alokad@quicinc.com
This commit is contained in:
@@ -1299,11 +1299,14 @@ static int ath12k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath12k_mac_set_arvif_ies(struct ath12k_vif *arvif, struct sk_buff *bcn)
|
static void ath12k_mac_set_arvif_ies(struct ath12k_vif *arvif, struct sk_buff *bcn,
|
||||||
|
u8 bssid_index, bool *nontx_profile_found)
|
||||||
{
|
{
|
||||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)bcn->data;
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)bcn->data;
|
||||||
|
const struct element *elem, *nontx, *index, *nie;
|
||||||
const u8 *start, *tail;
|
const u8 *start, *tail;
|
||||||
u16 rem_len;
|
u16 rem_len;
|
||||||
|
u8 i;
|
||||||
|
|
||||||
start = bcn->data + ieee80211_get_hdrlen_from_skb(bcn) + sizeof(mgmt->u.beacon);
|
start = bcn->data + ieee80211_get_hdrlen_from_skb(bcn) + sizeof(mgmt->u.beacon);
|
||||||
tail = skb_tail_pointer(bcn);
|
tail = skb_tail_pointer(bcn);
|
||||||
@@ -1317,28 +1320,114 @@ static void ath12k_mac_set_arvif_ies(struct ath12k_vif *arvif, struct sk_buff *b
|
|||||||
if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA,
|
if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA,
|
||||||
start, rem_len))
|
start, rem_len))
|
||||||
arvif->wpaie_present = true;
|
arvif->wpaie_present = true;
|
||||||
|
|
||||||
|
/* Return from here for the transmitted profile */
|
||||||
|
if (!bssid_index)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Initial rsnie_present for the nontransmitted profile is set to be same as that
|
||||||
|
* of the transmitted profile. It will be changed if security configurations are
|
||||||
|
* different.
|
||||||
|
*/
|
||||||
|
*nontx_profile_found = false;
|
||||||
|
for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, rem_len) {
|
||||||
|
/* Fixed minimum MBSSID element length with at least one
|
||||||
|
* nontransmitted BSSID profile is 12 bytes as given below;
|
||||||
|
* 1 (max BSSID indicator) +
|
||||||
|
* 2 (Nontransmitted BSSID profile: Subelement ID + length) +
|
||||||
|
* 4 (Nontransmitted BSSID Capabilities: tag + length + info)
|
||||||
|
* 2 (Nontransmitted BSSID SSID: tag + length)
|
||||||
|
* 3 (Nontransmitted BSSID Index: tag + length + BSSID index
|
||||||
|
*/
|
||||||
|
if (elem->datalen < 12 || elem->data[0] < 1)
|
||||||
|
continue; /* Max BSSID indicator must be >=1 */
|
||||||
|
|
||||||
|
for_each_element(nontx, elem->data + 1, elem->datalen - 1) {
|
||||||
|
start = nontx->data;
|
||||||
|
|
||||||
|
if (nontx->id != 0 || nontx->datalen < 4)
|
||||||
|
continue; /* Invalid nontransmitted profile */
|
||||||
|
|
||||||
|
if (nontx->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
|
||||||
|
nontx->data[1] != 2) {
|
||||||
|
continue; /* Missing nontransmitted BSS capabilities */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nontx->data[4] != WLAN_EID_SSID)
|
||||||
|
continue; /* Missing SSID for nontransmitted BSS */
|
||||||
|
|
||||||
|
index = cfg80211_find_elem(WLAN_EID_MULTI_BSSID_IDX,
|
||||||
|
start, nontx->datalen);
|
||||||
|
if (!index || index->datalen < 1 || index->data[0] == 0)
|
||||||
|
continue; /* Invalid MBSSID Index element */
|
||||||
|
|
||||||
|
if (index->data[0] == bssid_index) {
|
||||||
|
*nontx_profile_found = true;
|
||||||
|
if (cfg80211_find_ie(WLAN_EID_RSN,
|
||||||
|
nontx->data,
|
||||||
|
nontx->datalen)) {
|
||||||
|
arvif->rsnie_present = true;
|
||||||
|
return;
|
||||||
|
} else if (!arvif->rsnie_present) {
|
||||||
|
return; /* Both tx and nontx BSS are open */
|
||||||
|
}
|
||||||
|
|
||||||
|
nie = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
|
||||||
|
nontx->data,
|
||||||
|
nontx->datalen);
|
||||||
|
if (!nie || nie->datalen < 2)
|
||||||
|
return; /* Invalid non-inheritance element */
|
||||||
|
|
||||||
|
for (i = 1; i < nie->datalen - 1; i++) {
|
||||||
|
if (nie->data[i] == WLAN_EID_RSN) {
|
||||||
|
arvif->rsnie_present = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
|
static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
|
||||||
{
|
{
|
||||||
|
struct ath12k_vif *tx_arvif = arvif;
|
||||||
struct ath12k *ar = arvif->ar;
|
struct ath12k *ar = arvif->ar;
|
||||||
struct ath12k_base *ab = ar->ab;
|
struct ath12k_base *ab = ar->ab;
|
||||||
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
|
|
||||||
struct ieee80211_vif *vif = arvif->vif;
|
struct ieee80211_vif *vif = arvif->vif;
|
||||||
struct ieee80211_mutable_offsets offs = {};
|
struct ieee80211_mutable_offsets offs = {};
|
||||||
|
bool nontx_profile_found = false;
|
||||||
struct sk_buff *bcn;
|
struct sk_buff *bcn;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
|
if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
|
if (vif->mbssid_tx_vif) {
|
||||||
|
tx_arvif = ath12k_vif_to_arvif(vif->mbssid_tx_vif);
|
||||||
|
if (tx_arvif != arvif && arvif->is_up)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bcn = ieee80211_beacon_get_template(ath12k_ar_to_hw(tx_arvif->ar), tx_arvif->vif,
|
||||||
|
&offs, 0);
|
||||||
if (!bcn) {
|
if (!bcn) {
|
||||||
ath12k_warn(ab, "failed to get beacon template from mac80211\n");
|
ath12k_warn(ab, "failed to get beacon template from mac80211\n");
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ath12k_mac_set_arvif_ies(arvif, bcn);
|
if (tx_arvif == arvif) {
|
||||||
|
ath12k_mac_set_arvif_ies(arvif, bcn, 0, NULL);
|
||||||
|
} else {
|
||||||
|
ath12k_mac_set_arvif_ies(arvif, bcn,
|
||||||
|
arvif->vif->bss_conf.bssid_index,
|
||||||
|
&nontx_profile_found);
|
||||||
|
if (!nontx_profile_found)
|
||||||
|
ath12k_warn(ab,
|
||||||
|
"nontransmitted profile not found in beacon template\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (arvif->vif->type == NL80211_IFTYPE_AP && arvif->vif->p2p) {
|
if (arvif->vif->type == NL80211_IFTYPE_AP && arvif->vif->p2p) {
|
||||||
ret = ath12k_mac_setup_bcn_p2p_ie(arvif, bcn);
|
ret = ath12k_mac_setup_bcn_p2p_ie(arvif, bcn);
|
||||||
|
|||||||
@@ -1813,6 +1813,7 @@ int ath12k_wmi_bcn_tmpl(struct ath12k *ar, u32 vdev_id,
|
|||||||
cmd->csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[0]);
|
cmd->csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[0]);
|
||||||
cmd->ext_csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[1]);
|
cmd->ext_csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[1]);
|
||||||
cmd->buf_len = cpu_to_le32(bcn->len);
|
cmd->buf_len = cpu_to_le32(bcn->len);
|
||||||
|
cmd->mbssid_ie_offset = cpu_to_le32(offs->mbssid_off);
|
||||||
|
|
||||||
ptr = skb->data + sizeof(*cmd);
|
ptr = skb->data + sizeof(*cmd);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user