All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/9] ionic: Add support for Event Queues
@ 2020-02-16 23:11 Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 1/9] ionic: change param from lif to ionic Shannon Nelson
                   ` (9 more replies)
  0 siblings, 10 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

In configurations where we have many CPU cores and want lots
of queues in each device, we can easily run out of interrupt
resources, and so need to find ways to limit our usage, either
by using fewer queues, or by multiplexing the interrupt needs.

This patchset adds a new EventQueue feature that can be used
for multiplexing the interrupts if we find that we can't get
enough from the system to support our configuration.  We can
create a small number of EQs that use interrupts, and have
the TxRx queue pairs subscribe to event messages that come
through the EQs, selecting an EQ with (TxIndex % numEqs).

The interrupt messages normally generated by packet events
become events in the EQ, and the EQ handler will schedule napi
sessions for the queues subscribed to the particular event.

The use of EQs is driven by the firmware configuration - if
it shows support for ethernet event queues (eq_count in the
device identity), the driver will try to use them instead of
regular interrupts per TxRx queuepair.  If for some reason
the EQ setup fails, the driver falls back to using regular
TxRx interrupts.

The first 3 patches are prep work, the next 4 build up the
Event Queue support, the 8th links in and uses the new EQs,
and the final patch adds a bit of debugging assistance if
things ever go very wrong in probe.

Signed-off-by: Shannon Nelson <snelson@pensando.io>

Shannon Nelson (9):
  ionic: change param from lif to ionic
  ionic: rename rdma eqs field
  ionic: replace lif list with xarray
  ionic: add event queue definitions to hw interface
  ionic: rename napi irq functions
  ionic: add functions for setup and tear down event queues
  ionic: add q ident query for eq
  ionic: add basic eq support
  ionic: keep ionic dev on lif init fail

 drivers/net/ethernet/pensando/ionic/ionic.h   |  20 +-
 .../ethernet/pensando/ionic/ionic_bus_pci.c   |   8 +
 .../ethernet/pensando/ionic/ionic_debugfs.c   |  34 ++
 .../ethernet/pensando/ionic/ionic_debugfs.h   |   2 +
 .../net/ethernet/pensando/ionic/ionic_dev.c   | 357 ++++++++++++++++++
 .../net/ethernet/pensando/ionic/ionic_dev.h   |  29 ++
 .../net/ethernet/pensando/ionic/ionic_if.h    |  86 +++++
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 265 ++++++++-----
 .../net/ethernet/pensando/ionic/ionic_lif.h   |   7 +-
 .../net/ethernet/pensando/ionic/ionic_txrx.c  |  63 +++-
 .../net/ethernet/pensando/ionic/ionic_txrx.h  |   1 +
 11 files changed, 772 insertions(+), 100 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH net-next 1/9] ionic: change param from lif to ionic
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
@ 2020-02-16 23:11 ` Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 2/9] ionic: rename rdma eqs field Shannon Nelson
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

Use an ionic pointer rather than the lif in ionic_intr_alloc()
and ionic_intr_free() so that in the future we can allocate
interrupts before we have a lif.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
---
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 21 +++++++++----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 191271f6260d..15d5b24d89a1 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -149,15 +149,14 @@ static int ionic_request_irq(struct ionic_lif *lif, struct ionic_qcq *qcq)
 				0, intr->name, &qcq->napi);
 }
 
-static int ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
+static int ionic_intr_alloc(struct ionic *ionic, struct ionic_intr_info *intr)
 {
-	struct ionic *ionic = lif->ionic;
 	int index;
 
 	index = find_first_zero_bit(ionic->intrs, ionic->nintrs);
 	if (index == ionic->nintrs) {
-		netdev_warn(lif->netdev, "%s: no intr, index=%d nintrs=%d\n",
-			    __func__, index, ionic->nintrs);
+		dev_warn(ionic->dev, "%s: no intr, index=%d nintrs=%d\n",
+			 __func__, index, ionic->nintrs);
 		return -ENOSPC;
 	}
 
@@ -167,10 +166,10 @@ static int ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
 	return 0;
 }
 
-static void ionic_intr_free(struct ionic_lif *lif, int index)
+static void ionic_intr_free(struct ionic *ionic, int index)
 {
-	if (index != INTR_INDEX_NOT_ASSIGNED && index < lif->ionic->nintrs)
-		clear_bit(index, lif->ionic->intrs);
+	if (index != INTR_INDEX_NOT_ASSIGNED && index < ionic->nintrs)
+		clear_bit(index, ionic->intrs);
 }
 
 static int ionic_qcq_enable(struct ionic_qcq *qcq)
@@ -294,7 +293,7 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
 	qcq->base_pa = 0;
 
 	if (qcq->flags & IONIC_QCQ_F_INTR)
-		ionic_intr_free(lif, qcq->intr.index);
+		ionic_intr_free(lif->ionic, qcq->intr.index);
 
 	devm_kfree(dev, qcq->cq.info);
 	qcq->cq.info = NULL;
@@ -337,7 +336,7 @@ static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
 				      struct ionic_qcq *n_qcq)
 {
 	if (WARN_ON(n_qcq->flags & IONIC_QCQ_F_INTR)) {
-		ionic_intr_free(n_qcq->cq.lif, n_qcq->intr.index);
+		ionic_intr_free(n_qcq->cq.lif->ionic, n_qcq->intr.index);
 		n_qcq->flags &= ~IONIC_QCQ_F_INTR;
 	}
 
@@ -407,7 +406,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
 	}
 
 	if (flags & IONIC_QCQ_F_INTR) {
-		err = ionic_intr_alloc(lif, &new->intr);
+		err = ionic_intr_alloc(lif->ionic, &new->intr);
 		if (err) {
 			netdev_warn(lif->netdev, "no intr for %s: %d\n",
 				    name, err);
@@ -478,7 +477,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
 	return 0;
 
 err_out_free_intr:
-	ionic_intr_free(lif, new->intr.index);
+	ionic_intr_free(lif->ionic, new->intr.index);
 err_out:
 	dev_err(dev, "qcq alloc of %s%d failed %d\n", name, index, err);
 	return err;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 2/9] ionic: rename rdma eqs field
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 1/9] ionic: change param from lif to ionic Shannon Nelson
@ 2020-02-16 23:11 ` Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 3/9] ionic: replace lif list with xarray Shannon Nelson
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

Before adding fields to track the Eth Event Queues, we
need to rename the RDMA Event Queues fields so as to
prevent any confusion as to which set we're working with.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
---
 drivers/net/ethernet/pensando/ionic/ionic.h   |  2 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 22 ++++++++++---------
 .../net/ethernet/pensando/ionic/ionic_lif.h   |  2 +-
 3 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h
index bb106a32f416..7d41e7e56ca6 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic.h
@@ -46,7 +46,7 @@ struct ionic {
 	struct list_head lifs;
 	struct ionic_lif *master_lif;
 	unsigned int nnqs_per_lif;
-	unsigned int neqs_per_lif;
+	unsigned int nrdma_eqs_per_lif;
 	unsigned int ntxqs_per_lif;
 	unsigned int nrxqs_per_lif;
 	DECLARE_BITMAP(lifbits, IONIC_LIFS_MAX);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 15d5b24d89a1..43c8bff02831 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1912,7 +1912,7 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
 	netdev->min_mtu = IONIC_MIN_MTU;
 	netdev->max_mtu = IONIC_MAX_MTU;
 
-	lif->neqs = ionic->neqs_per_lif;
+	lif->nrdma_eqs = ionic->nrdma_eqs_per_lif;
 	lif->nxqs = ionic->ntxqs_per_lif;
 
 	lif->ionic = ionic;
@@ -2458,26 +2458,28 @@ int ionic_lif_identify(struct ionic *ionic, u8 lif_type,
 int ionic_lifs_size(struct ionic *ionic)
 {
 	struct ionic_identity *ident = &ionic->ident;
-	unsigned int nintrs, dev_nintrs;
+	unsigned int nrdma_eqs_per_lif;
 	union ionic_lif_config *lc;
 	unsigned int ntxqs_per_lif;
 	unsigned int nrxqs_per_lif;
-	unsigned int neqs_per_lif;
 	unsigned int nnqs_per_lif;
-	unsigned int nxqs, neqs;
+	unsigned int dev_nintrs;
 	unsigned int min_intrs;
+	unsigned int nrdma_eqs;
+	unsigned int nintrs;
+	unsigned int nxqs;
 	int err;
 
 	lc = &ident->lif.eth.config;
 	dev_nintrs = le32_to_cpu(ident->dev.nintrs);
-	neqs_per_lif = le32_to_cpu(ident->lif.rdma.eq_qtype.qid_count);
+	nrdma_eqs_per_lif = le32_to_cpu(ident->lif.rdma.eq_qtype.qid_count);
 	nnqs_per_lif = le32_to_cpu(lc->queue_count[IONIC_QTYPE_NOTIFYQ]);
 	ntxqs_per_lif = le32_to_cpu(lc->queue_count[IONIC_QTYPE_TXQ]);
 	nrxqs_per_lif = le32_to_cpu(lc->queue_count[IONIC_QTYPE_RXQ]);
 
 	nxqs = min(ntxqs_per_lif, nrxqs_per_lif);
 	nxqs = min(nxqs, num_online_cpus());
-	neqs = min(neqs_per_lif, num_online_cpus());
+	nrdma_eqs = min(nrdma_eqs_per_lif, num_online_cpus());
 
 try_again:
 	/* interrupt usage:
@@ -2485,7 +2487,7 @@ int ionic_lifs_size(struct ionic *ionic)
 	 *    1 for each CPU for master lif TxRx queue pairs
 	 *    whatever's left is for RDMA queues
 	 */
-	nintrs = 1 + nxqs + neqs;
+	nintrs = 1 + nxqs + nrdma_eqs;
 	min_intrs = 2;  /* adminq + 1 TxRx queue pair */
 
 	if (nintrs > dev_nintrs)
@@ -2505,7 +2507,7 @@ int ionic_lifs_size(struct ionic *ionic)
 	}
 
 	ionic->nnqs_per_lif = nnqs_per_lif;
-	ionic->neqs_per_lif = neqs;
+	ionic->nrdma_eqs_per_lif = nrdma_eqs;
 	ionic->ntxqs_per_lif = nxqs;
 	ionic->nrxqs_per_lif = nxqs;
 	ionic->nintrs = nintrs;
@@ -2519,8 +2521,8 @@ int ionic_lifs_size(struct ionic *ionic)
 		nnqs_per_lif >>= 1;
 		goto try_again;
 	}
-	if (neqs > 1) {
-		neqs >>= 1;
+	if (nrdma_eqs > 1) {
+		nrdma_eqs >>= 1;
 		goto try_again;
 	}
 	if (nxqs > 1) {
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
index 9c5a7dd45f9d..e912f8efb3d5 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -149,7 +149,7 @@ struct ionic_lif {
 	struct ionic_qcqst *txqcqs;
 	struct ionic_qcqst *rxqcqs;
 	u64 last_eid;
-	unsigned int neqs;
+	unsigned int nrdma_eqs;
 	unsigned int nxqs;
 	unsigned int ntxq_descs;
 	unsigned int nrxq_descs;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 3/9] ionic: replace lif list with xarray
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 1/9] ionic: change param from lif to ionic Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 2/9] ionic: rename rdma eqs field Shannon Nelson
@ 2020-02-16 23:11 ` Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 4/9] ionic: add event queue definitions to hw interface Shannon Nelson
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

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 --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;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 4/9] ionic: add event queue definitions to hw interface
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
                   ` (2 preceding siblings ...)
  2020-02-16 23:11 ` [PATCH net-next 3/9] ionic: replace lif list with xarray Shannon Nelson
