Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Oct 2015 02:14:45 +0000 (UTC)
From:      "Conrad E. Meyer" <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r289281 - in head/sys/dev/ntb: if_ntb ntb_hw
Message-ID:  <201510140214.t9E2EjPe059361@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Wed Oct 14 02:14:45 2015
New Revision: 289281
URL: https://svnweb.freebsd.org/changeset/base/289281

Log:
  NTB: MFV e8aeb60c: Disable interrupts and poll under high load
  
  Authored by:	Jon Mason
  Obtained from:	Linux (Dual BSD/GPL driver)
  Sponsored by:	EMC / Isilon Storage Division

Modified:
  head/sys/dev/ntb/if_ntb/if_ntb.c
  head/sys/dev/ntb/ntb_hw/ntb_hw.c
  head/sys/dev/ntb/ntb_hw/ntb_hw.h

Modified: head/sys/dev/ntb/if_ntb/if_ntb.c
==============================================================================
--- head/sys/dev/ntb/if_ntb/if_ntb.c	Wed Oct 14 02:14:15 2015	(r289280)
+++ head/sys/dev/ntb/if_ntb/if_ntb.c	Wed Oct 14 02:14:45 2015	(r289281)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/ktr.h>
+#include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
@@ -249,9 +250,8 @@ static int ntb_process_tx(struct ntb_tra
 static void ntb_tx_copy_task(struct ntb_transport_qp *qp,
     struct ntb_queue_entry *entry, void *offset);
 static void ntb_qp_full(void *arg);
-static void ntb_transport_rxc_db(void *data, int db_num);
+static int ntb_transport_rxc_db(void *arg, int dummy);
 static void ntb_rx_pendq_full(void *arg);
-static void ntb_transport_rx(struct ntb_transport_qp *qp);
 static int ntb_process_rxc(struct ntb_transport_qp *qp);
 static void ntb_rx_copy_task(struct ntb_transport_qp *qp,
     struct ntb_queue_entry *entry, void *offset);
@@ -840,24 +840,17 @@ ntb_qp_full(void *arg)
 
 /* Transport Rx */
 static void
-ntb_transport_rxc_db(void *data, int db_num)
-{
-	struct ntb_transport_qp *qp = data;
-
-	ntb_transport_rx(qp);
-}
-
-static void
 ntb_rx_pendq_full(void *arg)
 {
 
 	CTR0(KTR_NTB, "RX: ntb_rx_pendq_full callout");
-	ntb_transport_rx(arg);
+	ntb_transport_rxc_db(arg, 0);
 }
 
-static void
-ntb_transport_rx(struct ntb_transport_qp *qp)
+static int
+ntb_transport_rxc_db(void *arg, int dummy __unused)
 {
+	struct ntb_transport_qp *qp = arg;
 	uint64_t i;
 	int rc;
 
@@ -867,7 +860,7 @@ ntb_transport_rx(struct ntb_transport_qp
 	 */
 	mtx_lock(&qp->transport->rx_lock);
 	CTR0(KTR_NTB, "RX: transport_rx");
-	for (i = 0; i < qp->rx_max_entry; i++) {
+	for (i = 0; i < MIN(qp->rx_max_entry, INT_MAX); i++) {
 		rc = ntb_process_rxc(qp);
 		if (rc != 0) {
 			CTR0(KTR_NTB, "RX: process_rxc failed");
@@ -875,6 +868,8 @@ ntb_transport_rx(struct ntb_transport_qp
 		}
 	}
 	mtx_unlock(&qp->transport->rx_lock);
+
+	return ((int)i);
 }
 
 static int

Modified: head/sys/dev/ntb/ntb_hw/ntb_hw.c
==============================================================================
--- head/sys/dev/ntb/ntb_hw/ntb_hw.c	Wed Oct 14 02:14:15 2015	(r289280)
+++ head/sys/dev/ntb/ntb_hw/ntb_hw.c	Wed Oct 14 02:14:45 2015	(r289281)
@@ -109,6 +109,7 @@ struct ntb_db_cb {
 	unsigned int		db_num;
 	void			*data;
 	struct ntb_softc	*ntb;
+	struct callout		irq_work;
 };
 
 struct ntb_softc {
@@ -204,6 +205,9 @@ static void handle_soc_irq(void *arg);
 static void handle_xeon_irq(void *arg);
 static void handle_xeon_event_irq(void *arg);
 static void ntb_handle_legacy_interrupt(void *arg);
+static void ntb_irq_work(void *arg);
+static void mask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx);
+static void unmask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx);
 static int ntb_create_callbacks(struct ntb_softc *ntb, int num_vectors);
 static void ntb_free_callbacks(struct ntb_softc *ntb);
 static struct ntb_hw_info *ntb_get_device_info(uint32_t device_id);
@@ -580,6 +584,26 @@ ntb_teardown_interrupts(struct ntb_softc
 }
 
 static void
+mask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx)
+{
+	unsigned long mask;
+
+	mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask);
+	mask |= 1 << (idx * ntb->bits_per_vector);
+	ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask);
+}
+
+static void
+unmask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx)
+{
+	unsigned long mask;
+
+	mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask);
+	mask &= ~(1 << (idx * ntb->bits_per_vector));
+	ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask);
+}
+
+static void
 handle_soc_irq(void *arg)
 {
 	struct ntb_db_cb *db_cb = arg;
@@ -587,8 +611,10 @@ handle_soc_irq(void *arg)
 
 	ntb_reg_write(8, ntb->reg_ofs.ldb, (uint64_t) 1 << db_cb->db_num);
 
-	if (db_cb->callback != NULL)
-		db_cb->callback(db_cb->data, db_cb->db_num);
+	if (db_cb->callback != NULL) {
+		mask_ldb_interrupt(ntb, db_cb->db_num);
+		callout_reset(&db_cb->irq_work, 0, ntb_irq_work, db_cb);
+	}
 }
 
 static void
