diff mbox series

[RFC,v1,235/256] cl8k: add vif.c

Message ID 20210617160223.160998-236-viktor.barna@celeno.com
State New
Headers show
Series wireless: cl8k driver for Celeno IEEE 802.11ax devices | expand

Commit Message

Viktor Barna June 17, 2021, 4:02 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>
---
 drivers/net/wireless/celeno/cl8k/vif.c | 143 +++++++++++++++++++++++++
 1 file changed, 143 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/vif.c

--
2.30.0
diff mbox series

Patch

diff --git a/drivers/net/wireless/celeno/cl8k/vif.c b/drivers/net/wireless/celeno/cl8k/vif.c
new file mode 100644
index 000000000000..80234de0bb7c
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/vif.c
@@ -0,0 +1,143 @@ 
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "vif.h"
+#include "hw.h"
+#include "mac_addr.h"
+#include "utils/utils.h"
+#include <linux/list.h>
+
+void cl_vif_init(struct cl_hw *cl_hw)
+{
+       INIT_LIST_HEAD(&cl_hw->vif_db.head);
+}
+
+void cl_vif_add(struct cl_hw *cl_hw, struct cl_vif *cl_vif)
+{
+       list_add_tail(&cl_vif->list, &cl_hw->vif_db.head);
+
+       if (cl_vif->vif->type != NL80211_IFTYPE_STATION)
+               cl_hw->vif_db.num_iface_bcn++;
+
+       /* Multicast vif set */
+       cl_hw->mc_vif = cl_vif;
+}
+
+void cl_vif_remove(struct cl_hw *cl_hw, struct cl_vif *cl_vif)
+{
+       /* Multicast vif unset */
+       if (cl_hw->mc_vif == cl_vif)
+               cl_hw->mc_vif = cl_vif_get_next(cl_hw, cl_hw->mc_vif);
+
+       list_del(&cl_vif->list);
+
+       if (cl_vif->vif->type != NL80211_IFTYPE_STATION)
+               cl_hw->vif_db.num_iface_bcn--;
+}
+
+struct cl_vif *cl_vif_get_next(struct cl_hw *cl_hw, struct cl_vif *cl_vif)
+{
+       if (list_is_last(&cl_vif->list, &cl_hw->vif_db.head))
+               return list_first_entry_or_null(&cl_hw->vif_db.head,
+                                               struct cl_vif, list);
+       else
+               return list_next_entry(cl_vif, list);
+}
+
+struct cl_vif *cl_vif_get_by_dev(struct cl_hw *cl_hw, struct net_device *dev)
+{
+       struct cl_vif *cl_vif = NULL;
+
+       list_for_each_entry(cl_vif, &cl_hw->vif_db.head, list)
+               if (cl_vif->dev == dev)
+                       return cl_vif;
+
+       return NULL;
+}
+
+struct cl_vif *cl_vif_get_by_mac(struct cl_hw *cl_hw, u8 *mac_addr)
+{
+       struct cl_vif *cl_vif;
+
+       list_for_each_entry(cl_vif, &cl_hw->vif_db.head, list)
+               if (cl_mac_addr_compare(cl_vif->vif->addr, mac_addr))
+                       return cl_vif;
+
+       return NULL;
+}
+
+struct cl_vif *cl_vif_get_first(struct cl_hw *cl_hw)
+{
+       return list_first_entry_or_null(&cl_hw->vif_db.head, struct cl_vif, list);
+}
+
+struct cl_vif *cl_vif_get_first_ap(struct cl_hw *cl_hw)
+{
+       struct cl_vif *cl_vif;
+
+       list_for_each_entry(cl_vif, &cl_hw->vif_db.head, list)
+               if (cl_vif->vif->type == NL80211_IFTYPE_AP ||
+                   cl_vif->vif->type == NL80211_IFTYPE_MESH_POINT)
+                       return cl_vif;
+
+       return NULL;
+}
+
+struct net_device *cl_vif_get_first_net_device(struct cl_hw *cl_hw)
+{
+       struct cl_vif *cl_vif = list_first_entry_or_null(&cl_hw->vif_db.head, struct cl_vif, list);
+
+       return cl_vif ? cl_vif->dev : NULL;
+}
+
+struct net_device *cl_vif_get_dev_by_index(struct cl_hw *cl_hw, u8 index)
+{
+       struct cl_vif *cl_vif = NULL;
+
+       list_for_each_entry(cl_vif, &cl_hw->vif_db.head, list)
+               if (cl_vif->vif_index == index)
+                       return cl_vif->dev;
+
+       return NULL;
+}
+
+bool cl_vif_find_mac(struct cl_hw *cl_hw, u8 *mac_addr)
+{
+       struct cl_vif *cl_vif;
+
+       list_for_each_entry(cl_vif, &cl_hw->vif_db.head, list)
+               if (cl_mac_addr_compare(cl_vif->vif->addr, mac_addr))
+                       return true;
+
+       return false;
+}
+
+void cl_vif_ap_tx_enable(struct cl_hw *cl_hw, bool enable)
+{
+       struct cl_vif *cl_vif;
+       struct ieee80211_vif *vif;
+
+       list_for_each_entry(cl_vif, &cl_hw->vif_db.head, list) {
+               vif = cl_vif->vif;
+
+               if (vif->type != NL80211_IFTYPE_AP)
+                       continue;
+
+               cl_vif->tx_en = enable;
+               cl_dbg_verbose(cl_hw, "Set tx_en=%u for vif_index=%u\n",
+                              enable, cl_vif->vif_index);
+       }
+}
+
+void cl_vif_bring_all_interfaces_down(struct cl_hw *cl_hw)
+{
+       struct cl_vif *cl_vif = NULL, *cl_vif_tmp = NULL;
+
+       /* Remove all interfaces gracefully to avoid of memleaks and kernel panics */
+       list_for_each_entry_safe(cl_vif, cl_vif_tmp, &cl_hw->vif_db.head, list) {
+               rtnl_lock();
+               dev_close(cl_vif->dev);
+               rtnl_unlock();
+       }
+}
+