svn commit: r219286 - head/sys/dev/cxgbe

Navdeep Parhar np at FreeBSD.org
Sat Mar 5 03:06:39 UTC 2011


Author: np
Date: Sat Mar  5 03:06:38 2011
New Revision: 219286
URL: http://svn.freebsd.org/changeset/base/219286

Log:
  Resume tx immediately in response to an SGE egress update from the hardware.
  
  MFC after:	1 week

Modified:
  head/sys/dev/cxgbe/adapter.h
  head/sys/dev/cxgbe/t4_main.c
  head/sys/dev/cxgbe/t4_sge.c

Modified: head/sys/dev/cxgbe/adapter.h
==============================================================================
--- head/sys/dev/cxgbe/adapter.h	Sat Mar  5 03:01:14 2011	(r219285)
+++ head/sys/dev/cxgbe/adapter.h	Sat Mar  5 03:06:38 2011	(r219286)
@@ -177,6 +177,7 @@ struct port_info {
 	struct link_config link_cfg;
 	struct port_stats stats;
 
+	struct taskqueue *tq;
 	struct callout tick;
 	struct sysctl_ctx_list ctx;	/* lives from ifconfig up to down */
 	struct sysctl_oid *oid_rxq;
@@ -310,6 +311,9 @@ struct sge_fl {
 struct sge_txq {
 	struct sge_eq eq;	/* MUST be first */
 	struct mbuf *m;		/* held up due to temporary resource shortage */
+	struct task resume_tx;
+
+	struct port_info *port;	/* the port this txq belongs to */
 
 	/* stats for common events first */
 
@@ -545,13 +549,15 @@ static inline bool is_10G_port(const str
 	return ((pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G) != 0);
 }
 
+/* t4_main.c */
+void cxgbe_txq_start(void *, int);
 int t4_os_find_pci_capability(struct adapter *, int);
 int t4_os_pci_save_state(struct adapter *);
 int t4_os_pci_restore_state(struct adapter *);
-
 void t4_os_portmod_changed(const struct adapter *, int);
 void t4_os_link_changed(struct adapter *, int, int);
 
+/* t4_sge.c */
 void t4_sge_init(struct adapter *);
 int t4_create_dma_tag(struct adapter *);
 int t4_destroy_dma_tag(struct adapter *);

Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c	Sat Mar  5 03:01:14 2011	(r219285)
+++ head/sys/dev/cxgbe/t4_main.c	Sat Mar  5 03:06:38 2011	(r219286)
@@ -36,6 +36,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/bus.h>
 #include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
 #include <sys/pciio.h>
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
@@ -274,6 +277,7 @@ static int sysctl_holdoff_pktc_idx(SYSCT
 static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS);
 static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS);
 static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS);
+static inline void txq_start(struct ifnet *, struct sge_txq *);
 
 
 struct t4_pciids {
@@ -692,6 +696,15 @@ cxgbe_attach(device_t dev)
 	ifp->if_softc = pi;
 
 	callout_init(&pi->tick, CALLOUT_MPSAFE);
+	pi->tq = taskqueue_create("cxgbe_taskq", M_NOWAIT,
+	    taskqueue_thread_enqueue, &pi->tq);
+	if (pi->tq == NULL) {
+		device_printf(dev, "failed to allocate port task queue\n");
+		if_free(pi->ifp);
+		return (ENOMEM);
+	}
+	taskqueue_start_threads(&pi->tq, 1, PI_NET, "%s taskq",
+	    device_get_nameunit(dev));
 
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
@@ -746,6 +759,8 @@ cxgbe_detach(device_t dev)
 	if (rc != 0)
 		device_printf(dev, "port uninit failed: %d.\n", rc);
 
+	taskqueue_free(pi->tq);
+
 	ifmedia_removeall(&pi->media);
 	ether_ifdetach(pi->ifp);
 	if_free(pi->ifp);
@@ -951,13 +966,7 @@ cxgbe_start(struct ifnet *ifp)
 
 	for_each_txq(pi, i, txq) {
 		if (TXQ_TRYLOCK(txq)) {
-			struct buf_ring *br = txq->eq.br;
-			struct mbuf *m;
-
-			m = txq->m ? txq->m : drbr_dequeue(ifp, br);
-			if (m)
-				t4_eth_tx(ifp, txq, m);
-
+			txq_start(ifp, txq);
 			TXQ_UNLOCK(txq);
 		}
 	}
@@ -2581,6 +2590,31 @@ sysctl_handle_t4_reg64(SYSCTL_HANDLER_AR
 	return (sysctl_handle_64(oidp, &val, 0, req));
 }
 
+static inline void
+txq_start(struct ifnet *ifp, struct sge_txq *txq)
+{
+	struct buf_ring *br;
+	struct mbuf *m;
+
+	TXQ_LOCK_ASSERT_OWNED(txq);
+
+	br = txq->eq.br;
+	m = txq->m ? txq->m : drbr_dequeue(ifp, br);
+	if (m)
+		t4_eth_tx(ifp, txq, m);
+}
+
+void
+cxgbe_txq_start(void *arg, int count)
+{
+	struct sge_txq *txq = arg;
+	struct ifnet *ifp = txq->port->ifp;
+
+	TXQ_LOCK(txq);
+	txq_start(ifp, txq);
+	TXQ_UNLOCK(txq);
+}
+
 int
 t4_os_find_pci_capability(struct adapter *sc, int cap)
 {

Modified: head/sys/dev/cxgbe/t4_sge.c
==============================================================================
--- head/sys/dev/cxgbe/t4_sge.c	Sat Mar  5 03:01:14 2011	(r219285)
+++ head/sys/dev/cxgbe/t4_sge.c	Sat Mar  5 03:06:38 2011	(r219286)
@@ -34,6 +34,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/mbuf.h>
 #include <sys/socket.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
 #include <sys/sysctl.h>
 #include <net/bpf.h>
 #include <net/ethernet.h>
@@ -136,6 +139,8 @@ static inline void ring_tx_db(struct ada
 static int reclaim_tx_descs(struct sge_eq *, int, int);
 static void write_eqflush_wr(struct sge_eq *);
 static __be64 get_flit(bus_dma_segment_t *, int, int);
+static int handle_sge_egr_update(struct adapter *,
+    const struct cpl_sge_egr_update *);
 
 /**
  *	t4_sge_init - initialize SGE
@@ -492,21 +497,9 @@ t4_intr_evt(void *arg)
 
 			break;
 			}
-		case CPL_SGE_EGR_UPDATE: {
-			const struct cpl_sge_egr_update *cpl;
-			unsigned int qid;
-			struct sge *s = &sc->sge;
-			struct sge_txq *txq;
-
-			cpl = (const void *)(rss + 1);
-			qid = G_EGR_QID(ntohl(cpl->opcode_qid));
-			txq = (void *)s->eqmap[qid - s->eq_start];
-			txq->egr_update++;
-
-			/* XXX: wake up stalled tx */
-
+		case CPL_SGE_EGR_UPDATE:
+			handle_sge_egr_update(sc, (const void *)(rss + 1));
 			break;
-			}
 
 		default:
 			device_printf(sc->dev,
@@ -565,20 +558,9 @@ t4_intr_data(void *arg)
 		rsp_type = G_RSPD_TYPE(ctrl->u.type_gen);
 
 		if (__predict_false(rsp_type == X_RSPD_TYPE_CPL)) {
-			const struct cpl_sge_egr_update *p = (const void *)cpl;
-			unsigned int qid = G_EGR_QID(ntohl(p->opcode_qid));
-
-			KASSERT(cpl->opcode == CPL_SGE_EGR_UPDATE,
-			    ("unexpected opcode on data ingress queue: %x",
-			    cpl->opcode));
-
-			/* XXX: noone's waiting to be woken up... */
-			wakeup(sc->sge.eqmap[qid - sc->sge.eq_start]);
-
-			ndescs++;
-			iq_next(iq);
-
-			continue;
+			/* Can't be anything except an egress update */
+			handle_sge_egr_update(sc, (const void *)cpl);
+			goto nextdesc;
 		}
 
 		KASSERT(G_RSPD_TYPE(ctrl->u.type_gen) == X_RSPD_TYPE_FLBUF,
@@ -650,7 +632,7 @@ t4_intr_data(void *arg)
 		}
 		FL_UNLOCK(fl);
 
-		ndescs++;
+nextdesc:	ndescs++;
 		iq_next(iq);
 
 		if (ndescs > 32) {
@@ -1264,6 +1246,9 @@ alloc_txq(struct port_info *pi, struct s
 	struct sysctl_oid *oid;
 	struct sysctl_oid_list *children;
 
+	txq->port = pi;
+	TASK_INIT(&txq->resume_tx, 0, cxgbe_txq_start, txq);
+
 	mtx_init(&eq->eq_lock, eq->lockname, NULL, MTX_DEF);
 
 	len = eq->qsize * TX_EQ_ESIZE;
@@ -1797,12 +1782,14 @@ write_txpkt_wr(struct port_info *pi, str
 	struct cpl_tx_pkt_core *cpl;
 	uint32_t ctrl;	/* used in many unrelated places */
 	uint64_t ctrl1;
-	int nflits, ndesc;
+	int nflits, ndesc, pktlen;
 	struct tx_sdesc *txsd;
 	caddr_t dst;
 
 	TXQ_LOCK_ASSERT_OWNED(txq);
 
+	pktlen = m->m_pkthdr.len;
+
 	/*
 	 * Do we have enough flits to send this frame out?
 	 */
@@ -1815,8 +1802,8 @@ write_txpkt_wr(struct port_info *pi, str
 	if (sgl->nsegs > 0)
 		nflits += sgl->nflits;
 	else {
-		nflits += howmany(m->m_pkthdr.len, 8);
-		ctrl += m->m_pkthdr.len;
+		nflits += howmany(pktlen, 8);
+		ctrl += pktlen;
 	}
 	ndesc = howmany(nflits, 8);
 	if (ndesc > eq->avail)
@@ -1856,7 +1843,7 @@ write_txpkt_wr(struct port_info *pi, str
 		lso->ipid_ofst = htobe16(0);
 		lso->mss = htobe16(m->m_pkthdr.tso_segsz);
 		lso->seqno_offset = htobe32(0);
-		lso->len = htobe32(m->m_pkthdr.len);
+		lso->len = htobe32(pktlen);
 
 		cpl = (void *)(lso + 1);
 
@@ -1883,7 +1870,7 @@ write_txpkt_wr(struct port_info *pi, str
 	cpl->ctrl0 = htobe32(V_TXPKT_OPCODE(CPL_TX_PKT) |
 	    V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_PF(pi->adapter->pf));
 	cpl->pack = 0;
-	cpl->len = htobe16(m->m_pkthdr.len);
+	cpl->len = htobe16(pktlen);
 	cpl->ctrl1 = htobe64(ctrl1);
 
 	/* Software descriptor */
@@ -1907,7 +1894,14 @@ write_txpkt_wr(struct port_info *pi, str
 		txq->imm_wrs++;
 		for (; m; m = m->m_next) {
 			copy_to_txd(eq, mtod(m, caddr_t), &dst, m->m_len);
+#ifdef INVARIANTS
+			pktlen -= m->m_len;
+#endif
 		}
+#ifdef INVARIANTS
+		KASSERT(pktlen == 0, ("%s: %d bytes left.", __func__, pktlen));
+#endif
+
 	}
 
 	txq->txpkt_wrs++;
@@ -2390,3 +2384,17 @@ set_fl_tag_idx(struct sge_fl *fl, int mt
 
 	fl->tag_idx = i;
 }
+
+static int
+handle_sge_egr_update(struct adapter *sc, const struct cpl_sge_egr_update *cpl)
+{
+	unsigned int qid = G_EGR_QID(ntohl(cpl->opcode_qid));
+	struct sge *s = &sc->sge;
+	struct sge_txq *txq;
+
+	txq = (void *)s->eqmap[qid - s->eq_start];
+	taskqueue_enqueue(txq->port->tq, &txq->resume_tx);
+	txq->egr_update++;
+
+	return (0);
+}


More information about the svn-src-all mailing list