Date: Wed, 19 Oct 2016 07:27:45 +0000 (UTC) From: Sepherosa Ziehau <sephe@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r307614 - in stable/11/sys/dev/hyperv: include netvsc vmbus Message-ID: <201610190727.u9J7RjvC019552@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Wed Oct 19 07:27:45 2016 New Revision: 307614 URL: https://svnweb.freebsd.org/changeset/base/307614 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/11/sys/dev/hyperv/include/vmbus.h stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c stable/11/sys/dev/hyperv/netvsc/if_hnvar.h stable/11/sys/dev/hyperv/vmbus/vmbus_chan.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/dev/hyperv/include/vmbus.h ============================================================================== --- stable/11/sys/dev/hyperv/include/vmbus.h Wed Oct 19 07:24:32 2016 (r307613) +++ stable/11/sys/dev/hyperv/include/vmbus.h Wed Oct 19 07:27:45 2016 (r307614) @@ -117,6 +117,7 @@ struct vmbus_chan_br { struct vmbus_channel; struct hyperv_guid; +struct task; typedef void (*vmbus_chan_callback_t)(struct vmbus_channel *, void *); @@ -134,6 +135,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/11/sys/dev/hyperv/netvsc/hv_net_vsc.h ============================================================================== --- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h Wed Oct 19 07:24:32 2016 (r307613) +++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h Wed Oct 19 07:27:45 2016 (r307614) @@ -233,6 +233,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; @@ -271,7 +275,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/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Wed Oct 19 07:24:32 2016 (r307613) +++ stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Wed Oct 19 07:27:45 2016 (r307614) @@ -334,6 +334,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); @@ -349,7 +351,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 *); @@ -518,7 +524,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; @@ -551,6 +556,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(). @@ -621,12 +635,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; @@ -736,6 +744,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) @@ -755,6 +769,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); @@ -767,6 +787,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); @@ -786,6 +807,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) @@ -1311,19 +1362,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. @@ -1653,8 +1691,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. @@ -1672,9 +1713,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; @@ -1801,9 +1843,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); @@ -1896,9 +1938,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 @@ -3600,7 +3639,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; @@ -3654,6 +3693,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; @@ -3671,7 +3746,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; @@ -3685,7 +3760,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); @@ -3713,6 +3789,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/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c ============================================================================== --- stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c Wed Oct 19 07:24:32 2016 (r307613) +++ stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c Wed Oct 19 07:27:45 2016 (r307614) @@ -167,11 +167,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/11/sys/dev/hyperv/netvsc/if_hnvar.h ============================================================================== --- stable/11/sys/dev/hyperv/netvsc/if_hnvar.h Wed Oct 19 07:24:32 2016 (r307613) +++ stable/11/sys/dev/hyperv/netvsc/if_hnvar.h Wed Oct 19 07:27:45 2016 (r307614) @@ -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/11/sys/dev/hyperv/vmbus/vmbus_chan.c ============================================================================== --- stable/11/sys/dev/hyperv/vmbus/vmbus_chan.c Wed Oct 19 07:24:32 2016 (r307613) +++ stable/11/sys/dev/hyperv/vmbus/vmbus_chan.c Wed Oct 19 07:27:45 2016 (r307614) @@ -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); +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610190727.u9J7RjvC019552>