diff mbox series

[RFC,v1,079/256] cl8k: add ext/dyn_mcast_rate.c

Message ID 20210617160223.160998-80-viktor.barna@celeno.com (mailing list archive)
State RFC
Delegated to: Kalle Valo
Headers show
Series wireless: cl8k driver for Celeno IEEE 802.11ax devices | expand

Commit Message

Viktor Barna June 17, 2021, 3:59 p.m. UTC
From: Viktor Barna <viktor.barna@celeno.com>

(Part of the split. Please, take a look at the cover letter for more
details).

Signed-off-by: Viktor Barna <viktor.barna@celeno.com>
---
 .../wireless/celeno/cl8k/ext/dyn_mcast_rate.c | 125 ++++++++++++++++++
 1 file changed, 125 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/ext/dyn_mcast_rate.c

--
2.30.0
diff mbox series

Patch

diff --git a/drivers/net/wireless/celeno/cl8k/ext/dyn_mcast_rate.c b/drivers/net/wireless/celeno/cl8k/ext/dyn_mcast_rate.c
new file mode 100644
index 000000000000..bbd83468bcc7
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/ext/dyn_mcast_rate.c
@@ -0,0 +1,125 @@ 
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "band.h"
+#include "sta.h"
+#include "rate_ctrl.h"
+#include "data_rates.h"
+#include "utils/utils.h"
+
+static void _cl_dyn_mcast_rate_send(struct cl_hw *cl_hw, u8 wrs_mode_new)
+{
+       struct cl_dyn_mcast_rate *dyn_mcast_rate = &cl_hw->dyn_mcast_rate;
+
+       if (dyn_mcast_rate->wrs_mode_curr == wrs_mode_new)
+               return;
+
+       if (!cl_rate_ctrl_set_mcast(cl_hw, wrs_mode_new, cl_hw->conf->ce_mcast_rate))
+               return;
+
+       dyn_mcast_rate->wrs_mode_curr = wrs_mode_new;
+       cl_dbg_trace(cl_hw, "New multicast mode = %u\n", wrs_mode_new);
+}
+
+void cl_dyn_mcast_rate_init(struct cl_hw *cl_hw)
+{
+       struct cl_dyn_mcast_rate *dyn_mcast_rate = &cl_hw->dyn_mcast_rate;
+
+       if (cl_hw->conf->ci_min_he_en &&
+           cl_hw->conf->ce_wireless_mode == WIRELESS_MODE_HE)
+               dyn_mcast_rate->wrs_mode_default = WRS_MODE_HE;
+       else if (cl_band_is_24g(cl_hw) && cl_hw_mode_is_b_or_bg(cl_hw))
+               dyn_mcast_rate->wrs_mode_default = WRS_MODE_CCK;
+       else
+               dyn_mcast_rate->wrs_mode_default = WRS_MODE_OFDM;
+
+       cl_dbg_trace(cl_hw, "mode = %u, mcs = %u\n",
+                    dyn_mcast_rate->wrs_mode_default, cl_hw->conf->ce_mcast_rate);
+}
+
+void cl_dyn_mcast_rate_set(struct cl_hw *cl_hw)
+{
+       /*
+        * Set wrs_mode_curr to 0xff so that the message will be sent to
+        * firmware when this function is called from cl_ops_start()
+        */
+       struct cl_dyn_mcast_rate *dyn_mcast_rate = &cl_hw->dyn_mcast_rate;
+
+       dyn_mcast_rate->wrs_mode_curr = U8_MAX;
+
+       _cl_dyn_mcast_rate_send(cl_hw, dyn_mcast_rate->wrs_mode_default);
+}
+
+u16 cl_dyn_mcast_rate_get(struct cl_hw *cl_hw)
+{
+       struct cl_dyn_mcast_rate *dyn_mcast_rate = &cl_hw->dyn_mcast_rate;
+
+       return cl_data_rates_get(dyn_mcast_rate->wrs_mode_curr, 0, 0,
+                                cl_hw->conf->ce_mcast_rate, 0);
+}
+
+void cl_dyn_mcast_rate_recovery(struct cl_hw *cl_hw)
+{
+       /*
+        * cl_dyn_mcast_rate_recovery() is called during recovery process().
+        * Reset wrs_mode_curr so that message will be sent.
+        */
+       struct cl_dyn_mcast_rate *dyn_mcast_rate = &cl_hw->dyn_mcast_rate;
+       u8 wrs_mode_curr = dyn_mcast_rate->wrs_mode_curr;
+
+       dyn_mcast_rate->wrs_mode_curr = U8_MAX;
+
+       _cl_dyn_mcast_rate_send(cl_hw, wrs_mode_curr);
+}
+
+void cl_dyn_mcast_rate_update_upon_assoc(struct cl_hw *cl_hw, u8 wrs_mode, u8 num_sta)
+{
+       struct cl_dyn_mcast_rate *dyn_mcast_rate = &cl_hw->dyn_mcast_rate;
+
+       if (!cl_hw->conf->ce_dyn_mcast_rate_en)
+               return;
+
+       /*
+        * If the wrs_mode of the new station is lower than the current multicast
+        * wrs_mode, or if this is the first station to connect - update multicast mode
+        */
+       if (wrs_mode < dyn_mcast_rate->wrs_mode_curr || num_sta == 1)
+               _cl_dyn_mcast_rate_send(cl_hw, wrs_mode);
+}
+
+void cl_dyn_mcast_rate_update_upon_disassoc(struct cl_hw *cl_hw, u8 wrs_mode, u8 num_sta)
+{
+       struct cl_dyn_mcast_rate *dyn_mcast_rate = &cl_hw->dyn_mcast_rate;
+       struct cl_sta *cl_sta = NULL;
+       u8 wrs_mode_min = WRS_MODE_HE;
+
+       if (!cl_hw->conf->ce_dyn_mcast_rate_en)
+               return;
+
+       /* When the last station disconnects - set default mcast rate */
+       if (num_sta == 0) {
+               _cl_dyn_mcast_rate_send(cl_hw, dyn_mcast_rate->wrs_mode_default);
+               return;
+       }
+
+       /*
+        * If wrs_mode of the disassociating station is bigger
+        * than the current mode then there is nothing to update.
+        */
+       if (wrs_mode > dyn_mcast_rate->wrs_mode_curr)
+               return;
+
+       /*
+        * Find minimal wrs_mode among the connected stations (the
+        * disassociating station is not in list at this stage).
+        */
+       cl_sta_lock_bh(cl_hw);
+
+       list_for_each_entry(cl_sta, &cl_hw->cl_sta_db.head, list)
+               if (cl_sta->wrs_sta.mode < wrs_mode_min)
+                       wrs_mode_min = cl_sta->wrs_sta.mode;
+
+       cl_sta_unlock_bh(cl_hw);
+
+       _cl_dyn_mcast_rate_send(cl_hw, wrs_mode_min);
+}