@ 2020-02-16 23:11 ` Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 5/9] ionic: rename napi irq functions Shannon Nelson
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

Define the hw interface and driver structures for the Event
Queue operations.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
---
 drivers/net/ethernet/pensando/ionic/ionic.h   |  2 ++
 .../net/ethernet/pensando/ionic/ionic_dev.h   | 22 +++++++++++++++++
 .../net/ethernet/pensando/ionic/ionic_if.h    | 24 +++++++++++++++++++
 3 files changed, 48 insertions(+)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h
index e5a2a44d9308..faf2b748bd20 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic.h
@@ -47,6 +47,8 @@ struct ionic {
 	struct ionic_identity ident;
 	struct xarray lifs;
 	struct ionic_lif *master_lif;
+	struct ionic_eq **eqs;
+	unsigned int neth_eqs;
 	unsigned int nnqs_per_lif;
 	unsigned int nrdma_eqs_per_lif;
 	unsigned int ntxqs_per_lif;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
index 7838e342c4fd..d40be30536ae 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
@@ -232,6 +232,28 @@ struct ionic_cq {
 	unsigned int desc_size;
 };
 
+struct ionic_eq_ring {
+	struct ionic_eq_comp *base;
+	dma_addr_t base_pa;
+
+	int index;
+	u8 gen_color;	/* generation counter */
+};
+
+struct ionic_eq {
+	struct ionic *ionic;
+	struct ionic_eq_ring ring[2];
+	struct ionic_intr_info intr;
+
+	int index;
+	int depth;
+
+	bool is_init;
+};
+
+#define IONIC_EQ_DEPTH		0x1000
+#define IONIC_MAX_ETH_EQS	64
+
 struct ionic;
 
 static inline void ionic_intr_init(struct ionic_dev *idev,
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_if.h b/drivers/net/ethernet/pensando/ionic/ionic_if.h
index ce07c2931a72..72a4c0448afc 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_if.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_if.h
@@ -277,6 +277,7 @@ union ionic_dev_identity {
 		__le32 ndbpgs_per_lif;
 		__le32 intr_coal_mult;
 		__le32 intr_coal_div;
+		__le32 eq_count;
 	};
 	__le32 words[512];
 };
@@ -2392,6 +2393,7 @@ union ionic_dev_cmd {
 	struct ionic_qos_reset_cmd qos_reset;
 
 	struct ionic_q_init_cmd q_init;
+	struct ionic_q_control_cmd q_control;
 };
 
 union ionic_dev_cmd_comp {
@@ -2565,6 +2567,28 @@ union ionic_notifyq_comp {
 	struct ionic_log_event log;
 };
 
+/**
+ * struct ionic_eq_comp - Event queue completion descriptor
+ *
+ * @code:  Event code, see enum ionic_eq_comp_code.
+ * @lif_index: To which lif the event pertains.
+ * @qid:   To which queue id the event pertains.
+ * @gen_color: Event queue wrap counter, init 1, incr each wrap.
+ */
+struct ionic_eq_comp {
+	__le16 code;
+	__le16 lif_index;
+	__le32 qid;
+	u8 rsvd[7];
+	u8 gen_color;
+};
+
+enum ionic_eq_comp_code {
+	IONIC_EQ_COMP_CODE_NONE = 0,
+	IONIC_EQ_COMP_CODE_RX_COMP = 1,
+	IONIC_EQ_COMP_CODE_TX_COMP = 2,
+};
+
 /* Deprecate */
 struct ionic_identity {
 	union ionic_drv_identity drv;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 5/9] ionic: rename napi irq functions
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
                   ` (3 preceding siblings ...)
  2020-02-16 23:11 ` [PATCH net-next 4/9] ionic: add event queue definitions to hw interface Shannon Nelson
@ 2020-02-16 23:11 ` Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 6/9] ionic: add functions for setup and tear down event queues Shannon Nelson
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

Make room for similar functions for Event Queue handling.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
---
 drivers/net/ethernet/pensando/ionic/ionic_lif.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 58f23760769f..1eb3bd4016ce 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -121,7 +121,7 @@ static void ionic_link_status_check_request(struct ionic_lif *lif)
 	}
 }
 
