]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: support change_sta_links() mac80211 op
authorSriram R <quic_srirrama@quicinc.com>
Thu, 21 Nov 2024 15:58:00 +0000 (17:58 +0200)
committerKalle Valo <quic_kvalo@quicinc.com>
Mon, 25 Nov 2024 17:02:54 +0000 (19:02 +0200)
Add ath12k_mac_op_change_sta_links() for adding and removing
link station.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://patch.msgid.link/20241121155806.1862733-3-kvalo@kernel.org
drivers/net/wireless/ath/ath12k/mac.c

index d796185c843110ebfe6607ac3c291f2b1d8dc4e6..d92a5e0afe2e4fe39894269410cb7dab548520a9 100644 (file)
@@ -5554,6 +5554,101 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
        rcu_read_unlock();
 }
 
+static struct ath12k_link_sta *ath12k_mac_alloc_assign_link_sta(struct ath12k_hw *ah,
+                                                               struct ath12k_sta *ahsta,
+                                                               struct ath12k_vif *ahvif,
+                                                               u8 link_id)
+{
+       struct ath12k_link_sta *arsta;
+       int ret;
+
+       lockdep_assert_wiphy(ah->hw->wiphy);
+
+       if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
+               return NULL;
+
+       arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
+       if (arsta)
+               return NULL;
+
+       arsta = kmalloc(sizeof(*arsta), GFP_KERNEL);
+       if (!arsta)
+               return NULL;
+
+       ret = ath12k_mac_assign_link_sta(ah, ahsta, arsta, ahvif, link_id);
+       if (ret) {
+               kfree(arsta);
+               return NULL;
+       }
+
+       return arsta;
+}
+
+static int ath12k_mac_op_change_sta_links(struct ieee80211_hw *hw,
+                                         struct ieee80211_vif *vif,
+                                         struct ieee80211_sta *sta,
+                                         u16 old_links, u16 new_links)
+{
+       struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+       struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+       struct ath12k_hw *ah = hw->priv;
+       struct ath12k_link_vif *arvif;
+       struct ath12k_link_sta *arsta;
+       unsigned long valid_links;
+       struct ath12k *ar;
+       u8 link_id;
+       int ret;
+
+       lockdep_assert_wiphy(hw->wiphy);
+
+       if (!sta->valid_links)
+               return -EINVAL;
+
+       /* Firmware does not support removal of one of link stas. All sta
+        * would be removed during ML STA delete in sta_state(), hence link
+        * sta removal is not handled here.
+        */
+       if (new_links < old_links)
+               return 0;
+
+       if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
+               ath12k_hw_warn(ah, "unable to add link for ml sta %pM", sta->addr);
+               return -EINVAL;
+       }
+
+       /* this op is expected only after initial sta insertion with default link */
+       if (WARN_ON(ahsta->links_map == 0))
+               return -EINVAL;
+
+       valid_links = new_links;
+       for_each_set_bit(link_id, &valid_links, IEEE80211_MLD_MAX_NUM_LINKS) {
+               if (ahsta->links_map & BIT(link_id))
+                       continue;
+
+               arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+               arsta = ath12k_mac_alloc_assign_link_sta(ah, ahsta, ahvif, link_id);
+
+               if (!arvif || !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) {
+                       ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
+                                   arsta->addr, arvif->vdev_id);
+                       ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 static int ath12k_conf_tx_uapsd(struct ath12k_link_vif *arvif,
                                u16 ac, bool enable)
 {
@@ -9604,7 +9699,7 @@ static const struct ieee80211_ops ath12k_ops = {
        .sta_statistics                 = ath12k_mac_op_sta_statistics,
        .remain_on_channel              = ath12k_mac_op_remain_on_channel,
        .cancel_remain_on_channel       = ath12k_mac_op_cancel_remain_on_channel,
-
+       .change_sta_links               = ath12k_mac_op_change_sta_links,
 #ifdef CONFIG_PM
        .suspend                        = ath12k_wow_op_suspend,
        .resume                         = ath12k_wow_op_resume,