diff mbox series

[2/2] wifi: ath11k: reports address list if chip supports 2 stations

Message ID 20230714023801.2621802-3-quic_cjhuang@quicinc.com (mailing list archive)
State Accepted
Commit 24395ec117076216c78d0874d9d44f62ba1f9747
Delegated to: Kalle Valo
Headers show
Series wifi: ath11k: support 2 station interfaces | expand

Commit Message

Carl Huang July 14, 2023, 2:38 a.m. UTC
Report address list to mac80211 layer so user doesn't need to specify
address when an interface is added because the address can be allocated
from the list by mac80211.

The derived addresses have LAA(Local Administered Address) bit set, and
only the first byte is changed. Take the 00:03:7f:xx:xx:xx as example to
derive:
addresses[0] is unchanged, it's siill 00:03:7f:xx:xx:xx,
addresses[1] is 02:03:7f:xx:xx:xx,
addresses[2] is 12:03:7f:xx:xx:xx,
addresses[3] is 22:03:7f:xx:xx:xx,
addresses[4] is 32:03:7f:xx:xx:xx.
However as only 3 addresses are reported now, so addresses[3] and addresses[4]
aren't actually derived.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3

Signed-off-by: Carl Huang <quic_cjhuang@quicinc.com>
---
 drivers/net/wireless/ath/ath11k/mac.c | 30 +++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 3a9494bc944c..f3cc6f140c8a 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -9268,6 +9268,33 @@  static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
 	return 0;
 }
 
+static void ath11k_mac_setup_mac_address_list(struct ath11k *ar)
+{
+	struct mac_address *addresses;
+	u16 n_addresses;
+	int i;
+
+	if (!ar->ab->hw_params.support_dual_stations)
+		return;
+
+	n_addresses = ar->ab->hw_params.num_vdevs;
+	addresses = kcalloc(n_addresses, sizeof(*addresses), GFP_KERNEL);
+	if (!addresses)
+		return;
+
+	memcpy(addresses[0].addr, ar->mac_addr, ETH_ALEN);
+	for (i = 1; i < n_addresses; i++) {
+		memcpy(addresses[i].addr, ar->mac_addr, ETH_ALEN);
+		/* set Local Administered Address bit */
+		addresses[i].addr[0] |= 0x2;
+
+		addresses[i].addr[0] += (i - 1) << 4;
+	}
+
+	ar->hw->wiphy->addresses = addresses;
+	ar->hw->wiphy->n_addresses = n_addresses;
+}
+
 static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
 {
 	struct ath11k_base *ab = ar->ab;
@@ -9391,6 +9418,8 @@  static void __ath11k_mac_unregister(struct ath11k *ar)
 	kfree(ar->hw->wiphy->iface_combinations[0].limits);
 	kfree(ar->hw->wiphy->iface_combinations);
 
+	kfree(ar->hw->wiphy->addresses);
+
 	SET_IEEE80211_DEV(ar->hw, NULL);
 }
 
@@ -9433,6 +9462,7 @@  static int __ath11k_mac_register(struct ath11k *ar)
 	ath11k_pdev_caps_update(ar);
 
 	SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr);
+	ath11k_mac_setup_mac_address_list(ar);
 
 	SET_IEEE80211_DEV(ar->hw, ab->dev);