wifi: rtl8xxxu: Add sta_add() and sta_remove() callbacks
authorMartin Kaistra <martin.kaistra@linutronix.de>
Fri, 28 Apr 2023 15:08:25 +0000 (17:08 +0200)
committerKalle Valo <kvalo@kernel.org>
Fri, 5 May 2023 07:30:13 +0000 (10:30 +0300)
In AP mode, sta_add() gets called when a new STA gets associated to
us. Call rtl8xxxu_refresh_rate_mask() to set a rate mask for the newly
connected STA (referenced by the macid) and then send a media connnect
report. Ignore the call to sta_add() in station mode.

Reserve one macid for broadcast/multicast packets in init.

Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230428150833.218605-11-martin.kaistra@linutronix.de
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c

index 2dc9b20..a918d12 100644 (file)
@@ -1730,6 +1730,7 @@ struct rtl8xxxu_cfo_tracking {
 };
 
 #define RTL8XXXU_HW_LED_CONTROL        2
+#define RTL8XXXU_MAX_MAC_ID_NUM        128
 #define RTL8XXXU_BC_MC_MACID   0
 
 struct rtl8xxxu_priv {
@@ -1863,6 +1864,14 @@ struct rtl8xxxu_priv {
        bool led_registered;
        char led_name[32];
        struct led_classdev led_cdev;
+       DECLARE_BITMAP(mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
+};
+
+struct rtl8xxxu_sta_info {
+       struct ieee80211_sta *sta;
+       struct ieee80211_vif *vif;
+
+       u8 macid;
 };
 
 struct rtl8xxxu_rx_urb {
index a3ca6ea..dd678f2 100644 (file)
@@ -3977,6 +3977,22 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv)
        rtl8xxxu_write8(priv, REG_RSV_CTRL, val8);
 }
 
+static u8 rtl8xxxu_acquire_macid(struct rtl8xxxu_priv *priv)
+{
+       u8 macid;
+
+       macid = find_first_zero_bit(priv->mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
+       if (macid < RTL8XXXU_MAX_MAC_ID_NUM)
+               set_bit(macid, priv->mac_id_map);
+
+       return macid;
+}
+
+static void rtl8xxxu_release_macid(struct rtl8xxxu_priv *priv, u8 macid)
+{
+       clear_bit(macid, priv->mac_id_map);
+}
+
 static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
 {
        struct rtl8xxxu_priv *priv = hw->priv;
@@ -4446,6 +4462,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
        if (priv->rtl_chip == RTL8188E)
                rtl8188e_ra_info_init_all(&priv->ra_info);
 
+       set_bit(RTL8XXXU_BC_MC_MACID, priv->mac_id_map);
+
 exit:
        return ret;
 }
@@ -7212,6 +7230,38 @@ static void rtl8xxxu_stop(struct ieee80211_hw *hw)
        rtl8xxxu_free_tx_resources(priv);
 }
 
+static int rtl8xxxu_sta_add(struct ieee80211_hw *hw,
+                           struct ieee80211_vif *vif,
+                           struct ieee80211_sta *sta)
+{
+       struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
+       struct rtl8xxxu_priv *priv = hw->priv;
+
+       if (vif->type == NL80211_IFTYPE_AP) {
+               sta_info->macid = rtl8xxxu_acquire_macid(priv);
+               if (sta_info->macid >= RTL8XXXU_MAX_MAC_ID_NUM)
+                       return -ENOSPC;
+
+               rtl8xxxu_refresh_rate_mask(priv, 0, sta, true);
+               priv->fops->report_connect(priv, sta_info->macid, H2C_MACID_ROLE_STA, true);
+       }
+
+       return 0;
+}
+
+static int rtl8xxxu_sta_remove(struct ieee80211_hw *hw,
+                              struct ieee80211_vif *vif,
+                              struct ieee80211_sta *sta)
+{
+       struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
+       struct rtl8xxxu_priv *priv = hw->priv;
+
+       if (vif->type == NL80211_IFTYPE_AP)
+               rtl8xxxu_release_macid(priv, sta_info->macid);
+
+       return 0;
+}
+
 static const struct ieee80211_ops rtl8xxxu_ops = {
        .tx = rtl8xxxu_tx,
        .wake_tx_queue = ieee80211_handle_wake_tx_queue,
@@ -7232,6 +7282,8 @@ static const struct ieee80211_ops rtl8xxxu_ops = {
        .sta_statistics = rtl8xxxu_sta_statistics,
        .get_antenna = rtl8xxxu_get_antenna,
        .set_tim = rtl8xxxu_set_tim,
+       .sta_add = rtl8xxxu_sta_add,
+       .sta_remove = rtl8xxxu_sta_remove,
 };
 
 static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv,