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