@@ -607,8 +633,10 @@ handle_xeon_irq(void *arg)
 	    ((1 << ntb->bits_per_vector) - 1) <<
 	    (db_cb->db_num * ntb->bits_per_vector));
 
-	if (db_cb->callback != NULL)
-		db_cb->callback(db_cb->data, db_cb->db_num);
+	if (db_cb->callback != NULL) {
+		mask_ldb_interrupt(ntb, db_cb->db_num);
+		callout_reset(&db_cb->irq_work, 0, ntb_irq_work, db_cb);
+	}
 }
 
 /* Since we do not have a HW doorbell in SOC, this is only used in JF/JT */
@@ -1191,6 +1219,25 @@ ntb_unregister_event_callback(struct ntb
 	ntb->event_cb = NULL;
 }
 
+static void
+ntb_irq_work(void *arg)
+{
+	struct ntb_db_cb *db_cb = arg;
+	struct ntb_softc *ntb;
+	int rc;
+
+	rc = db_cb->callback(db_cb->data, db_cb->db_num);
+	/* Poll if forward progress was made. */
+	if (rc != 0) {
+		callout_reset(&db_cb->irq_work, 0, ntb_irq_work, db_cb);
+		return;
+	}
+
+	/* Unmask interrupt if no progress was made. */
+	ntb = db_cb->ntb;
+	unmask_ldb_interrupt(ntb, db_cb->db_num);
+}
+
 /**
  * ntb_register_db_callback() - register a callback for doorbell interrupt
  * @ntb: pointer to ntb_softc instance
@@ -1208,7 +1255,6 @@ int
 ntb_register_db_callback(struct ntb_softc *ntb, unsigned int idx, void *data,
     ntb_db_callback func)
 {
-	uint16_t mask;
 
 	if (idx >= ntb->allocated_interrupts || ntb->db_cb[idx].callback) {
 		device_printf(ntb->device, "Invalid Index.\n");
@@ -1217,11 +1263,9 @@ ntb_register_db_callback(struct ntb_soft
 
 	ntb->db_cb[idx].callback = func;
 	ntb->db_cb[idx].data = data;
+	callout_init(&ntb->db_cb[idx].irq_work, 1);
 
-	/* unmask interrupt */
-	mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask);
-	mask &= ~(1 << (idx * ntb->bits_per_vector));
-	ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask);
+	unmask_ldb_interrupt(ntb, idx);
 
 	return (0);
 }
@@ -1237,15 +1281,13 @@ ntb_register_db_callback(struct ntb_soft
 void
 ntb_unregister_db_callback(struct ntb_softc *ntb, unsigned int idx)
 {
-	unsigned long mask;
 
 	if (idx >= ntb->allocated_interrupts || !ntb->db_cb[idx].callback)
 		return;
 
-	mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask);
-	mask |= 1 << (idx * ntb->bits_per_vector);
-	ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask);
+	mask_ldb_interrupt(ntb, idx);
 
+	callout_drain(&ntb->db_cb[idx].irq_work);
 	ntb->db_cb[idx].callback = NULL;
 }
 

Modified: head/sys/dev/ntb/ntb_hw/ntb_hw.h
==============================================================================
--- head/sys/dev/ntb/ntb_hw/ntb_hw.h	Wed Oct 14 02:14:15 2015	(r289280)
+++ head/sys/dev/ntb/ntb_hw/ntb_hw.h	Wed Oct 14 02:14:45 2015	(r289281)
@@ -46,7 +46,7 @@ enum ntb_hw_event {
 
 SYSCTL_DECL(_hw_ntb);
 
-typedef void (*ntb_db_callback)(void *data, int db_num);
+typedef int (*ntb_db_callback)(void *data, int db_num);
 typedef void (*ntb_event_callback)(void *data, enum ntb_hw_event event);
 
 int ntb_register_event_callback(struct ntb_softc *ntb, ntb_event_callback func);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201510140214.t9E2EjPe059361>