From owner-svn-src-all@FreeBSD.ORG Sat Mar 5 03:06:39 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 17BD0106564A; Sat, 5 Mar 2011 03:06:39 +0000 (UTC) (envelope-from np@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 058AB8FC08; Sat, 5 Mar 2011 03:06:39 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p2536cHO095937; Sat, 5 Mar 2011 03:06:38 GMT (envelope-from np@svn.freebsd.org) Received: (from np@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p2536cMX095933; Sat, 5 Mar 2011 03:06:38 GMT (envelope-from np@svn.freebsd.org) Message-Id: <201103050306.p2536cMX095933@svn.freebsd.org> From: Navdeep Parhar Date: Sat, 5 Mar 2011 03:06:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r219286 - head/sys/dev/cxgbe X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Mar 2011 03:06:39 -0000 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 #include #include +#include +#include +#include #include #include #include @@ -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 #include #include +#include +#include +#include #include #include #include @@ -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); +}