net: microchip: sparx5: add resource pools
authorDaniel Machon <daniel.machon@microchip.com>
Thu, 2 Feb 2023 10:43:47 +0000 (11:43 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 6 Feb 2023 08:26:25 +0000 (08:26 +0000)
Add resource pools and accessor functions. These pools can be queried by
the driver, whenever a finite resource is required. Some resources can
be reused, in which case an index and a reference count is used to keep
track of users.

Signed-off-by: Daniel Machon <daniel.machon@microchip.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/microchip/sparx5/Makefile
drivers/net/ethernet/microchip/sparx5/sparx5_main.h
drivers/net/ethernet/microchip/sparx5/sparx5_pool.c [new file with mode: 0644]

index d0ed709..6bb4609 100644 (file)
@@ -9,7 +9,8 @@ sparx5-switch-y  := sparx5_main.o sparx5_packet.o \
  sparx5_netdev.o sparx5_phylink.o sparx5_port.o sparx5_mactable.o sparx5_vlan.o \
  sparx5_switchdev.o sparx5_calendar.o sparx5_ethtool.o sparx5_fdma.o \
  sparx5_ptp.o sparx5_pgid.o sparx5_tc.o sparx5_qos.o \
- sparx5_vcap_impl.o sparx5_vcap_ag_api.o sparx5_tc_flower.o sparx5_tc_matchall.o
+ sparx5_vcap_impl.o sparx5_vcap_ag_api.o sparx5_tc_flower.o \
+ sparx5_tc_matchall.o sparx5_pool.o
 
 sparx5-switch-$(CONFIG_SPARX5_DCB) += sparx5_dcb.o
 sparx5-switch-$(CONFIG_DEBUG_FS) += sparx5_vcap_debugfs.o
index 4a574cd..4d0556e 100644 (file)
@@ -413,6 +413,18 @@ int sparx5_pgid_alloc_glag(struct sparx5 *spx5, u16 *idx);
 int sparx5_pgid_alloc_mcast(struct sparx5 *spx5, u16 *idx);
 int sparx5_pgid_free(struct sparx5 *spx5, u16 idx);
 
+/* sparx5_pool.c */
+struct sparx5_pool_entry {
+       u16 ref_cnt;
+       u32 idx; /* tc index */
+};
+
+u32 sparx5_pool_idx_to_id(u32 idx);
+int sparx5_pool_put(struct sparx5_pool_entry *pool, int size, u32 id);
+int sparx5_pool_get(struct sparx5_pool_entry *pool, int size, u32 *id);
+int sparx5_pool_get_with_idx(struct sparx5_pool_entry *pool, int size, u32 idx,
+                            u32 *id);
+
 /* Clock period in picoseconds */
 static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock)
 {
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_pool.c b/drivers/net/ethernet/microchip/sparx5/sparx5_pool.c
new file mode 100644 (file)
index 0000000..b4b280c
--- /dev/null
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip Sparx5 Switch driver
+ *
+ * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#include "sparx5_main_regs.h"
+#include "sparx5_main.h"
+
+static u32 sparx5_pool_id_to_idx(u32 id)
+{
+       return --id;
+}
+
+u32 sparx5_pool_idx_to_id(u32 idx)
+{
+       return ++idx;
+}
+
+/* Release resource from pool.
+ * Return reference count on success, otherwise return error.
+ */
+int sparx5_pool_put(struct sparx5_pool_entry *pool, int size, u32 id)
+{
+       struct sparx5_pool_entry *e_itr;
+
+       e_itr = (pool + sparx5_pool_id_to_idx(id));
+       if (e_itr->ref_cnt == 0)
+               return -EINVAL;
+
+       return --e_itr->ref_cnt;
+}
+
+/* Get resource from pool.
+ * Return reference count on success, otherwise return error.
+ */
+int sparx5_pool_get(struct sparx5_pool_entry *pool, int size, u32 *id)
+{
+       struct sparx5_pool_entry *e_itr;
+       int i;
+
+       for (i = 0, e_itr = pool; i < size; i++, e_itr++) {
+               if (e_itr->ref_cnt == 0) {
+                       *id = sparx5_pool_idx_to_id(i);
+                       return ++e_itr->ref_cnt;
+               }
+       }
+
+       return -ENOSPC;
+}
+
+/* Get resource from pool that matches index.
+ * Return reference count on success, otherwise return error.
+ */
+int sparx5_pool_get_with_idx(struct sparx5_pool_entry *pool, int size, u32 idx,
+                            u32 *id)
+{
+       struct sparx5_pool_entry *e_itr;
+       int i, ret = -ENOSPC;
+
+       for (i = 0, e_itr = pool; i < size; i++, e_itr++) {
+               /* Pool index of first free entry */
+               if (e_itr->ref_cnt == 0 && ret == -ENOSPC)
+                       ret = i;
+               /* Tc index already in use ? */
+               if (e_itr->idx == idx && e_itr->ref_cnt > 0) {
+                       ret = i;
+                       break;
+               }
+       }
+
+       /* Did we find a free entry? */
+       if (ret >= 0) {
+               *id = sparx5_pool_idx_to_id(ret);
+               e_itr = (pool + ret);
+               e_itr->idx = idx;
+               return ++e_itr->ref_cnt;
+       }
+
+       return ret;
+}