diff mbox series

[net-next,3/9] ionic: replace lif list with xarray

Message ID 20200216231158.5678-4-snelson@pensando.io
State Rejected
Delegated to: David Miller
Headers show
Series ionic: Add support for Event Queues | expand

Commit Message

Shannon Nelson Feb. 16, 2020, 11:11 p.m. UTC
The lif list works fine for our purposes now, especially when
we're only using a single lif.  However in the near future there
will be support for slave lifs for RDMA and macvlan offloads,
and with that a need to quickly find a given lif by index.
This patch replaces the lif list with an xarray so we don't have
to search through the list every time we need to fine a lif,
and yet don't need to allocate a possibly large but sparsely
populated array.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
---
 drivers/net/ethernet/pensando/ionic/ionic.h   | 16 +++++++-
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 38 +++++++++++--------
 .../net/ethernet/pensando/ionic/ionic_lif.h   |  1 -
 3 files changed, 37 insertions(+), 18 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h
index 7d41e7e56ca6..e5a2a44d9308 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic.h
@@ -4,6 +4,8 @@ 
 #ifndef _IONIC_H_
 #define _IONIC_H_
 
+#include <linux/xarray.h>
+
 struct ionic_lif;
 
 #include "ionic_if.h"
@@ -43,7 +45,7 @@  struct ionic {
 	struct ionic_dev_bar bars[IONIC_BARS_MAX];
 	unsigned int num_bars;
 	struct ionic_identity ident;
-	struct list_head lifs;
+	struct xarray lifs;
 	struct ionic_lif *master_lif;
 	unsigned int nnqs_per_lif;
 	unsigned int nrdma_eqs_per_lif;
@@ -67,6 +69,18 @@  struct ionic_admin_ctx {
 	union ionic_adminq_comp comp;
 };
 
+/* Since we have a bitmap of the allocated lifs, we can use
+ * that to look up each lif specifically, rather than digging
+ * through the whole tree.
+ */
+#define for_each_lif(_ion, _bit, _lif) \
+	for ((_bit) = find_first_bit((_ion)->lifbits, IONIC_LIFS_MAX),   \
+		(_lif) = xa_load(&(_ion)->lifs, (_bit));                 \
+	     (_bit) < IONIC_LIFS_MAX;                                    \
+	     (_bit) = find_next_bit((_ion)->lifbits,                     \
+				    IONIC_LIFS_MAX, ((_bit) + 1)),       \
+		(_lif) = xa_load(&(_ion)->lifs, (_bit)))
+
 int ionic_napi(struct napi_struct *napi, int budget, ionic_cq_cb cb,
 	       ionic_cq_done_cb done_cb, void *done_arg);
 
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 43c8bff02831..58f23760769f 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1891,6 +1891,7 @@  static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
 	struct net_device *netdev;
 	struct ionic_lif *lif;
 	int tbl_sz;
+	void *p;
 	int err;
 
 	netdev = alloc_etherdev_mqs(sizeof(*lif),
@@ -1962,10 +1963,20 @@  static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
 	}
 	netdev_rss_key_fill(lif->rss_hash_key, IONIC_RSS_HASH_KEY_SIZE);
 
-	list_add_tail(&lif->list, &ionic->lifs);
+	p = xa_store(&ionic->lifs, lif->index, lif, GFP_KERNEL);
+	if (xa_err(p)) {
+		dev_err(dev, "LIF tree insertion failed %d, aborting\n",
+			xa_err(p));
+		goto err_out_free_rss;
+	}
 
 	return lif;
 
+err_out_free_rss:
+	dma_free_coherent(dev, lif->rss_ind_tbl_sz, lif->rss_ind_tbl,
+			  lif->rss_ind_tbl_pa);
+	lif->rss_ind_tbl = NULL;
+	lif->rss_ind_tbl_pa = 0;
 err_out_free_qcqs:
 	ionic_qcqs_free(lif);
 err_out_free_lif_info:
@@ -1983,7 +1994,7 @@  int ionic_lifs_alloc(struct ionic *ionic)
 {
 	struct ionic_lif *lif;
 
-	INIT_LIST_HEAD(&ionic->lifs);
+	xa_init(&ionic->lifs);
 
 	/* only build the first lif, others are for later features */
 	set_bit(0, ionic->lifbits);
@@ -2005,6 +2016,7 @@  static void ionic_lif_reset(struct ionic_lif *lif)
 static void ionic_lif_free(struct ionic_lif *lif)
 {
 	struct device *dev = lif->ionic->dev;
+	struct ionic *ionic = lif->ionic;
 
 	/* free rss indirection table */
 	dma_free_coherent(dev, lif->rss_ind_tbl_sz, lif->rss_ind_tbl,
@@ -2022,27 +2034,24 @@  static void ionic_lif_free(struct ionic_lif *lif)
 	lif->info_pa = 0;
 
 	/* unmap doorbell page */
-	ionic_bus_unmap_dbpage(lif->ionic, lif->kern_dbpage);
+	ionic_bus_unmap_dbpage(ionic, lif->kern_dbpage);
 	lif->kern_dbpage = NULL;
 	kfree(lif->dbid_inuse);
 	lif->dbid_inuse = NULL;
 
 	/* free netdev & lif */
 	ionic_debugfs_del_lif(lif);
-	list_del(&lif->list);
+	xa_erase(&ionic->lifs, lif->index);
 	free_netdev(lif->netdev);
 }
 
 void ionic_lifs_free(struct ionic *ionic)
 {
-	struct list_head *cur, *tmp;
 	struct ionic_lif *lif;
+	unsigned int i;
 
-	list_for_each_safe(cur, tmp, &ionic->lifs) {
-		lif = list_entry(cur, struct ionic_lif, list);
-
+	for_each_lif(ionic, i, lif)
 		ionic_lif_free(lif);
-	}
 }
 
 static void ionic_lif_deinit(struct ionic_lif *lif)
@@ -2064,13 +2073,11 @@  static void ionic_lif_deinit(struct ionic_lif *lif)
 
 void ionic_lifs_deinit(struct ionic *ionic)
 {
-	struct list_head *cur, *tmp;
 	struct ionic_lif *lif;
+	unsigned int i;
 
-	list_for_each_safe(cur, tmp, &ionic->lifs) {
-		lif = list_entry(cur, struct ionic_lif, list);
+	for_each_lif(ionic, i, lif)
 		ionic_lif_deinit(lif);
-	}
 }
 
 static int ionic_lif_adminq_init(struct ionic_lif *lif)
@@ -2308,12 +2315,11 @@  static int ionic_lif_init(struct ionic_lif *lif)
 
 int ionic_lifs_init(struct ionic *ionic)
 {
-	struct list_head *cur, *tmp;
 	struct ionic_lif *lif;
+	unsigned int i;
 	int err;
 
-	list_for_each_safe(cur, tmp, &ionic->lifs) {
-		lif = list_entry(cur, struct ionic_lif, list);
+	for_each_lif(ionic, i, lif) {
 		err = ionic_lif_init(lif);
 		if (err)
 			return err;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
index e912f8efb3d5..48d4592c6c9f 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -134,7 +134,6 @@  enum ionic_lif_state_flags {
 #define IONIC_LIF_NAME_MAX_SZ		32
 struct ionic_lif {
 	char name[IONIC_LIF_NAME_MAX_SZ];
-	struct list_head list;
 	struct net_device *netdev;
 	DECLARE_BITMAP(state, IONIC_LIF_STATE_SIZE);
 	struct ionic *ionic;