-static irqreturn_t ionic_isr(int irq, void *data)
+static irqreturn_t ionic_napi_isr(int irq, void *data)
 {
 	struct napi_struct *napi = data;
 
@@ -130,7 +130,7 @@ static irqreturn_t ionic_isr(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int ionic_request_irq(struct ionic_lif *lif, struct ionic_qcq *qcq)
+static int ionic_request_napi_irq(struct ionic_lif *lif, struct ionic_qcq *qcq)
 {
 	struct ionic_intr_info *intr = &qcq->intr;
 	struct device *dev = lif->ionic->dev;
@@ -145,7 +145,7 @@ static int ionic_request_irq(struct ionic_lif *lif, struct ionic_qcq *qcq)
 	snprintf(intr->name, sizeof(intr->name),
 		 "%s-%s-%s", IONIC_DRV_NAME, name, q->name);
 
-	return devm_request_irq(dev, intr->vector, ionic_isr,
+	return devm_request_irq(dev, intr->vector, ionic_napi_isr,
 				0, intr->name, &qcq->napi);
 }
 
@@ -654,7 +654,7 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
 	netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi,
 		       NAPI_POLL_WEIGHT);
 
-	err = ionic_request_irq(lif, qcq);
+	err = ionic_request_napi_irq(lif, qcq);
 	if (err) {
 		netif_napi_del(&qcq->napi);
 		return err;
@@ -2113,7 +2113,7 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif)
 	netif_napi_add(lif->netdev, &qcq->napi, ionic_adminq_napi,
 		       NAPI_POLL_WEIGHT);
 
-	err = ionic_request_irq(lif, qcq);
+	err = ionic_request_napi_irq(lif, qcq);
 	if (err) {
 		netdev_warn(lif->netdev, "adminq irq request failed %d\n", err);
 		netif_napi_del(&qcq->napi);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 6/9] ionic: add functions for setup and tear down event queues
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
                   ` (4 preceding siblings ...)
  2020-02-16 23:11 ` [PATCH net-next 5/9] ionic: rename napi irq functions Shannon Nelson
@ 2020-02-16 23:11 ` Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 7/9] ionic: add q ident query for eq Shannon Nelson
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

Define the the Event Queue setup and teardown functions.
We'll link them into the driver setup in the next patch.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
---
 .../ethernet/pensando/ionic/ionic_debugfs.c   |  34 ++
 .../ethernet/pensando/ionic/ionic_debugfs.h   |   2 +
 .../net/ethernet/pensando/ionic/ionic_dev.c   | 323 ++++++++++++++++++
 .../net/ethernet/pensando/ionic/ionic_dev.h   |   5 +
 .../net/ethernet/pensando/ionic/ionic_lif.c   |   4 +-
 .../net/ethernet/pensando/ionic/ionic_lif.h   |   3 +
 6 files changed, 369 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c b/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c
index bc03cecf80cc..2b2a0019f36b 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c
@@ -43,6 +43,7 @@ static int identity_show(struct seq_file *seq, void *v)
 
 	seq_printf(seq, "nlifs:            %d\n", ident->dev.nlifs);
 	seq_printf(seq, "nintrs:           %d\n", ident->dev.nintrs);
+	seq_printf(seq, "eth_eq_count:     %d\n", ident->dev.eq_count);
 	seq_printf(seq, "ndbpgs_per_lif:   %d\n", ident->dev.ndbpgs_per_lif);
 	seq_printf(seq, "intr_coal_mult:   %d\n", ident->dev.intr_coal_mult);
 	seq_printf(seq, "intr_coal_div:    %d\n", ident->dev.intr_coal_div);
@@ -125,6 +126,7 @@ void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq)
 
 	debugfs_create_x32("total_size", 0400, qcq->dentry, &qcq->total_size);
 	debugfs_create_x64("base_pa", 0400, qcq->dentry, &qcq->base_pa);
+	debugfs_create_bool("armed", 0400, qcq->dentry, &qcq->armed);
 
 	q_dentry = debugfs_create_dir("q", qcq->dentry);
 
@@ -239,6 +241,38 @@ void ionic_debugfs_del_lif(struct ionic_lif *lif)
 	lif->dentry = NULL;
 }
 
+void ionic_debugfs_add_eq(struct ionic_eq *eq)
+{
+	const int ring_bytes = sizeof(struct ionic_eq_comp) * IONIC_EQ_DEPTH;
+	struct device *dev = eq->ionic->dev;
+	struct debugfs_blob_wrapper *blob;
+	struct debugfs_regset32 *regset;
+	struct dentry *ent;
+	char name[40];
+
+	snprintf(name, sizeof(name), "eq%02u", eq->index);
+
+	ent = debugfs_create_dir(name, eq->ionic->dentry);
+	if (IS_ERR_OR_NULL(ent))
+		return;
+
+	blob = devm_kzalloc(dev, sizeof(*blob), GFP_KERNEL);
+	blob->data = eq->ring[0].base;
+	blob->size = ring_bytes;
+	debugfs_create_blob("ring0", 0400, ent, blob);
+
+	blob = devm_kzalloc(dev, sizeof(*blob), GFP_KERNEL);
+	blob->data = eq->ring[1].base;
+	blob->size = ring_bytes;
+	debugfs_create_blob("ring1", 0400, ent, blob);
+
+	regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL);
+	regset->regs = intr_ctrl_regs;
+	regset->nregs = ARRAY_SIZE(intr_ctrl_regs);
+	regset->base = &eq->ionic->idev.intr_ctrl[eq->intr.index];
+	debugfs_create_regset32("intr_ctrl", 0400, ent, regset);
+}
+
 void ionic_debugfs_del_qcq(struct ionic_qcq *qcq)
 {
 	debugfs_remove_recursive(qcq->dentry);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_debugfs.h b/drivers/net/ethernet/pensando/ionic/ionic_debugfs.h
index c44ebde170b6..dcff2ebe7bf5 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_debugfs.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_debugfs.h
@@ -14,6 +14,7 @@ void ionic_debugfs_add_dev(struct ionic *ionic);
 void ionic_debugfs_del_dev(struct ionic *ionic);
 void ionic_debugfs_add_ident(struct ionic *ionic);
 void ionic_debugfs_add_sizes(struct ionic *ionic);
+void ionic_debugfs_add_eq(struct ionic_eq *eq);
 void ionic_debugfs_add_lif(struct ionic_lif *lif);
 void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq);
 void ionic_debugfs_del_lif(struct ionic_lif *lif);
@@ -25,6 +26,7 @@ static inline void ionic_debugfs_add_dev(struct ionic *ionic) { }
 static inline void ionic_debugfs_del_dev(struct ionic *ionic) { }
 static inline void ionic_debugfs_add_ident(struct ionic *ionic) { }
 static inline void ionic_debugfs_add_sizes(struct ionic *ionic) { }
+static inline void ionic_debugfs_add_eq(struct ionic_eq *eq) { }
 static inline void ionic_debugfs_add_lif(struct ionic_lif *lif) { }
 static inline void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq) { }
 static inline void ionic_debugfs_del_lif(struct ionic_lif *lif) { }
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
index 87f82f36812f..a1e45f4b0c88 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
@@ -8,7 +8,9 @@
 #include <linux/slab.h>
 #include <linux/etherdevice.h>
 #include "ionic.h"
+#include "ionic_bus.h"
 #include "ionic_dev.h"
+#include "ionic_debugfs.h"
 #include "ionic_lif.h"
 
 static void ionic_watchdog_cb(struct timer_list *t)
@@ -406,6 +408,327 @@ int ionic_db_page_num(struct ionic_lif *lif, int pid)
 	return (lif->hw_index * lif->dbid_count) + pid;
 }
 
+static void ionic_txrx_notify(struct ionic *ionic,
+			      int lif_index, int qcq_id, bool is_tx)
+{
+	struct ionic_lif *lif;
+
+	lif = radix_tree_lookup(&ionic->lifs, lif_index);
+	if (!lif)
+		return;
+
+	if (is_tx)
+		lif->txqcqs[qcq_id].qcq->armed = false;
+	else
+		lif->rxqcqs[qcq_id].qcq->armed = false;
+
+	/* We schedule rx napi, it handles both tx and rx */
+	napi_schedule_irqoff(&lif->rxqcqs[qcq_id].qcq->napi);
+}
+
+static bool ionic_next_eq_comp(struct ionic_eq *eq, int ring_index,
+			       struct ionic_eq_comp *comp)
+{
+	struct ionic_eq_ring *ring = &eq->ring[ring_index];
+	struct ionic_eq_comp *qcomp;
+	u8 gen_color;
+
+	qcomp = &ring->base[ring->index];
+	gen_color = qcomp->gen_color;
+
+	if (gen_color == (u8)(ring->gen_color - 1))
+		return false;
+
+	/* Make sure ring descriptor is up-to-date before reading */
+	smp_rmb();
+	*comp = *qcomp;
+	gen_color = comp->gen_color;
+
+	if (gen_color != ring->gen_color) {
+		dev_err(eq->ionic->dev,
+			"eq %u ring %u missed %u events\n",
+			eq->index, ring_index,
+			eq->depth * (gen_color - ring->gen_color));
+
+		ring->gen_color = gen_color;
+	}
+
+	ring->index = (ring->index + 1) & (eq->depth - 1);
+	ring->gen_color += ring->index == 0;
+
+	return true;
+}
+
+static int ionic_poll_eq_ring(struct ionic_eq *eq, int ring_index)
+{
+	struct ionic_eq_comp comp;
+	int budget = eq->depth;
+	int credits = 0;
+	int code;
+
+	while (credits < budget && ionic_next_eq_comp(eq, ring_index, &comp)) {
+		code = le16_to_cpu(comp.code);
+
+		switch (code) {
+		case IONIC_EQ_COMP_CODE_NONE:
+			break;
+		case IONIC_EQ_COMP_CODE_RX_COMP:
+		case IONIC_EQ_COMP_CODE_TX_COMP:
+			ionic_txrx_notify(eq->ionic,
+					  le16_to_cpu(comp.lif_index),
+					  le32_to_cpu(comp.qid),
+					  code == IONIC_EQ_COMP_CODE_TX_COMP);
+			break;
+		default:
+			dev_warn(eq->ionic->dev,
+				 "eq %u ring %u unrecognized event %u\n",
+				 eq->index, ring_index, code);
+			break;
+		}
+
+		credits++;
+	}
+
+	return credits;
+}
+
+static irqreturn_t ionic_eq_isr(int irq, void *data)
+{
+	struct ionic_eq *eq = data;
+	int credits;
+
+	credits = ionic_poll_eq_ring(eq, 0) + ionic_poll_eq_ring(eq, 1);
+	ionic_intr_credits(eq->ionic->idev.intr_ctrl, eq->intr.index,
+			   credits, IONIC_INTR_CRED_UNMASK);
+
+	return IRQ_HANDLED;
+}
+
+static int ionic_request_eq_irq(struct ionic *ionic, struct ionic_eq *eq)
+{
+	struct device *dev = ionic->dev;
+	struct ionic_intr_info *intr = &eq->intr;
+	const char *name = dev_name(dev);
+
+	snprintf(intr->name, sizeof(intr->name),
+		 "%s-%s-eq%d", IONIC_DRV_NAME, name, eq->index);
+
+	return devm_request_irq(dev, intr->vector, ionic_eq_isr,
+				0, intr->name, eq);
+}
+
+static int ionic_eq_alloc(struct ionic *ionic, int index)
+{
+	const int ring_bytes = sizeof(struct ionic_eq_comp) * IONIC_EQ_DEPTH;
+	struct ionic_eq *eq;
+	int err;
+
+	eq = kzalloc(sizeof(*eq), GFP_KERNEL);
+	eq->ionic = ionic;
+	eq->index = index;
+	eq->depth = IONIC_EQ_DEPTH;
+
+	err = ionic_intr_alloc(ionic, &eq->intr);
+	if (err) {
+		dev_warn(ionic->dev, "no intr for eq %u: %d\n", index, err);
+		goto err_out;
+	}
+
+	err = ionic_bus_get_irq(ionic, eq->intr.index);
+	if (err < 0) {
+		dev_warn(ionic->dev, "no vector for eq %u: %d\n", index, err);
+		goto err_out_free_intr;
+	}
+	eq->intr.vector = err;
+
+	ionic_intr_mask_assert(ionic->idev.intr_ctrl, eq->intr.index,
+			       IONIC_INTR_MASK_SET);
+
+	eq->intr.cpu = index % num_online_cpus();
+	if (cpu_online(eq->intr.cpu))
+		cpumask_set_cpu(eq->intr.cpu,
+				&eq->intr.affinity_mask);
+
+	eq->ring[0].gen_color = 1;
+	eq->ring[0].base = dma_alloc_coherent(ionic->dev, ring_bytes,
+					      &eq->ring[0].base_pa,
+					      GFP_KERNEL);
+
+	eq->ring[1].gen_color = 1;
+	eq->ring[1].base = dma_alloc_coherent(ionic->dev, ring_bytes,
+					      &eq->ring[1].base_pa,
+					      GFP_KERNEL);
+
+	ionic->eqs[index] = eq;
+
+	ionic_debugfs_add_eq(eq);
+
+	return 0;
+
+err_out_free_intr:
+	ionic_intr_free(ionic, eq->intr.index);
+err_out:
+	return err;
+}
+
+int ionic_eqs_alloc(struct ionic *ionic)
+{
+	size_t eq_size;
+	int i, err;
+
+	eq_size = sizeof(*ionic->eqs) * ionic->neth_eqs;
+	ionic->eqs = kzalloc(eq_size, GFP_KERNEL);
+	if (!ionic->eqs)
+		return -ENOMEM;
+
+	for (i = 0; i < ionic->neth_eqs; i++) {
+		err = ionic_eq_alloc(ionic, i);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static void ionic_eq_free(struct ionic_eq *eq)
+{
+	const int ring_bytes = sizeof(struct ionic_eq_comp) * IONIC_EQ_DEPTH;
+	struct ionic *ionic = eq->ionic;
+
+	eq->ionic->eqs[eq->index] = NULL;
+
+	dma_free_coherent(ionic->dev, ring_bytes,
+			  eq->ring[0].base,
+			  eq->ring[0].base_pa);
+	dma_free_coherent(ionic->dev, ring_bytes,
+			  eq->ring[1].base,
+			  eq->ring[1].base_pa);
+	ionic_intr_free(ionic, eq->intr.index);
+	kfree(eq);
+}
+
+void ionic_eqs_free(struct ionic *ionic)
+{
+	int i;
+
+	if (!ionic->eqs)
+		return;
+
+	for (i = 0; i < ionic->neth_eqs; i++) {
+		if (ionic->eqs[i])
+			ionic_eq_free(ionic->eqs[i]);
+	}
+
+	kfree(ionic->eqs);
+	ionic->eqs = NULL;
+	ionic->neth_eqs = 0;
+}
+
+static void ionic_eq_deinit(struct ionic_eq *eq)
+{
+	struct ionic *ionic = eq->ionic;
+	union ionic_dev_cmd cmd = {
+		.q_control = {
+			.opcode = IONIC_CMD_Q_CONTROL,
+			.type = IONIC_QTYPE_EQ,
+			.index = cpu_to_le32(eq->index),
+			.oper = IONIC_Q_DISABLE,
+		},
+	};
+
+	if (!eq->is_init)
+		return;
+	eq->is_init = false;
+
+	mutex_lock(&ionic->dev_cmd_lock);
+	ionic_dev_cmd_go(&ionic->idev, &cmd);
+	ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
+	mutex_unlock(&ionic->dev_cmd_lock);
+
+	ionic_intr_mask(ionic->idev.intr_ctrl, eq->intr.index,
+			IONIC_INTR_MASK_SET);
+	synchronize_irq(eq->intr.vector);
+
+	irq_set_affinity_hint(eq->intr.vector, NULL);
+	devm_free_irq(ionic->dev, eq->intr.vector, eq);
+}
+
+void ionic_eqs_deinit(struct ionic *ionic)
+{
+	int i;
+
+	if (!ionic->eqs)
+		return;
+
+	for (i = 0; i < ionic->neth_eqs; i++) {
+		if (ionic->eqs[i])
+			ionic_eq_deinit(ionic->eqs[i]);
+	}
+}
+
+static int ionic_eq_init(struct ionic_eq *eq)
+{
+	struct ionic *ionic = eq->ionic;
+	union ionic_dev_cmd cmd = {
+		.q_init = {
+			.opcode = IONIC_CMD_Q_INIT,
+			.type = IONIC_QTYPE_EQ,
+			.index = cpu_to_le32(eq->index),
+			.intr_index = cpu_to_le16(eq->intr.index),
+			.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
+					     IONIC_QINIT_F_ENA),
+			.ring_size = ilog2(eq->depth),
+			.ring_base = cpu_to_le64(eq->ring[0].base_pa),
+			.cq_ring_base = cpu_to_le64(eq->ring[1].base_pa),
+		},
+	};
+	int err;
+
+	ionic_intr_mask(ionic->idev.intr_ctrl, eq->intr.index,
+			IONIC_INTR_MASK_SET);
+	ionic_intr_clean(ionic->idev.intr_ctrl, eq->intr.index);
+
+	err = ionic_request_eq_irq(ionic, eq);
+	if (err) {
+		dev_warn(ionic->dev, "eq %d irq request failed %d\n",
+			 eq->index, err);
+		return err;
+	}
+
+	mutex_lock(&ionic->dev_cmd_lock);
+	ionic_dev_cmd_go(&ionic->idev, &cmd);
+	err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
+	mutex_unlock(&ionic->dev_cmd_lock);
+
+	if (err) {
+		dev_err(ionic->dev, "eq %d init failed %d\n",
+			eq->index, err);
+		return err;
+	}
+
+	ionic_intr_mask(ionic->idev.intr_ctrl, eq->intr.index,
+			IONIC_INTR_MASK_CLEAR);
+
+	eq->is_init = true;
+
+	return 0;
+}
+
+int ionic_eqs_init(struct ionic *ionic)
+{
+	int i, err;
+
+	for (i = 0; i < ionic->neth_eqs; i++) {
+		if (ionic->eqs[i]) {
+			err = ionic_eq_init(ionic->eqs[i]);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
 int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
 		  struct ionic_intr_info *intr,
 		  unsigned int num_descs, size_t desc_size)
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
index d40be30536ae..a9e7249b5680 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
@@ -313,6 +313,11 @@ void ionic_dev_cmd_adminq_init(struct ionic_dev *idev, struct ionic_qcq *qcq,
 
 int ionic_db_page_num(struct ionic_lif *lif, int pid);
 
+int ionic_eqs_alloc(struct ionic *ionic);
+void ionic_eqs_free(struct ionic *ionic);
+void ionic_eqs_deinit(struct ionic *ionic);
+int ionic_eqs_init(struct ionic *ionic);
+
 int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
 		  struct ionic_intr_info *intr,
 		  unsigned int num_descs, size_t desc_size);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 1eb3bd4016ce..9150cca06b77 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -149,7 +149,7 @@ static int ionic_request_napi_irq(struct ionic_lif *lif, struct ionic_qcq *qcq)
 				0, intr->name, &qcq->napi);
 }
 
-static int ionic_intr_alloc(struct ionic *ionic, struct ionic_intr_info *intr)
+int ionic_intr_alloc(struct ionic *ionic, struct ionic_intr_info *intr)
 {
 	int index;
 
@@ -166,7 +166,7 @@ static int ionic_intr_alloc(struct ionic *ionic, struct ionic_intr_info *intr)
 	return 0;
 }
 
-static void ionic_intr_free(struct ionic *ionic, int index)
+void ionic_intr_free(struct ionic *ionic, int index)
 {
 	if (index != INTR_INDEX_NOT_ASSIGNED && index < ionic->nintrs)
 		clear_bit(index, ionic->intrs);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
index 48d4592c6c9f..bb9202a10ac1 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -63,6 +63,7 @@ struct ionic_qcq {
 	void *base;
 	dma_addr_t base_pa;
 	unsigned int total_size;
+	bool armed;
 	struct ionic_queue q;
 	struct ionic_cq cq;
 	struct ionic_intr_info intr;
@@ -236,6 +237,8 @@ int ionic_lifs_size(struct ionic *ionic);
 int ionic_lif_rss_config(struct ionic_lif *lif, u16 types,
 			 const u8 *key, const u32 *indir);
 
+int ionic_intr_alloc(struct ionic *ionic, struct ionic_intr_info *intr);
+void ionic_intr_free(struct ionic *ionic, int index);
 int ionic_open(struct net_device *netdev);
 int ionic_stop(struct net_device *netdev);
 int ionic_reset_queues(struct ionic_lif *lif);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 7/9] ionic: add q ident query for eq
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
                   ` (5 preceding siblings ...)
  2020-02-16 23:11 ` [PATCH net-next 6/9] ionic: add functions for setup and tear down event queues Shannon Nelson
@ 2020-02-16 23:11 ` Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 8/9] ionic: add basic eq support Shannon Nelson
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

Add the queue identity query and use it to verify that
EventQueues are supported in the FW.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
---
 .../net/ethernet/pensando/ionic/ionic_dev.c   | 34 ++++++++++
 .../net/ethernet/pensando/ionic/ionic_dev.h   |  2 +
 .../net/ethernet/pensando/ionic/ionic_if.h    | 62 +++++++++++++++++++
 3 files changed, 98 insertions(+)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
index a1e45f4b0c88..add0e026ba55 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
@@ -347,6 +347,19 @@ int ionic_set_vf_config(struct ionic *ionic, int vf, u8 attr, u8 *data)
 }
 
 /* LIF commands */
