Date: Thu, 29 Dec 2016 07:27:13 +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-10@freebsd.org Subject: svn commit: r310761 - in stable/10/sys/dev/hyperv: include vmbus Message-ID: <201612290727.uBT7RDa8064036@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Thu Dec 29 07:27:13 2016 New Revision: 310761 URL: https://svnweb.freebsd.org/changeset/base/310761 Log: MFC 309240,309242,309244,309245,309319,309670 309240 hyperv/vmbus: Add result polling support for xact API. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8633 309242 hyperv/vmbus: Add result polling support for message Hypercall API. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8634 309244 hyperv/vmbus: Add exec cancel support for message Hypercall API. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8635 309245 hyperv/vmbus: Use poll/cancel APIs to wait for the CHOPEN response. Since hypervisor does not respond CHOPEN to a revoked channel. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8636 309319 hypver/vmbus: Remove extra assertion. It is asserted by vmbus_chan_gpadl_connect() now. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8660 309670 hyperv/vmbus: Use pause if possible. This makes booting on Hyper-V w/ small # of vCPUs work properly. Reported by: Hongxiong Xian <v-hoxian microsoft com>, Hongjiang Zhang <honzhan microsoft com> Sponsored by: Microsoft Modified: stable/10/sys/dev/hyperv/include/vmbus_xact.h stable/10/sys/dev/hyperv/vmbus/vmbus.c stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c stable/10/sys/dev/hyperv/vmbus/vmbus_var.h stable/10/sys/dev/hyperv/vmbus/vmbus_xact.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/hyperv/include/vmbus_xact.h ============================================================================== --- stable/10/sys/dev/hyperv/include/vmbus_xact.h Thu Dec 29 07:20:53 2016 (r310760) +++ stable/10/sys/dev/hyperv/include/vmbus_xact.h Thu Dec 29 07:27:13 2016 (r310761) @@ -56,6 +56,8 @@ const void *vmbus_xact_wait(struct vmbu size_t *resp_len); const void *vmbus_xact_busywait(struct vmbus_xact *xact, size_t *resp_len); +const void *vmbus_xact_poll(struct vmbus_xact *xact, + size_t *resp_len); void vmbus_xact_wakeup(struct vmbus_xact *xact, const void *data, size_t dlen); void vmbus_xact_ctx_wakeup(struct vmbus_xact_ctx *ctx, Modified: stable/10/sys/dev/hyperv/vmbus/vmbus.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus.c Thu Dec 29 07:20:53 2016 (r310760) +++ stable/10/sys/dev/hyperv/vmbus/vmbus.c Thu Dec 29 07:27:13 2016 (r310761) @@ -309,6 +309,13 @@ vmbus_msghc_exec(struct vmbus_softc *sc return error; } +void +vmbus_msghc_exec_cancel(struct vmbus_softc *sc __unused, struct vmbus_msghc *mh) +{ + + vmbus_xact_deactivate(mh->mh_xact); +} + const struct vmbus_message * vmbus_msghc_wait_result(struct vmbus_softc *sc __unused, struct vmbus_msghc *mh) { @@ -317,6 +324,14 @@ vmbus_msghc_wait_result(struct vmbus_sof return (vmbus_xact_wait(mh->mh_xact, &resp_len)); } +const struct vmbus_message * +vmbus_msghc_poll_result(struct vmbus_softc *sc __unused, struct vmbus_msghc *mh) +{ + size_t resp_len; + + return (vmbus_xact_poll(mh->mh_xact, &resp_len)); +} + void vmbus_msghc_wakeup(struct vmbus_softc *sc, const struct vmbus_message *msg) { Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Thu Dec 29 07:20:53 2016 (r310760) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Thu Dec 29 07:27:13 2016 (r310761) @@ -67,7 +67,7 @@ static void vmbus_chan_set_chmap(struc static void vmbus_chan_clear_chmap(struct vmbus_channel *); static void vmbus_chan_detach(struct vmbus_channel *); static bool vmbus_chan_wait_revoke( - const struct vmbus_channel *); + const struct vmbus_channel *, bool); static void vmbus_chan_ins_prilist(struct vmbus_softc *, struct vmbus_channel *); @@ -349,7 +349,6 @@ vmbus_chan_open_br(struct vmbus_channel const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg) { struct vmbus_softc *sc = chan->ch_vmbus; - const struct vmbus_chanmsg_chopen_resp *resp; const struct vmbus_message *msg; struct vmbus_chanmsg_chopen *req; struct vmbus_msghc *mh; @@ -406,8 +405,6 @@ vmbus_chan_open_br(struct vmbus_channel /* * Connect the bufrings, both RX and TX, to this channel. */ - KASSERT(chan->ch_bufring_gpadl == 0, - ("bufring GPADL is still connected")); error = vmbus_chan_gpadl_connect(chan, cbr->cbr_paddr, txbr_size + rxbr_size, &chan->ch_bufring_gpadl); if (error) { @@ -453,9 +450,50 @@ vmbus_chan_open_br(struct vmbus_channel goto failed; } - msg = vmbus_msghc_wait_result(sc, mh); - resp = (const struct vmbus_chanmsg_chopen_resp *)msg->msg_data; - status = resp->chm_status; + for (;;) { + msg = vmbus_msghc_poll_result(sc, mh); + if (msg != NULL) + break; + if (vmbus_chan_is_revoked(chan)) { + int i; + + /* + * NOTE: + * Hypervisor does _not_ send response CHOPEN to + * a revoked channel. + */ + vmbus_chan_printf(chan, + "chan%u is revoked, when it is being opened\n", + chan->ch_id); + + /* + * XXX + * Add extra delay before cancel the hypercall + * execution; mainly to close any possible + * CHRESCIND and CHOPEN_RESP races on the + * hypervisor side. + */ +#define REVOKE_LINGER 100 + for (i = 0; i < REVOKE_LINGER; ++i) { + msg = vmbus_msghc_poll_result(sc, mh); + if (msg != NULL) + break; + pause("rchopen", 1); + } +#undef REVOKE_LINGER + if (msg == NULL) + vmbus_msghc_exec_cancel(sc, mh); + break; + } + pause("chopen", 1); + } + if (msg != NULL) { + status = ((const struct vmbus_chanmsg_chopen_resp *) + msg->msg_data)->chm_status; + } else { + /* XXX any non-0 value is ok here. */ + status = 0xff; + } vmbus_msghc_put(sc, mh); @@ -620,7 +658,7 @@ vmbus_chan_gpadl_connect(struct vmbus_ch } static bool -vmbus_chan_wait_revoke(const struct vmbus_channel *chan) +vmbus_chan_wait_revoke(const struct vmbus_channel *chan, bool can_sleep) { #define WAIT_COUNT 200 /* 200ms */ @@ -629,8 +667,10 @@ vmbus_chan_wait_revoke(const struct vmbu for (i = 0; i < WAIT_COUNT; ++i) { if (vmbus_chan_is_revoked(chan)) return (true); - /* Not sure about the context; use busy-wait. */ - DELAY(1000); + if (can_sleep) + pause("wchrev", 1); + else + DELAY(1000); } return (false); @@ -667,7 +707,7 @@ vmbus_chan_gpadl_disconnect(struct vmbus if (error) { vmbus_msghc_put(sc, mh); - if (vmbus_chan_wait_revoke(chan)) { + if (vmbus_chan_wait_revoke(chan, true)) { /* * Error is benign; this channel is revoked, * so this GPADL will not be touched anymore. Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_var.h ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_var.h Thu Dec 29 07:20:53 2016 (r310760) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_var.h Thu Dec 29 07:27:13 2016 (r310761) @@ -157,9 +157,14 @@ void vmbus_msghc_put(struct vmbus_softc void *vmbus_msghc_dataptr(struct vmbus_msghc *); int vmbus_msghc_exec_noresult(struct vmbus_msghc *); int vmbus_msghc_exec(struct vmbus_softc *, struct vmbus_msghc *); +void vmbus_msghc_exec_cancel(struct vmbus_softc *, + struct vmbus_msghc *); const struct vmbus_message * vmbus_msghc_wait_result(struct vmbus_softc *, struct vmbus_msghc *); +const struct vmbus_message * + vmbus_msghc_poll_result(struct vmbus_softc *, + struct vmbus_msghc *); void vmbus_msghc_wakeup(struct vmbus_softc *, const struct vmbus_message *); void vmbus_msghc_reset(struct vmbus_msghc *, size_t); Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_xact.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_xact.c Thu Dec 29 07:20:53 2016 (r310760) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_xact.c Thu Dec 29 07:27:13 2016 (r310761) @@ -71,8 +71,10 @@ static struct vmbus_xact *vmbus_xact_all static void vmbus_xact_free(struct vmbus_xact *); static struct vmbus_xact *vmbus_xact_get1(struct vmbus_xact_ctx *, uint32_t); -const void *vmbus_xact_wait1(struct vmbus_xact *, size_t *, +static const void *vmbus_xact_wait1(struct vmbus_xact *, size_t *, bool); +static const void *vmbus_xact_return(struct vmbus_xact *, + size_t *); static void vmbus_xact_save_resp(struct vmbus_xact *, const void *, size_t); static void vmbus_xact_ctx_free(struct vmbus_xact_ctx *); @@ -277,27 +279,13 @@ vmbus_xact_deactivate(struct vmbus_xact mtx_unlock(&ctx->xc_lock); } -const void * -vmbus_xact_wait1(struct vmbus_xact *xact, size_t *resp_len, - bool can_sleep) +static const void * +vmbus_xact_return(struct vmbus_xact *xact, size_t *resp_len) { struct vmbus_xact_ctx *ctx = xact->x_ctx; const void *resp; - mtx_lock(&ctx->xc_lock); - - KASSERT(ctx->xc_active == xact, ("xact mismatch")); - while (xact->x_resp == NULL && - (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) == 0) { - if (can_sleep) { - mtx_sleep(&ctx->xc_active, &ctx->xc_lock, 0, - "wxact", 0); - } else { - mtx_unlock(&ctx->xc_lock); - DELAY(1000); - mtx_lock(&ctx->xc_lock); - } - } + mtx_assert(&ctx->xc_lock, MA_OWNED); KASSERT(ctx->xc_active == xact, ("xact trashed")); if ((ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) && xact->x_resp == NULL) { @@ -317,6 +305,32 @@ vmbus_xact_wait1(struct vmbus_xact *xact resp = xact->x_resp; *resp_len = xact->x_resp_len; + return (resp); +} + +static const void * +vmbus_xact_wait1(struct vmbus_xact *xact, size_t *resp_len, + bool can_sleep) +{ + struct vmbus_xact_ctx *ctx = xact->x_ctx; + const void *resp; + + mtx_lock(&ctx->xc_lock); + + KASSERT(ctx->xc_active == xact, ("xact mismatch")); + while (xact->x_resp == NULL && + (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) == 0) { + if (can_sleep) { + mtx_sleep(&ctx->xc_active, &ctx->xc_lock, 0, + "wxact", 0); + } else { + mtx_unlock(&ctx->xc_lock); + DELAY(1000); + mtx_lock(&ctx->xc_lock); + } + } + resp = vmbus_xact_return(xact, resp_len); + mtx_unlock(&ctx->xc_lock); return (resp); @@ -336,6 +350,28 @@ vmbus_xact_busywait(struct vmbus_xact *x return (vmbus_xact_wait1(xact, resp_len, false /* can't sleep */)); } +const void * +vmbus_xact_poll(struct vmbus_xact *xact, size_t *resp_len) +{ + struct vmbus_xact_ctx *ctx = xact->x_ctx; + const void *resp; + + mtx_lock(&ctx->xc_lock); + + KASSERT(ctx->xc_active == xact, ("xact mismatch")); + if (xact->x_resp == NULL && + (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) == 0) { + mtx_unlock(&ctx->xc_lock); + *resp_len = 0; + return (NULL); + } + resp = vmbus_xact_return(xact, resp_len); + + mtx_unlock(&ctx->xc_lock); + + return (resp); +} + static void vmbus_xact_save_resp(struct vmbus_xact *xact, const void *data, size_t dlen) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612290727.uBT7RDa8064036>