Date: Sat, 5 Mar 2011 03:06:38 +0000 (UTC) From: Navdeep Parhar <np@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r219286 - head/sys/dev/cxgbe Message-ID: <201103050306.p2536cMX095933@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103050306.p2536cMX095933>