+void ionic_dev_cmd_queue_identify(struct ionic_dev *idev,
+				  u16 lif_type, u8 qtype, u8 qver)
+{
+	union ionic_dev_cmd cmd = {
+		.q_identify.opcode = IONIC_CMD_Q_IDENTIFY,
+		.q_identify.lif_type = lif_type,
+		.q_identify.type = qtype,
+		.q_identify.ver = qver,
+	};
+
+	ionic_dev_cmd_go(idev, &cmd);
+}
+
 void ionic_dev_cmd_lif_identify(struct ionic_dev *idev, u8 type, u8 ver)
 {
 	union ionic_dev_cmd cmd = {
@@ -669,6 +682,7 @@ void ionic_eqs_deinit(struct ionic *ionic)
 static int ionic_eq_init(struct ionic_eq *eq)
 {
 	struct ionic *ionic = eq->ionic;
+	union ionic_q_identity *q_ident;
 	union ionic_dev_cmd cmd = {
 		.q_init = {
 			.opcode = IONIC_CMD_Q_INIT,
@@ -684,6 +698,26 @@ static int ionic_eq_init(struct ionic_eq *eq)
 	};
 	int err;
 
+	q_ident = (union ionic_q_identity *)&ionic->idev.dev_cmd_regs->data;
+
+	mutex_lock(&ionic->dev_cmd_lock);
+	ionic_dev_cmd_queue_identify(&ionic->idev, IONIC_LIF_TYPE_CLASSIC,
+				     IONIC_QTYPE_EQ, 0);
+	err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
+	cmd.q_init.ver = q_ident->version;
+	mutex_unlock(&ionic->dev_cmd_lock);
+
+	if (err == -EINVAL) {
+		dev_err(ionic->dev, "eq init failed, not supported\n");
+		return err;
+	} else if (err == -EIO) {
+		dev_err(ionic->dev, "q_ident eq failed, not supported on older FW\n");
+		return err;
+	} else if (err) {
+		dev_warn(ionic->dev, "eq version type request failed %d, defaulting to %d\n",
+			 err, cmd.q_init.ver);
+	}
+
 	ionic_intr_mask(ionic->idev.intr_ctrl, eq->intr.index,
 			IONIC_INTR_MASK_SET);
 	ionic_intr_clean(ionic->idev.intr_ctrl, eq->intr.index);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
index a9e7249b5680..6a4f060505fd 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
@@ -304,6 +304,8 @@ void ionic_dev_cmd_port_fec(struct ionic_dev *idev, u8 fec_type);
 void ionic_dev_cmd_port_pause(struct ionic_dev *idev, u8 pause_type);
 
 int ionic_set_vf_config(struct ionic *ionic, int vf, u8 attr, u8 *data);
+void ionic_dev_cmd_queue_identify(struct ionic_dev *idev,
+				  u16 lif_type, u8 qtype, u8 qver);
 void ionic_dev_cmd_lif_identify(struct ionic_dev *idev, u8 type, u8 ver);
 void ionic_dev_cmd_lif_init(struct ionic_dev *idev, u16 lif_index,
 			    dma_addr_t addr);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_if.h b/drivers/net/ethernet/pensando/ionic/ionic_if.h
index 72a4c0448afc..af38ebb543cd 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_if.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_if.h
@@ -42,6 +42,7 @@ enum ionic_cmd_opcode {
 	IONIC_CMD_RX_FILTER_DEL			= 32,
 
 	/* Queue commands */
+	IONIC_CMD_Q_IDENTIFY			= 39,
 	IONIC_CMD_Q_INIT			= 40,
 	IONIC_CMD_Q_CONTROL			= 41,
 
@@ -461,6 +462,65 @@ struct ionic_lif_init_cmd {
 	u8     rsvd2[48];
 };
 
+/**
+ * struct ionic_q_identify_cmd - queue identify command
+ * @opcode:     opcode
+ * @lif_type:   lif type (enum lif_type)
+ * @type:       logical queue type (enum logical_qtype)
+ * @ver:        highest queue type version that the driver supports
+ */
+struct ionic_q_identify_cmd {
+	u8     opcode;
+	u8     rsvd;
+	__le16 lif_type;
+	u8     type;
+	u8     ver;
+	u8     rsvd2[58];
+};
+
+/**
+ * struct ionic_q_identify_comp - queue identify command completion
+ * @status:  status of the command (enum status_code)
+ * @ver:     queue type version that can be used with FW
+ */
+struct ionic_q_identify_comp {
+	u8     status;
+	u8     rsvd;
+	__le16 comp_index;
+	u8     ver;
+	u8     rsvd2[11];
+};
+
+/**
+ * union ionic_q_identity - queue identity information
+ *     @version:        queue type version that can be used with FW
+ *     @supported:      bitfield of queue versions, first bit = ver 0
+ *     @features:       queue features
+ *     @desc_sz:        descriptor size
+ *     @comp_sz:        completion descriptor size
+ *     @sg_desc_sz:     sg descriptor size
+ *     @max_sg_elems:   maximum number of sg elements
+ *     @sg_desc_stride: number of sg elements per descriptor
+ */
+union ionic_q_identity {
+	struct {
+		u8      version;
+		u8      supported;
+		u8      rsvd[6];
+#define IONIC_QIDENT_F_CQ	0x01	/* queue has completion ring */
+#define IONIC_QIDENT_F_SG	0x02	/* queue has scatter/gather ring */
+#define IONIC_QIDENT_F_EQ	0x04	/* queue can use event queue */
+#define IONIC_QIDENT_F_CMB	0x08	/* queue is in cmb bar */
+		__le64  features;
+		__le16  desc_sz;
+		__le16  comp_sz;
+		__le16  sg_desc_sz;
+		__le16  max_sg_elems;
+		__le16  sg_desc_stride;
+	};
+	__le32 words[478];
+};
+
 /**
  * struct ionic_lif_init_comp - LIF init command completion
  * @status: The status of the command (enum status_code)
@@ -2392,6 +2452,7 @@ union ionic_dev_cmd {
 	struct ionic_qos_init_cmd qos_init;
 	struct ionic_qos_reset_cmd qos_reset;
 
+	struct ionic_q_identify_cmd q_identify;
 	struct ionic_q_init_cmd q_init;
 	struct ionic_q_control_cmd q_control;
 };
@@ -2425,6 +2486,7 @@ union ionic_dev_cmd_comp {
 	ionic_qos_init_comp qos_init;
 	ionic_qos_reset_comp qos_reset;
 
+	struct ionic_q_identify_comp q_identify;
 	struct ionic_q_init_comp q_init;
 };
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 8/9] ionic: add basic eq support
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
                   ` (6 preceding siblings ...)
  2020-02-16 23:11 ` [PATCH net-next 7/9] ionic: add q ident query for eq Shannon Nelson
@ 2020-02-16 23:11 ` Shannon Nelson
  2020-02-16 23:11 ` [PATCH net-next 9/9] ionic: keep ionic dev on lif init fail Shannon Nelson
  2020-02-17  4:11 ` [PATCH net-next 0/9] ionic: Add support for Event Queues David Miller
  9 siblings, 0 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

Link the Event Queues into the driver setup and use them if
the NIC configuration has defined them.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
---
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 175 +++++++++++++-----
 .../net/ethernet/pensando/ionic/ionic_lif.h   |   1 +
 .../net/ethernet/pensando/ionic/ionic_txrx.c  |  63 +++++--
 .../net/ethernet/pensando/ionic/ionic_txrx.h  |   1 +
 4 files changed, 184 insertions(+), 56 deletions(-)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 9150cca06b77..85dfd76ff0c6 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -189,6 +189,7 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq)
 			.oper = IONIC_Q_ENABLE,
 		},
 	};
+	int ret;
 
 	idev = &lif->ionic->idev;
 	dev = lif->ionic->dev;
@@ -196,16 +197,29 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq)
 	dev_dbg(dev, "q_enable.index %d q_enable.qtype %d\n",
 		ctx.cmd.q_control.index, ctx.cmd.q_control.type);
 
-	if (qcq->flags & IONIC_QCQ_F_INTR) {
+	ret = ionic_adminq_post_wait(lif, &ctx);
+	if (ret)
+		return ret;
+
+	if (qcq->napi.poll)
+		napi_enable(&qcq->napi);
+
+	if (lif->ionic->neth_eqs) {
+		qcq->armed = true;
+		ionic_dbell_ring(lif->kern_dbpage,
+				 qcq->q.hw_type,
+				 IONIC_DBELL_RING_1 |
+				 IONIC_DBELL_QID(qcq->q.hw_index) |
+				 qcq->cq.tail->index);
+	} else if (qcq->flags & IONIC_QCQ_F_INTR) {
 		irq_set_affinity_hint(qcq->intr.vector,
 				      &qcq->intr.affinity_mask);
-		napi_enable(&qcq->napi);
 		ionic_intr_clean(idev->intr_ctrl, qcq->intr.index);
 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
 				IONIC_INTR_MASK_CLEAR);
 	}
 
-	return ionic_adminq_post_wait(lif, &ctx);
+	return 0;
 }
 
 static int ionic_qcq_disable(struct ionic_qcq *qcq)
@@ -232,12 +246,14 @@ static int ionic_qcq_disable(struct ionic_qcq *qcq)
 	dev_dbg(dev, "q_disable.index %d q_disable.qtype %d\n",
 		ctx.cmd.q_control.index, ctx.cmd.q_control.type);
 
+	if (qcq->napi.poll)
+		napi_disable(&qcq->napi);
+
 	if (qcq->flags & IONIC_QCQ_F_INTR) {
 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
 				IONIC_INTR_MASK_SET);
 		synchronize_irq(qcq->intr.vector);
 		irq_set_affinity_hint(qcq->intr.vector, NULL);
-		napi_disable(&qcq->napi);
 	}
 
 	return ionic_adminq_post_wait(lif, &ctx);
@@ -275,7 +291,6 @@ static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
 				IONIC_INTR_MASK_SET);
 		devm_free_irq(dev, qcq->intr.vector, &qcq->napi);
-		netif_napi_del(&qcq->napi);
 	}
 
 	qcq->flags &= ~IONIC_QCQ_F_INITED;
@@ -564,6 +579,11 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif)
 	return err;
 }
 
+static inline int ionic_choose_eq(struct ionic_lif *lif, int q_index)
+{
+	return q_index % lif->ionic->neth_eqs;
+}
+
 static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
 {
 	struct device *dev = lif->ionic->dev;
@@ -576,9 +596,6 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
 			.lif_index = cpu_to_le16(lif->index),
 			.type = q->type,
 			.index = cpu_to_le32(q->index),
-			.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
-					     IONIC_QINIT_F_SG),
-			.intr_index = cpu_to_le16(lif->rxqcqs[q->index].qcq->intr.index),
 			.pid = cpu_to_le16(q->pid),
 			.ring_size = ilog2(q->num_descs),
 			.ring_base = cpu_to_le64(q->base_pa),
@@ -588,6 +605,20 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
 	};
 	int err;
 
+	if (lif->ionic->neth_eqs) {
+		unsigned int eq_index = ionic_choose_eq(lif, q->index);
+
+		ctx.cmd.q_init.flags = cpu_to_le16(IONIC_QINIT_F_EQ |
+						   IONIC_QINIT_F_SG);
+		ctx.cmd.q_init.intr_index = cpu_to_le16(eq_index);
+	} else {
+		unsigned int intr_index = lif->rxqcqs[q->index].qcq->intr.index;
+
+		ctx.cmd.q_init.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
+						   IONIC_QINIT_F_SG);
+		ctx.cmd.q_init.intr_index = cpu_to_le16(intr_index);
+	}
+
 	dev_dbg(dev, "txq_init.pid %d\n", ctx.cmd.q_init.pid);
 	dev_dbg(dev, "txq_init.index %d\n", ctx.cmd.q_init.index);
 	dev_dbg(dev, "txq_init.ring_base 0x%llx\n", ctx.cmd.q_init.ring_base);
@@ -623,9 +654,6 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
 			.lif_index = cpu_to_le16(lif->index),
 			.type = q->type,
 			.index = cpu_to_le32(q->index),
-			.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
-					     IONIC_QINIT_F_SG),
-			.intr_index = cpu_to_le16(cq->bound_intr->index),
 			.pid = cpu_to_le16(q->pid),
 			.ring_size = ilog2(q->num_descs),
 			.ring_base = cpu_to_le64(q->base_pa),
@@ -635,6 +663,18 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
 	};
 	int err;
 
+	if (lif->ionic->neth_eqs) {
+		unsigned int eq_index = ionic_choose_eq(lif, q->index);
+
+		ctx.cmd.q_init.flags = cpu_to_le16(IONIC_QINIT_F_EQ |
+						   IONIC_QINIT_F_SG);
+		ctx.cmd.q_init.intr_index = cpu_to_le16(eq_index);
+	} else {
+		ctx.cmd.q_init.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
+						   IONIC_QINIT_F_SG);
+		ctx.cmd.q_init.intr_index = cpu_to_le16(cq->bound_intr->index);
+	}
+
 	dev_dbg(dev, "rxq_init.pid %d\n", ctx.cmd.q_init.pid);
 	dev_dbg(dev, "rxq_init.index %d\n", ctx.cmd.q_init.index);
 	dev_dbg(dev, "rxq_init.ring_base 0x%llx\n", ctx.cmd.q_init.ring_base);
@@ -654,10 +694,12 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
 	netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi,
 		       NAPI_POLL_WEIGHT);
 
-	err = ionic_request_napi_irq(lif, qcq);
-	if (err) {
-		netif_napi_del(&qcq->napi);
-		return err;
+	if (!lif->ionic->neth_eqs) {
+		err = ionic_request_napi_irq(lif, qcq);
+		if (err) {
+			netif_napi_del(&qcq->napi);
+			return err;
+		}
 	}
 
 	qcq->flags |= IONIC_QCQ_F_INITED;
@@ -1426,7 +1468,9 @@ static void ionic_txrx_deinit(struct ionic_lif *lif)
 	for (i = 0; i < lif->nxqs; i++) {
 		ionic_lif_qcq_deinit(lif, lif->txqcqs[i].qcq);
 		ionic_tx_flush(&lif->txqcqs[i].qcq->cq);
+		ionic_tx_empty(&lif->txqcqs[i].qcq->q);
 
+		netif_napi_del(&lif->rxqcqs[i].qcq->napi);
 		ionic_lif_qcq_deinit(lif, lif->rxqcqs[i].qcq);
 		ionic_rx_flush(&lif->rxqcqs[i].qcq->cq);
 		ionic_rx_empty(&lif->rxqcqs[i].qcq->q);
@@ -1466,7 +1510,10 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
 		lif->txqcqs[i].qcq->stats = lif->txqcqs[i].stats;
 	}
 
-	flags = IONIC_QCQ_F_RX_STATS | IONIC_QCQ_F_SG | IONIC_QCQ_F_INTR;
+	flags = IONIC_QCQ_F_RX_STATS | IONIC_QCQ_F_SG;
+	if (!lif->ionic->neth_eqs)
+		flags |= IONIC_QCQ_F_INTR;
+
 	for (i = 0; i < lif->nxqs; i++) {
 		err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags,
 				      lif->nrxq_descs,
@@ -1479,11 +1526,13 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
 
 		lif->rxqcqs[i].qcq->stats = lif->rxqcqs[i].stats;
 
-		ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
-				     lif->rxqcqs[i].qcq->intr.index,
-				     lif->rx_coalesce_hw);
-		ionic_link_qcq_interrupts(lif->rxqcqs[i].qcq,
-					  lif->txqcqs[i].qcq);
+		if (!lif->ionic->neth_eqs) {
+			ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
+					     lif->rxqcqs[i].qcq->intr.index,
+					     lif->rx_coalesce_hw);
+			ionic_link_qcq_interrupts(lif->rxqcqs[i].qcq,
+						  lif->txqcqs[i].qcq);
+		}
 	}
 
 	return 0;
@@ -1521,6 +1570,8 @@ static int ionic_txrx_init(struct ionic_lif *lif)
 err_out:
 	while (i--) {
 		ionic_lif_qcq_deinit(lif, lif->txqcqs[i].qcq);
+
+		netif_napi_del(&lif->rxqcqs[i].qcq->napi);
 		ionic_lif_qcq_deinit(lif, lif->rxqcqs[i].qcq);
 	}
 
@@ -2042,6 +2093,7 @@ static void ionic_lif_free(struct ionic_lif *lif)
 	/* free netdev & lif */
 	ionic_debugfs_del_lif(lif);
 	xa_erase(&ionic->lifs, lif->index);
+	lif->ionic->master_lif = NULL;
 	free_netdev(lif->netdev);
 }
 
@@ -2062,9 +2114,17 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
 	clear_bit(IONIC_LIF_INITED, lif->state);
 
 	ionic_rx_filters_deinit(lif);
-	ionic_lif_rss_deinit(lif);
+
+	if (is_master_lif(lif)) {
+		if (lif->netdev->features & NETIF_F_RXHASH)
+			ionic_lif_rss_deinit(lif);
+
+		ionic_eqs_deinit(lif->ionic);
+		ionic_eqs_free(lif->ionic);
+	}
 
 	napi_disable(&lif->adminqcq->napi);
+	netif_napi_del(&lif->adminqcq->napi);
 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
 
@@ -2228,12 +2288,11 @@ static int ionic_lif_init(struct ionic_lif *lif)
 {
 	struct ionic_dev *idev = &lif->ionic->idev;
 	struct device *dev = lif->ionic->dev;
+	struct ionic *ionic = lif->ionic;
 	struct ionic_lif_init_comp comp;
 	int dbpage_num;
 	int err;
 
-	ionic_debugfs_add_lif(lif);
-
 	mutex_lock(&lif->ionic->dev_cmd_lock);
 	ionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa);
 	err = ionic_dev_cmd_wait(lif->ionic, DEVCMD_TIMEOUT);
@@ -2269,6 +2328,23 @@ static int ionic_lif_init(struct ionic_lif *lif)
 		goto err_out_free_dbid;
 	}
 
+	if (is_master_lif(lif) && ionic->neth_eqs) {
+		err = ionic_eqs_alloc(ionic);
+		if (err) {
+			dev_err(dev, "Cannot allocate EQs: %d\n", err);
+			ionic->neth_eqs = 0;
+		} else {
+			err = ionic_eqs_init(ionic);
+			if (err) {
+				dev_err(dev, "Cannot init EQs: %d\n", err);
+				ionic_eqs_free(ionic);
+				ionic->neth_eqs = 0;
+			}
+		}
+	}
+
+	ionic_debugfs_add_lif(lif);
+
 	err = ionic_lif_adminq_init(lif);
 	if (err)
 		goto err_out_adminq_deinit;
@@ -2292,9 +2368,7 @@ static int ionic_lif_init(struct ionic_lif *lif)
 		goto err_out_notifyq_deinit;
 
 	lif->rx_copybreak = IONIC_RX_COPYBREAK_DEFAULT;
-
 	set_bit(IONIC_LIF_INITED, lif->state);
-
 	INIT_WORK(&lif->tx_timeout_work, ionic_tx_timeout_work);
 
 	return 0;
@@ -2303,9 +2377,8 @@ static int ionic_lif_init(struct ionic_lif *lif)
 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
 err_out_adminq_deinit:
 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
-	ionic_lif_reset(lif);
-	ionic_bus_unmap_dbpage(lif->ionic, lif->kern_dbpage);
-	lif->kern_dbpage = NULL;
+	ionic_eqs_deinit(lif->ionic);
+	ionic_eqs_free(lif->ionic);
 err_out_free_dbid:
 	kfree(lif->dbid_inuse);
 	lif->dbid_inuse = NULL;
@@ -2469,54 +2542,64 @@ int ionic_lifs_size(struct ionic *ionic)
 	unsigned int ntxqs_per_lif;
 	unsigned int nrxqs_per_lif;
 	unsigned int nnqs_per_lif;
+	unsigned int dev_neth_eqs;
 	unsigned int dev_nintrs;
-	unsigned int min_intrs;
 	unsigned int nrdma_eqs;
+	unsigned int neth_eqs;
 	unsigned int nintrs;
 	unsigned int nxqs;
 	int err;
 
 	lc = &ident->lif.eth.config;
 	dev_nintrs = le32_to_cpu(ident->dev.nintrs);
+	dev_neth_eqs = le32_to_cpu(ident->dev.eq_count);
+	if (dev_neth_eqs > IONIC_MAX_ETH_EQS)
+		dev_neth_eqs = 0; /* fix bogus value from old FW */
 	nrdma_eqs_per_lif = le32_to_cpu(ident->lif.rdma.eq_qtype.qid_count);
 	nnqs_per_lif = le32_to_cpu(lc->queue_count[IONIC_QTYPE_NOTIFYQ]);
 	ntxqs_per_lif = le32_to_cpu(lc->queue_count[IONIC_QTYPE_TXQ]);
 	nrxqs_per_lif = le32_to_cpu(lc->queue_count[IONIC_QTYPE_RXQ]);
 
+	/* limit TxRx queuepairs and RDMA event queues to num cpu */
 	nxqs = min(ntxqs_per_lif, nrxqs_per_lif);
 	nxqs = min(nxqs, num_online_cpus());
 	nrdma_eqs = min(nrdma_eqs_per_lif, num_online_cpus());
 
-try_again:
-	/* interrupt usage:
-	 *    1 for master lif adminq/notifyq
-	 *    1 for each CPU for master lif TxRx queue pairs
-	 *    whatever's left is for RDMA queues
+	neth_eqs = min(dev_neth_eqs, num_online_cpus());
+
+	/* EventQueue interrupt usage: (if eq_count != 0)
+	 *    1 aq intr + n EQs + m RDMA
+	 *
+	 * Default interrupt usage:
+	 *    1 aq intr + n TxRx intrs + m RDMA
 	 */
-	nintrs = 1 + nxqs + nrdma_eqs;
-	min_intrs = 2;  /* adminq + 1 TxRx queue pair */
+try_again:
+	if (neth_eqs)
+		nintrs = 1 + neth_eqs + nrdma_eqs;
+	else
+		nintrs = 1 + nxqs + nrdma_eqs;
 
 	if (nintrs > dev_nintrs)
 		goto try_fewer;
 
 	err = ionic_bus_alloc_irq_vectors(ionic, nintrs);
-	if (err < 0 && err != -ENOSPC) {
+	if (err == -ENOSPC) {
+		goto try_fewer;
+	} else if (err < 0) {
 		dev_err(ionic->dev, "Can't get intrs from OS: %d\n", err);
 		return err;
-	}
-	if (err == -ENOSPC)
-		goto try_fewer;
-
-	if (err != nintrs) {
+	} else if (err != nintrs) {
 		ionic_bus_free_irq_vectors(ionic);
 		goto try_fewer;
 	}
 
+	/* At this point we have the interrupts we need */
 	ionic->nnqs_per_lif = nnqs_per_lif;
 	ionic->nrdma_eqs_per_lif = nrdma_eqs;
 	ionic->ntxqs_per_lif = nxqs;
 	ionic->nrxqs_per_lif = nxqs;
 	ionic->nintrs = nintrs;
+	ionic->neth_eqs = neth_eqs;
 
 	ionic_debugfs_add_sizes(ionic);
 
@@ -2531,10 +2614,14 @@ int ionic_lifs_size(struct ionic *ionic)
 		nrdma_eqs >>= 1;
 		goto try_again;
 	}
+	if (neth_eqs > 1) {
+		neth_eqs >>= 1;
+		goto try_again;
+	}
 	if (nxqs > 1) {
 		nxqs >>= 1;
 		goto try_again;
 	}
-	dev_err(ionic->dev, "Can't get minimum %d intrs from OS\n", min_intrs);
+	dev_err(ionic->dev, "Can't get minimum intrs from OS\n");
 	return -ENOSPC;
 }
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
index bb9202a10ac1..25423332f028 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -189,6 +189,7 @@ struct ionic_lif {
 #define lif_to_rxstats(lif, i)	((lif)->rxqcqs[i].stats->rx)
 #define lif_to_txq(lif, i)	(&lif_to_txqcq((lif), i)->q)
 #define lif_to_rxq(lif, i)	(&lif_to_txqcq((lif), i)->q)
+#define is_master_lif(lif)	((lif)->index == 0)
 
 /* return 0 if successfully set the bit, else non-zero */
 static inline int ionic_wait_for_bit(struct ionic_lif *lif, int bitname)
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
index e452f4242ba0..e860fb199ef3 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
@@ -274,7 +274,7 @@ void ionic_rx_flush(struct ionic_cq *cq)
 
 	work_done = ionic_rx_walk_cq(cq, cq->num_descs);
 
-	if (work_done)
+	if (work_done && !cq->lif->ionic->neth_eqs)
 		ionic_intr_credits(idev->intr_ctrl, cq->bound_intr->index,
 				   work_done, IONIC_INTR_CRED_RESET_COALESCE);
 }
@@ -439,9 +439,10 @@ void ionic_rx_empty(struct ionic_queue *q)
 
 int ionic_rx_napi(struct napi_struct *napi, int budget)
 {
-	struct ionic_qcq *qcq = napi_to_qcq(napi);
+	struct ionic_qcq *rxqcq = napi_to_qcq(napi);
 	struct ionic_cq *rxcq = napi_to_cq(napi);
 	unsigned int qi = rxcq->bound_q->index;
+	struct ionic_qcq *txqcq;
 	struct ionic_dev *idev;
 	struct ionic_lif *lif;
 	struct ionic_cq *txcq;
@@ -450,12 +451,12 @@ int ionic_rx_napi(struct napi_struct *napi, int budget)
 
 	lif = rxcq->bound_q->lif;
 	idev = &lif->ionic->idev;
+	txqcq = lif->txqcqs[qi].qcq;
 	txcq = &lif->txqcqs[qi].qcq->cq;
 
 	ionic_tx_flush(txcq);
 
 	work_done = ionic_rx_walk_cq(rxcq, budget);
-
 	if (work_done)
 		ionic_rx_fill_cb(rxcq->bound_q);
 
@@ -466,11 +467,33 @@ int ionic_rx_napi(struct napi_struct *napi, int budget)
 
 	if (work_done || flags) {
 		flags |= IONIC_INTR_CRED_RESET_COALESCE;
-		ionic_intr_credits(idev->intr_ctrl, rxcq->bound_intr->index,
-				   work_done, flags);
+		if (!lif->ionic->neth_eqs) {
+			ionic_intr_credits(idev->intr_ctrl,
+					   rxcq->bound_intr->index,
+					   work_done, flags);
+		} else {
+			u64 dbr;
+
+			if (!rxqcq->armed) {
+				rxqcq->armed = true;
+				dbr = IONIC_DBELL_RING_1 |
+				      IONIC_DBELL_QID(rxqcq->q.hw_index);
+				ionic_dbell_ring(lif->kern_dbpage,
+						 rxqcq->q.hw_type,
+						 dbr | rxqcq->cq.tail->index);
+			}
+			if (!txqcq->armed) {
+				txqcq->armed = true;
+				dbr = IONIC_DBELL_RING_1 |
+				      IONIC_DBELL_QID(txqcq->q.hw_index);
+				ionic_dbell_ring(lif->kern_dbpage,
+						 txqcq->q.hw_type,
+						 dbr | txqcq->cq.tail->index);
+			}
+		}
 	}
 
-	DEBUG_STATS_NAPI_POLL(qcq, work_done);
+	DEBUG_STATS_NAPI_POLL(rxqcq, work_done);
 
 	return work_done;
 }
@@ -516,7 +539,6 @@ static void ionic_tx_clean(struct ionic_queue *q, struct ionic_desc_info *desc_i
 	struct ionic_txq_desc *desc = desc_info->desc;
 	struct device *dev = q->lif->ionic->dev;
 	u8 opcode, flags, nsge;
-	u16 queue_index;
 	unsigned int i;
 	u64 addr;
 
@@ -541,11 +563,12 @@ static void ionic_tx_clean(struct ionic_queue *q, struct ionic_desc_info *desc_i
 	if (cb_arg) {
 		struct sk_buff *skb = cb_arg;
 		u32 len = skb->len;
+		u16 qi;
 
-		queue_index = skb_get_queue_mapping(skb);
-		if (unlikely(__netif_subqueue_stopped(q->lif->netdev,
-						      queue_index))) {
-			netif_wake_subqueue(q->lif->netdev, queue_index);
+		qi = skb_get_queue_mapping(skb);
+		if (unlikely(__netif_subqueue_stopped(q->lif->netdev, qi) &&
+			     cq_info)) {
+			netif_wake_subqueue(q->lif->netdev, qi);
 			q->wake++;
 		}
 		dev_kfree_skb_any(skb);
@@ -588,11 +611,27 @@ void ionic_tx_flush(struct ionic_cq *cq)
 		work_done++;
 	}
 
-	if (work_done)
+	if (work_done && !cq->lif->ionic->neth_eqs)
 		ionic_intr_credits(idev->intr_ctrl, cq->bound_intr->index,
 				   work_done, 0);
 }
 
+void ionic_tx_empty(struct ionic_queue *q)
+{
+	struct ionic_desc_info *desc_info;
+	int done = 0;
+
+	/* walk the not completed tx entries, if any */
+	while (q->head != q->tail) {
+		desc_info = q->tail;
+		q->tail = desc_info->next;
+		ionic_tx_clean(q, desc_info, NULL, desc_info->cb_arg);
+		desc_info->cb = NULL;
+		desc_info->cb_arg = NULL;
+		done++;
+	}
+}
+
 static int ionic_tx_tcp_inner_pseudo_csum(struct sk_buff *skb)
 {
 	int err;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.h b/drivers/net/ethernet/pensando/ionic/ionic_txrx.h
index 53775c62c85a..71973e3c35a6 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.h
@@ -9,6 +9,7 @@ void ionic_tx_flush(struct ionic_cq *cq);
 
 void ionic_rx_fill(struct ionic_queue *q);
 void ionic_rx_empty(struct ionic_queue *q);
+void ionic_tx_empty(struct ionic_queue *q);
 int ionic_rx_napi(struct napi_struct *napi, int budget);
 netdev_tx_t ionic_start_xmit(struct sk_buff *skb, struct net_device *netdev);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 9/9] ionic: keep ionic dev on lif init fail
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
                   ` (7 preceding siblings ...)
  2020-02-16 23:11 ` [PATCH net-next 8/9] ionic: add basic eq support Shannon Nelson
@ 2020-02-16 23:11 ` Shannon Nelson
  2020-02-17  4:11 ` [PATCH net-next 0/9] ionic: Add support for Event Queues David Miller
  9 siblings, 0 replies; 15+ messages in thread
From: Shannon Nelson @ 2020-02-16 23:11 UTC (permalink / raw)
  To: davem, netdev; +Cc: Shannon Nelson

If the basic ionic interface works but the lif creation fails,
don't fail the probe.  This will allow us to use the driver to
help inspect the hw/fw/pci interface for debugging purposes.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
---
 drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c | 8 ++++++++
 drivers/net/ethernet/pensando/ionic/ionic_lif.c     | 3 +++
 2 files changed, 11 insertions(+)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
index 448d7b23b2f7..554bafac1147 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
@@ -37,6 +37,9 @@ int ionic_bus_alloc_irq_vectors(struct ionic *ionic, unsigned int nintrs)
 
 void ionic_bus_free_irq_vectors(struct ionic *ionic)
 {
+	if (!ionic->nintrs)
+		return;
+
 	pci_free_irq_vectors(ionic->pdev);
 }
 
@@ -346,6 +349,11 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	ionic_reset(ionic);
 err_out_teardown:
 	ionic_dev_teardown(ionic);
+	/* Don't fail the probe for these errors, keep
+	 * the hw interface around for inspection
+	 */
+	return 0;
+
 err_out_unmap_bars:
 	ionic_unmap_bars(ionic);
 	pci_release_regions(pdev);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 85dfd76ff0c6..a6fd6aa4ce40 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -2486,6 +2486,9 @@ void ionic_lifs_unregister(struct ionic *ionic)
 	 * current model, so don't bother searching the
 	 * ionic->lif for candidates to unregister
 	 */
+	if (!ionic->master_lif)
+		return;
+
 	cancel_work_sync(&ionic->master_lif->deferred.work);
 	cancel_work_sync(&ionic->master_lif->tx_timeout_work);
 	if (ionic->master_lif->netdev->reg_state == NETREG_REGISTERED)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 0/9] ionic: Add support for Event Queues
  2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
                   ` (8 preceding siblings ...)
  2020-02-16 23:11 ` [PATCH net-next 9/9] ionic: keep ionic dev on lif init fail Shannon Nelson
@ 2020-02-17  4:11 ` David Miller
  2020-02-17  6:55   ` Shannon Nelson
  9 siblings, 1 reply; 15+ messages in thread
From: David Miller @ 2020-02-17  4:11 UTC (permalink / raw)
  To: snelson; +Cc: netdev

From: Shannon Nelson <snelson@pensando.io>
Date: Sun, 16 Feb 2020 15:11:49 -0800

> This patchset adds a new EventQueue feature that can be used
> for multiplexing the interrupts if we find that we can't get
> enough from the system to support our configuration.  We can
> create a small number of EQs that use interrupts, and have
> the TxRx queue pairs subscribe to event messages that come
> through the EQs, selecting an EQ with (TxIndex % numEqs).

How is a user going to be able to figure out how to direct
traffic to specific cpus using multiqueue settings if you're
going to have the mapping go through this custom muxing
afterwards?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 0/9] ionic: Add support for Event Queues
  2020-02-17  4:11 ` [PATCH net-next 0/9] ionic: Add support for Event Queues David Miller
@ 2020-02-17  6:55   ` Shannon Nelson
  2020-02-17 22:03     ` David Miller
  0 siblings, 1 reply; 15+ messages in thread
From: Shannon Nelson @ 2020-02-17  6:55 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

On 2/16/20 8:11 PM, David Miller wrote:
> From: Shannon Nelson <snelson@pensando.io>
> Date: Sun, 16 Feb 2020 15:11:49 -0800
>
>> This patchset adds a new EventQueue feature that can be used
>> for multiplexing the interrupts if we find that we can't get
>> enough from the system to support our configuration.  We can
>> create a small number of EQs that use interrupts, and have
>> the TxRx queue pairs subscribe to event messages that come
>> through the EQs, selecting an EQ with (TxIndex % numEqs).
> How is a user going to be able to figure out how to direct
> traffic to specific cpus using multiqueue settings if you're
> going to have the mapping go through this custom muxing
> afterwards?

When using the EQ feature, the TxRx are assigned to the EventQueues in a 
straight round-robin, so the layout is predictable.  I suppose we could 
have a way to print out the TxRx -> EQ -> Irq mappings, but I'm not sure 
where we would put such a thing.

sln


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 0/9] ionic: Add support for Event Queues
  2020-02-17  6:55   ` Shannon Nelson
@ 2020-02-17 22:03     ` David Miller
  2020-02-18 16:16       ` Shannon Nelson
  0 siblings, 1 reply; 15+ messages in thread
From: David Miller @ 2020-02-17 22:03 UTC (permalink / raw)
  To: snelson; +Cc: netdev

From: Shannon Nelson <snelson@pensando.io>
Date: Sun, 16 Feb 2020 22:55:22 -0800

> On 2/16/20 8:11 PM, David Miller wrote:
>> From: Shannon Nelson <snelson@pensando.io>
>> Date: Sun, 16 Feb 2020 15:11:49 -0800
>>
>>> This patchset adds a new EventQueue feature that can be used
>>> for multiplexing the interrupts if we find that we can't get
>>> enough from the system to support our configuration.  We can
>>> create a small number of EQs that use interrupts, and have
>>> the TxRx queue pairs subscribe to event messages that come
>>> through the EQs, selecting an EQ with (TxIndex % numEqs).
>> How is a user going to be able to figure out how to direct
>> traffic to specific cpus using multiqueue settings if you're
>> going to have the mapping go through this custom muxing
>> afterwards?
> 
> When using the EQ feature, the TxRx are assigned to the EventQueues in
> a straight round-robin, so the layout is predictable.  I suppose we
> could have a way to print out the TxRx -> EQ -> Irq mappings, but I'm
> not sure where we would put such a thing.

No user is going to know this and it's completely inconsistent with how
other multiqueue networking devices behave.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 0/9] ionic: Add support for Event Queues
  2020-02-17 22:03     ` David Miller
@ 2020-02-18 16:16       ` Shannon Nelson
  2020-02-18 20:33         ` David Miller
  0 siblings, 1 reply; 15+ messages in thread
From: Shannon Nelson @ 2020-02-18 16:16 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

On 2/17/20 2:03 PM, David Miller wrote:
> From: Shannon Nelson <snelson@pensando.io>
> Date: Sun, 16 Feb 2020 22:55:22 -0800
>
>> On 2/16/20 8:11 PM, David Miller wrote:
>>> From: Shannon Nelson <snelson@pensando.io>
>>> Date: Sun, 16 Feb 2020 15:11:49 -0800
>>>
>>>> This patchset adds a new EventQueue feature that can be used
>>>> for multiplexing the interrupts if we find that we can't get
>>>> enough from the system to support our configuration.  We can
>>>> create a small number of EQs that use interrupts, and have
>>>> the TxRx queue pairs subscribe to event messages that come
>>>> through the EQs, selecting an EQ with (TxIndex % numEqs).
>>> How is a user going to be able to figure out how to direct
>>> traffic to specific cpus using multiqueue settings if you're
>>> going to have the mapping go through this custom muxing
>>> afterwards?
>> When using the EQ feature, the TxRx are assigned to the EventQueues in
>> a straight round-robin, so the layout is predictable.  I suppose we
>> could have a way to print out the TxRx -> EQ -> Irq mappings, but I'm
>> not sure where we would put such a thing.
> No user is going to know this and it's completely inconsistent with how
> other multiqueue networking devices behave.

The ionic's main RSS set is limited to number of cpus, so that in normal 
use we remain consistent with other drivers.  With no additional 
configuration, this is the standard behavior, as expected, so most users 
won't need to know or care.

We have a FW configuration option that can be chosen by the customer to 
make use of the much larger set of queues that we have available.  This 
keeps the RSS set limited to the cpu count or less, keeping normal use 
consistent, and makes additional queues available for macvlan offload 
use.  Depending on the customer's configuration, this can be 100's of 
queues, which seems excessive, but we have been given use-cases for 
them.  In these cases, the queues will be wrapped around the vectors 
available with the customer's use case. This is similar to the Intel 
i40e's support for macvlan offload which can also end up wrapping 
around, but they have the number of offload channels constrained to a 
much smaller number.

(BTW, with the ixgbe we can do an ethtool set_channel to get more queues 
than vectors on the PF, which will end up up wrapping the queues around 
the vectors allocated.  Not extremely useful perhaps, but possible.)

We don't have support for the macvlan offload in this upstream driver 
yet, but this patchset allows us to play nicely with that FW configuration.

sln


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 0/9] ionic: Add support for Event Queues
  2020-02-18 16:16       ` Shannon Nelson
@ 2020-02-18 20:33         ` David Miller
  0 siblings, 0 replies; 15+ messages in thread
From: David Miller @ 2020-02-18 20:33 UTC (permalink / raw)
  To: snelson; +Cc: netdev

From: Shannon Nelson <snelson@pensando.io>
Date: Tue, 18 Feb 2020 08:16:43 -0800

> and makes additional queues available for macvlan offload use
 ...
> We don't have support for the macvlan offload in this upstream driver
> yet, but this patchset allows us to play nicely with that FW
> configuration.

Translation: this entire patch set is useless upstream

Make your driver consistent and add support for things that
actually are usable.

I'm not applying this, sorry.

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-02-18 20:33 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-16 23:11 [PATCH net-next 0/9] ionic: Add support for Event Queues Shannon Nelson
2020-02-16 23:11 ` [PATCH net-next 1/9] ionic: change param from lif to ionic Shannon Nelson
2020-02-16 23:11 ` [PATCH net-next 2/9] ionic: rename rdma eqs field Shannon Nelson
2020-02-16 23:11 ` [PATCH net-next 3/9] ionic: replace lif list with xarray Shannon Nelson
2020-02-16 23:11 ` [PATCH net-next 4/9] ionic: add event queue definitions to hw interface Shannon Nelson
2020-02-16 23:11 ` [PATCH net-next 5/9] ionic: rename napi irq functions Shannon Nelson
2020-02-16 23:11 ` [PATCH net-next 6/9] ionic: add functions for setup and tear down event queues Shannon Nelson
2020-02-16 23:11 ` [PATCH net-next 7/9] ionic: add q ident query for eq Shannon Nelson
2020-02-16 23:11 ` [PATCH net-next 8/9] ionic: add basic eq support Shannon Nelson
2020-02-16 23:11 ` [PATCH net-next 9/9] ionic: keep ionic dev on lif init fail Shannon Nelson
2020-02-17  4:11 ` [PATCH net-next 0/9] ionic: Add support for Event Queues David Miller
2020-02-17  6:55   ` Shannon Nelson
2020-02-17 22:03     ` David Miller
2020-02-18 16:16       ` Shannon Nelson
2020-02-18 20:33         ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.