From owner-svn-src-all@freebsd.org Wed Oct 19 08:40:26 2016 Return-Path: Delivered-To: svn-src-all@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 15246C18CE6; Wed, 19 Oct 2016 08:40:26 +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 E31C02FA; Wed, 19 Oct 2016 08:40:25 +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 u9J8ePmf046150; Wed, 19 Oct 2016 08:40:25 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u9J8eOrc046144; Wed, 19 Oct 2016 08:40:24 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201610190840.u9J8eOrc046144@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Wed, 19 Oct 2016 08:40:24 +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: r307621 - in stable/10/sys/dev/hyperv: include netvsc vmbus X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 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: Wed, 19 Oct 2016 08:40:26 -0000 Author: sephe Date: Wed Oct 19 08:40:24 2016 New Revision: 307621 URL: https://svnweb.freebsd.org/changeset/base/307621 Log: MFC 307012,307013,307262 307012 hyperv/vmbus: Allow driver to inject synchronous task into channel taskq. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8208 307013 hyperv/hn: Rework link status support. This is the preamble for network device SR-IOV and NDIS_STATUS_NETWORK_CHANGE handling. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8209 307262 hyperv/hn: Management parts always need suspend and resume. Sponsored by: Microsoft Modified: stable/10/sys/dev/hyperv/include/vmbus.h stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c stable/10/sys/dev/hyperv/netvsc/if_hnvar.h stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/hyperv/include/vmbus.h ============================================================================== --- stable/10/sys/dev/hyperv/include/vmbus.h Wed Oct 19 08:32:24 2016 (r307620) +++ stable/10/sys/dev/hyperv/include/vmbus.h Wed Oct 19 08:40:24 2016 (r307621) @@ -118,6 +118,7 @@ struct vmbus_chan_br { struct vmbus_channel; struct hyperv_guid; +struct task; typedef void (*vmbus_chan_callback_t)(struct vmbus_channel *, void *); @@ -135,6 +136,8 @@ int vmbus_chan_open_br(struct vmbus_cha int udlen, vmbus_chan_callback_t cb, void *cbarg); void vmbus_chan_close(struct vmbus_channel *chan); void vmbus_chan_intr_drain(struct vmbus_channel *chan); +void vmbus_chan_run_task(struct vmbus_channel *chan, + struct task *task); int vmbus_chan_gpadl_connect(struct vmbus_channel *chan, bus_addr_t paddr, int size, uint32_t *gpadl); Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Wed Oct 19 08:32:24 2016 (r307620) +++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Wed Oct 19 08:40:24 2016 (r307621) @@ -234,6 +234,10 @@ struct hn_softc { struct vmbus_xact_ctx *hn_xact; uint32_t hn_nvs_ver; + struct taskqueue *hn_mgmt_taskq; + struct taskqueue *hn_mgmt_taskq0; + struct task hn_link_task; + uint32_t hn_caps; /* HN_CAP_ */ uint32_t hn_flags; /* HN_FLAG_ */ void *hn_rxbuf; @@ -272,7 +276,6 @@ struct hn_softc { */ struct hn_send_ctx; -void netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status); int hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt); Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Wed Oct 19 08:32:24 2016 (r307620) +++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Wed Oct 19 08:40:24 2016 (r307621) @@ -336,6 +336,8 @@ static void hn_fixup_tx_data(struct hn_s static void hn_destroy_tx_data(struct hn_softc *); static void hn_start_taskfunc(void *, int); static void hn_start_txeof_taskfunc(void *, int); +static void hn_link_taskfunc(void *, int); +static void hn_suspend_mgmt_taskfunc(void *, int); static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **); static int hn_create_rx_data(struct hn_softc *sc, int); static void hn_destroy_rx_data(struct hn_softc *sc); @@ -351,7 +353,11 @@ static int hn_synth_attach(struct hn_sof static void hn_synth_detach(struct hn_softc *); static bool hn_tx_ring_pending(struct hn_tx_ring *); static void hn_suspend(struct hn_softc *); +static void hn_suspend_data(struct hn_softc *); +static void hn_suspend_mgmt(struct hn_softc *); static void hn_resume(struct hn_softc *); +static void hn_resume_data(struct hn_softc *); +static void hn_resume_mgmt(struct hn_softc *); static void hn_rx_drain(struct vmbus_channel *); static void hn_tx_resume(struct hn_softc *, int); static void hn_tx_ring_qflush(struct hn_tx_ring *); @@ -533,7 +539,6 @@ netvsc_attach(device_t dev) struct sysctl_oid_list *child; struct sysctl_ctx_list *ctx; uint8_t eaddr[ETHER_ADDR_LEN]; - uint32_t link_status; struct ifnet *ifp = NULL; int error, ring_cnt, tx_ring_cnt; @@ -567,6 +572,15 @@ netvsc_attach(device_t dev) } /* + * Setup taskqueue for mangement tasks, e.g. link status. + */ + sc->hn_mgmt_taskq0 = taskqueue_create("hn_mgmt", M_WAITOK, + taskqueue_thread_enqueue, &sc->hn_mgmt_taskq0); + taskqueue_start_threads(&sc->hn_mgmt_taskq0, 1, PI_NET, "%s mgmt", + device_get_nameunit(dev)); + TASK_INIT(&sc->hn_link_task, 0, hn_link_taskfunc, sc); + + /* * Allocate ifnet and setup its name earlier, so that if_printf * can be used by functions, which will be called after * ether_ifattach(). @@ -637,12 +651,6 @@ netvsc_attach(device_t dev) if (error) goto failed; - error = hn_rndis_get_linkstatus(sc, &link_status); - if (error) - goto failed; - if (link_status == NDIS_MEDIA_STATE_CONNECTED) - sc->hn_carrier = 1; - error = hn_rndis_get_eaddr(sc, eaddr); if (error) goto failed; @@ -752,6 +760,12 @@ netvsc_attach(device_t dev) /* Inform the upper layer about the long frame support. */ ifp->if_hdrlen = sizeof(struct ether_vlan_header); + /* + * Kick off link status check. + */ + sc->hn_mgmt_taskq = sc->hn_mgmt_taskq0; + hn_link_status_update(sc); + return (0); failed: if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) @@ -771,6 +785,12 @@ netvsc_detach(device_t dev) if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) { if (ifp->if_drv_flags & IFF_DRV_RUNNING) hn_stop(sc); + /* + * NOTE: + * hn_stop() only suspends data, so managment + * stuffs have to be suspended manually here. + */ + hn_suspend_mgmt(sc); hn_synth_detach(sc); } HN_UNLOCK(sc); @@ -783,6 +803,7 @@ netvsc_detach(device_t dev) if (sc->hn_tx_taskq != hn_tx_taskq) taskqueue_free(sc->hn_tx_taskq); + taskqueue_free(sc->hn_mgmt_taskq0); if (sc->hn_xact != NULL) vmbus_xact_ctx_destroy(sc->hn_xact); @@ -802,6 +823,36 @@ netvsc_shutdown(device_t dev) return (0); } +static void +hn_link_taskfunc(void *xsc, int pending __unused) +{ + struct hn_softc *sc = xsc; + struct ifnet *ifp = sc->hn_ifp; + uint32_t link_status; + int error; + + error = hn_rndis_get_linkstatus(sc, &link_status); + if (error) { + /* XXX what to do? */ + return; + } + + if (link_status == NDIS_MEDIA_STATE_CONNECTED) + sc->hn_carrier = 1; + else + sc->hn_carrier = 0; + if_link_state_change(ifp, + sc->hn_carrier ? LINK_STATE_UP : LINK_STATE_DOWN); +} + +void +hn_link_status_update(struct hn_softc *sc) +{ + + if (sc->hn_mgmt_taskq != NULL) + taskqueue_enqueue(sc->hn_mgmt_taskq, &sc->hn_link_task); +} + static __inline int hn_txdesc_dmamap_load(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head, bus_dma_segment_t *segs, int *nsegs) @@ -1333,19 +1384,6 @@ hn_start_locked(struct hn_tx_ring *txr, } /* - * Link up/down notification - */ -void -netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status) -{ - if (status == 1) { - sc->hn_carrier = 1; - } else { - sc->hn_carrier = 0; - } -} - -/* * Append the specified data to the indicated mbuf chain, * Extend the mbuf chain if the new data does not fit in * existing space. @@ -1673,8 +1711,11 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, hn_set_lro_lenlim(sc, HN_LRO_LENLIM_MIN(ifp)); #endif - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - hn_suspend(sc); + /* + * Suspend this interface before the synthetic parts + * are ripped. + */ + hn_suspend(sc); /* * Detach the synthetics parts, i.e. NVS and RNDIS. @@ -1692,9 +1733,10 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, hn_set_chim_size(sc, sc->hn_chim_szmax); hn_set_tso_maxsize(sc, hn_tso_maxlen, ifr->ifr_mtu); - /* All done! Resume now. */ - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - hn_resume(sc); + /* + * All done! Resume the interface now. + */ + hn_resume(sc); HN_UNLOCK(sc); break; @@ -1821,9 +1863,9 @@ hn_stop(struct hn_softc *sc) KASSERT(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED, ("synthetic parts were not attached")); - /* Clear RUNNING bit _before_ hn_suspend() */ + /* Clear RUNNING bit _before_ hn_suspend_data() */ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_RUNNING); - hn_suspend(sc); + hn_suspend_data(sc); /* Clear OACTIVE bit. */ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); @@ -1916,9 +1958,6 @@ hn_init_locked(struct hn_softc *sc) /* Everything is ready; unleash! */ atomic_set_int(&ifp->if_drv_flags, IFF_DRV_RUNNING); - - /* TODO: check RNDIS link status. */ - if_link_state_change(ifp, LINK_STATE_UP); } static void @@ -3620,7 +3659,7 @@ hn_rx_drain(struct vmbus_channel *chan) } static void -hn_suspend(struct hn_softc *sc) +hn_suspend_data(struct hn_softc *sc) { struct vmbus_channel **subch = NULL; int i, nsubch; @@ -3674,6 +3713,42 @@ hn_suspend(struct hn_softc *sc) } static void +hn_suspend_mgmt_taskfunc(void *xsc, int pending __unused) +{ + + ((struct hn_softc *)xsc)->hn_mgmt_taskq = NULL; +} + +static void +hn_suspend_mgmt(struct hn_softc *sc) +{ + struct task task; + + HN_LOCK_ASSERT(sc); + + /* + * Make sure that hn_mgmt_taskq0 can nolonger be accessed + * through hn_mgmt_taskq. + */ + TASK_INIT(&task, 0, hn_suspend_mgmt_taskfunc, sc); + vmbus_chan_run_task(sc->hn_prichan, &task); + + /* + * Make sure that all pending management tasks are completed. + */ + taskqueue_drain_all(sc->hn_mgmt_taskq0); +} + +static void +hn_suspend(struct hn_softc *sc) +{ + + if (sc->hn_ifp->if_drv_flags & IFF_DRV_RUNNING) + hn_suspend_data(sc); + hn_suspend_mgmt(sc); +} + +static void hn_tx_resume(struct hn_softc *sc, int tx_ring_cnt) { int i; @@ -3691,7 +3766,7 @@ hn_tx_resume(struct hn_softc *sc, int tx } static void -hn_resume(struct hn_softc *sc) +hn_resume_data(struct hn_softc *sc) { int i; @@ -3705,7 +3780,8 @@ hn_resume(struct hn_softc *sc) /* * Make sure to clear suspend status on "all" TX rings, - * since hn_tx_ring_inuse can be changed after hn_suspend(). + * since hn_tx_ring_inuse can be changed after + * hn_suspend_data(). */ hn_tx_resume(sc, sc->hn_tx_ring_cnt); @@ -3733,6 +3809,26 @@ hn_resume(struct hn_softc *sc) } static void +hn_resume_mgmt(struct hn_softc *sc) +{ + + /* + * Kick off link status check. + */ + sc->hn_mgmt_taskq = sc->hn_mgmt_taskq0; + hn_link_status_update(sc); +} + +static void +hn_resume(struct hn_softc *sc) +{ + + if (sc->hn_ifp->if_drv_flags & IFF_DRV_RUNNING) + hn_resume_data(sc); + hn_resume_mgmt(sc); +} + +static void hn_nvs_handle_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt) { const struct hn_nvs_hdr *hdr; Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c Wed Oct 19 08:32:24 2016 (r307620) +++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c Wed Oct 19 08:40:24 2016 (r307621) @@ -168,11 +168,8 @@ hv_rf_receive_indicate_status(struct hn_ switch (msg->rm_status) { case RNDIS_STATUS_MEDIA_CONNECT: - netvsc_linkstatus_callback(sc, 1); - break; - case RNDIS_STATUS_MEDIA_DISCONNECT: - netvsc_linkstatus_callback(sc, 0); + hn_link_status_update(sc); break; case RNDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG: Modified: stable/10/sys/dev/hyperv/netvsc/if_hnvar.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/if_hnvar.h Wed Oct 19 08:32:24 2016 (r307620) +++ stable/10/sys/dev/hyperv/netvsc/if_hnvar.h Wed Oct 19 08:40:24 2016 (r307621) @@ -138,6 +138,7 @@ void hn_nvs_sent_xact(struct hn_send_ct int hn_rxpkt(struct hn_rx_ring *rxr, const void *data, int dlen, const struct hn_recvinfo *info); void hn_chan_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); +void hn_link_status_update(struct hn_softc *sc); extern struct hn_send_ctx hn_send_ctx_none; Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Wed Oct 19 08:32:24 2016 (r307620) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Wed Oct 19 08:40:24 2016 (r307621) @@ -1713,3 +1713,11 @@ vmbus_chan_rx_empty(const struct vmbus_c return (vmbus_rxbr_empty(&chan->ch_rxbr)); } + +void +vmbus_chan_run_task(struct vmbus_channel *chan, struct task *task) +{ + + taskqueue_enqueue(chan->ch_tq, task); + taskqueue_drain(chan->ch_tq, task); +}