From owner-svn-src-stable@freebsd.org Mon Jun 13 08:38:05 2016 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E74FBAF1E3D; Mon, 13 Jun 2016 08:38:05 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9BE712580; Mon, 13 Jun 2016 08:38:05 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u5D8c43m009994; Mon, 13 Jun 2016 08:38:04 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u5D8c4t7009992; Mon, 13 Jun 2016 08:38:04 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201606130838.u5D8c4t7009992@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Mon, 13 Jun 2016 08:38:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r301864 - stable/10/sys/dev/hyperv/netvsc X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Jun 2016 08:38:06 -0000 Author: sephe Date: Mon Jun 13 08:38:04 2016 New Revision: 301864 URL: https://svnweb.freebsd.org/changeset/base/301864 Log: MFC 295875,295876,295877,295916,295918 295875 hyperv/hn: Rename TX related function and struct fields a bit Preamble to implement the ifnet.if_transmit method. Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5344 295876 hyperv/hn: Staticize and rename packet TX done function It is only used in hv_netvsc_drv_freebsd.c; and rename it to hn_tx_done() mainly to reserve "xmit" for ifnet.if_transmit implement. While I'm here, remove unapplied comment. Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5345 295877 hyperv/hn: Add TX method for txeof processing. Preamble to implement ifnet.if_transmit method. Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5346 295916 hyperv/hn: Factor out hn_send_pkt() from hn_start_locked() It will be shared w/ the upcoming ifnet.if_transmit method implementation. No functional change. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5385 295918 hyperv/hn: Use IFQ_DRV_PREPEND instead of IF_PREPEND IF_PREPEND promises out-of-order packet sending when the TX desc list is depleted. It was overlooked and copied blindly when the transmission path was partially rewritten. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5386 Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Mon Jun 13 08:18:45 2016 (r301863) +++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Mon Jun 13 08:38:04 2016 (r301864) @@ -1026,11 +1026,12 @@ struct hn_tx_ring { #endif int hn_txdesc_cnt; int hn_txdesc_avail; - int hn_txeof; + int hn_has_txeof; int hn_sched_tx; + void (*hn_txeof)(struct hn_tx_ring *); struct taskqueue *hn_tx_taskq; - struct task hn_start_task; + struct task hn_tx_task; struct task hn_txeof_task; struct mtx hn_tx_lock; @@ -1087,7 +1088,6 @@ typedef struct hn_softc { extern int hv_promisc_mode; void netvsc_linkstatus_callback(struct hv_device *device_obj, uint32_t status); -void netvsc_xmit_completion(void *context); void hv_nv_on_receive_completion(struct hv_device *device, uint64_t tid, uint32_t status); netvsc_dev *hv_nv_on_device_add(struct hv_device *device, Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Jun 13 08:18:45 2016 (r301863) +++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Jun 13 08:38:04 2016 (r301864) @@ -304,8 +304,8 @@ static int hn_create_tx_ring(struct hn_s static void hn_destroy_tx_ring(struct hn_tx_ring *); static int hn_create_tx_data(struct hn_softc *); static void hn_destroy_tx_data(struct hn_softc *); -static void hn_start_taskfunc(void *xsc, int pending); -static void hn_txeof_taskfunc(void *xsc, int pending); +static void hn_start_taskfunc(void *, int); +static void hn_start_txeof_taskfunc(void *, int); static void hn_stop_tx_tasks(struct hn_softc *); static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **); static void hn_create_rx_data(struct hn_softc *sc); @@ -673,17 +673,10 @@ hn_txdesc_hold(struct hn_txdesc *txd) atomic_add_int(&txd->refs, 1); } -/* - * Send completion processing - * - * Note: It looks like offset 0 of buf is reserved to hold the softc - * pointer. The sc pointer is not currently needed in this function, and - * it is not presently populated by the TX function. - */ -void -netvsc_xmit_completion(void *context) +static void +hn_tx_done(void *xpkt) { - netvsc_packet *packet = context; + netvsc_packet *packet = xpkt; struct hn_txdesc *txd; struct hn_tx_ring *txr; @@ -691,7 +684,7 @@ netvsc_xmit_completion(void *context) packet->compl.send.send_completion_tid; txr = txd->txr; - txr->hn_txeof = 1; + txr->hn_has_txeof = 1; hn_txdesc_put(txr, txd); } @@ -711,11 +704,11 @@ netvsc_channel_rollup(struct hv_device * } #endif - if (!txr->hn_txeof) + if (!txr->hn_has_txeof) return; - txr->hn_txeof = 0; - hn_start_txeof(txr); + txr->hn_has_txeof = 0; + txr->hn_txeof(txr); } /* @@ -925,7 +918,7 @@ done: txd->m = m_head; /* Set the completion routine */ - packet->compl.send.on_send_completion = netvsc_xmit_completion; + packet->compl.send.on_send_completion = hn_tx_done; packet->compl.send.send_completion_context = packet; packet->compl.send.send_completion_tid = (uint64_t)(uintptr_t)txd; @@ -933,6 +926,68 @@ done: } /* + * NOTE: + * If this function fails, then txd will be freed, but the mbuf + * associated w/ the txd will _not_ be freed. + */ +static int +hn_send_pkt(struct ifnet *ifp, struct hv_device *device_ctx, + struct hn_tx_ring *txr, struct hn_txdesc *txd) +{ + int error, send_failed = 0; + +again: + /* + * Make sure that txd is not freed before ETHER_BPF_MTAP. + */ + hn_txdesc_hold(txd); + error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt); + if (!error) { + ETHER_BPF_MTAP(ifp, txd->m); + if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + } + hn_txdesc_put(txr, txd); + + if (__predict_false(error)) { + int freed; + + /* + * This should "really rarely" happen. + * + * XXX Too many RX to be acked or too many sideband + * commands to run? Ask netvsc_channel_rollup() + * to kick start later. + */ + txr->hn_has_txeof = 1; + if (!send_failed) { + txr->hn_send_failed++; + send_failed = 1; + /* + * Try sending again after set hn_has_txeof; + * in case that we missed the last + * netvsc_channel_rollup(). + */ + goto again; + } + if_printf(ifp, "send failed\n"); + + /* + * Caller will perform further processing on the + * associated mbuf, so don't free it in hn_txdesc_put(); + * only unload it from the DMA map in hn_txdesc_put(), + * if it was loaded. + */ + txd->m = NULL; + freed = hn_txdesc_put(txr, txd); + KASSERT(freed != 0, + ("fail to free txd upon send error")); + + txr->hn_send_failed++; + } + return error; +} + +/* * Start a transmit of one or more packets */ static int @@ -950,9 +1005,9 @@ hn_start_locked(struct hn_tx_ring *txr, return 0; while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { - int error, send_failed = 0; struct hn_txdesc *txd; struct mbuf *m_head; + int error; IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); if (m_head == NULL) @@ -964,14 +1019,14 @@ hn_start_locked(struct hn_tx_ring *txr, * dispatch this packet sending (and sending of any * following up packets) to tx taskqueue. */ - IF_PREPEND(&ifp->if_snd, m_head); + IFQ_DRV_PREPEND(&ifp->if_snd, m_head); return 1; } txd = hn_txdesc_get(txr); if (txd == NULL) { txr->hn_no_txdescs++; - IF_PREPEND(&ifp->if_snd, m_head); + IFQ_DRV_PREPEND(&ifp->if_snd, m_head); atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); break; } @@ -981,53 +1036,11 @@ hn_start_locked(struct hn_tx_ring *txr, /* Both txd and m_head are freed */ continue; } -again: - /* - * Make sure that txd is not freed before ETHER_BPF_MTAP. - */ - hn_txdesc_hold(txd); - error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt); - if (!error) { - ETHER_BPF_MTAP(ifp, m_head); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - } - hn_txdesc_put(txr, txd); + error = hn_send_pkt(ifp, device_ctx, txr, txd); if (__predict_false(error)) { - int freed; - - /* - * This should "really rarely" happen. - * - * XXX Too many RX to be acked or too many sideband - * commands to run? Ask netvsc_channel_rollup() - * to kick start later. - */ - txr->hn_txeof = 1; - if (!send_failed) { - txr->hn_send_failed++; - send_failed = 1; - /* - * Try sending again after set hn_txeof; - * in case that we missed the last - * netvsc_channel_rollup(). - */ - goto again; - } - if_printf(ifp, "send failed\n"); - - /* - * This mbuf will be prepended, don't free it - * in hn_txdesc_put(); only unload it from the - * DMA map in hn_txdesc_put(), if it was loaded. - */ - txd->m = NULL; - freed = hn_txdesc_put(txr, txd); - KASSERT(freed != 0, - ("fail to free txd upon send error")); - - txr->hn_send_failed++; - IF_PREPEND(&ifp->if_snd, m_head); + /* txd is freed, but m_head is not */ + IFQ_DRV_PREPEND(&ifp->if_snd, m_head); atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); break; } @@ -1578,7 +1591,7 @@ hn_start(struct ifnet *ifp) return; } do_sched: - taskqueue_enqueue(txr->hn_tx_taskq, &txr->hn_start_task); + taskqueue_enqueue(txr->hn_tx_taskq, &txr->hn_tx_task); } static void @@ -1600,7 +1613,7 @@ hn_start_txeof(struct hn_tx_ring *txr) mtx_unlock(&txr->hn_tx_lock); if (sched) { taskqueue_enqueue(txr->hn_tx_taskq, - &txr->hn_start_task); + &txr->hn_tx_task); } } else { do_sched: @@ -2172,8 +2185,8 @@ hn_create_tx_ring(struct hn_softc *sc, i #endif txr->hn_tx_taskq = sc->hn_tx_taskq; - TASK_INIT(&txr->hn_start_task, 0, hn_start_taskfunc, txr); - TASK_INIT(&txr->hn_txeof_task, 0, hn_txeof_taskfunc, txr); + TASK_INIT(&txr->hn_tx_task, 0, hn_start_taskfunc, txr); + TASK_INIT(&txr->hn_txeof_task, 0, hn_start_txeof_taskfunc, txr); txr->hn_direct_tx_size = hn_direct_tx_size; if (hv_vmbus_protocal_version >= HV_VMBUS_VERSION_WIN8_1) @@ -2187,6 +2200,8 @@ hn_create_tx_ring(struct hn_softc *sc, i */ txr->hn_sched_tx = 1; + txr->hn_txeof = hn_start_txeof; /* TODO: if_transmit */ + parent_dtag = bus_get_dma_tag(sc->hn_dev); /* DMA tag for RNDIS messages. */ @@ -2468,7 +2483,7 @@ hn_start_taskfunc(void *xtxr, int pendin } static void -hn_txeof_taskfunc(void *xtxr, int pending __unused) +hn_start_txeof_taskfunc(void *xtxr, int pending __unused) { struct hn_tx_ring *txr = xtxr; @@ -2486,7 +2501,7 @@ hn_stop_tx_tasks(struct hn_softc *sc) for (i = 0; i < sc->hn_tx_ring_cnt; ++i) { struct hn_tx_ring *txr = &sc->hn_tx_ring[i]; - taskqueue_drain(txr->hn_tx_taskq, &txr->hn_start_task); + taskqueue_drain(txr->hn_tx_taskq, &txr->hn_tx_task); taskqueue_drain(txr->hn_tx_taskq, &txr->hn_txeof_task); } }