From owner-svn-src-head@freebsd.org Thu Nov 24 04:58:14 2016 Return-Path: Delivered-To: svn-src-head@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 C9D3FC526C2; Thu, 24 Nov 2016 04:58:14 +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 8AA13FD1; Thu, 24 Nov 2016 04:58:14 +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 uAO4wD3Z039788; Thu, 24 Nov 2016 04:58:13 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uAO4wD4e039786; Thu, 24 Nov 2016 04:58:13 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201611240458.uAO4wD4e039786@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Thu, 24 Nov 2016 04:58:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r309080 - in head/sys/dev/hyperv: include vmbus X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Nov 2016 04:58:14 -0000 Author: sephe Date: Thu Nov 24 04:58:13 2016 New Revision: 309080 URL: https://svnweb.freebsd.org/changeset/base/309080 Log: hyperv/vmbus: Implement orphan support for transaction API It will be used to fix the primary channel revocation support. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8525 Modified: head/sys/dev/hyperv/include/vmbus_xact.h head/sys/dev/hyperv/vmbus/vmbus_xact.c Modified: head/sys/dev/hyperv/include/vmbus_xact.h ============================================================================== --- head/sys/dev/hyperv/include/vmbus_xact.h Thu Nov 24 01:24:26 2016 (r309079) +++ head/sys/dev/hyperv/include/vmbus_xact.h Thu Nov 24 04:58:13 2016 (r309080) @@ -39,6 +39,8 @@ struct vmbus_xact_ctx *vmbus_xact_ctx_cr size_t req_size, size_t resp_size, size_t priv_size); void vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx); +bool vmbus_xact_ctx_orphan(struct vmbus_xact_ctx *ctx); + struct vmbus_xact *vmbus_xact_get(struct vmbus_xact_ctx *ctx, size_t req_len); void vmbus_xact_put(struct vmbus_xact *xact); Modified: head/sys/dev/hyperv/vmbus/vmbus_xact.c ============================================================================== --- head/sys/dev/hyperv/vmbus/vmbus_xact.c Thu Nov 24 01:24:26 2016 (r309079) +++ head/sys/dev/hyperv/vmbus/vmbus_xact.c Thu Nov 24 04:58:13 2016 (r309080) @@ -61,6 +61,7 @@ struct vmbus_xact_ctx { uint32_t xc_flags; /* VMBUS_XACT_CTXF_ */ struct vmbus_xact *xc_free; struct vmbus_xact *xc_active; + struct vmbus_xact *xc_orphan; }; #define VMBUS_XACT_CTXF_DESTROY 0x0001 @@ -72,6 +73,9 @@ static struct vmbus_xact *vmbus_xact_get uint32_t); const void *vmbus_xact_wait1(struct vmbus_xact *, size_t *, bool); +static void vmbus_xact_save_resp(struct vmbus_xact *, + const void *, size_t); +static void vmbus_xact_ctx_free(struct vmbus_xact_ctx *); static struct vmbus_xact * vmbus_xact_alloc(struct vmbus_xact_ctx *ctx, bus_dma_tag_t parent_dtag) @@ -136,6 +140,9 @@ vmbus_xact_ctx_create(bus_dma_tag_t dtag { struct vmbus_xact_ctx *ctx; + KASSERT(req_size > 0, ("request size is 0")); + KASSERT(resp_size > 0, ("response size is 0")); + ctx = malloc(sizeof(*ctx), M_DEVBUF, M_WAITOK | M_ZERO); ctx->xc_req_size = req_size; ctx->xc_resp_size = resp_size; @@ -152,25 +159,46 @@ vmbus_xact_ctx_create(bus_dma_tag_t dtag return (ctx); } -void -vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx) +bool +vmbus_xact_ctx_orphan(struct vmbus_xact_ctx *ctx) { - struct vmbus_xact *xact; - mtx_lock(&ctx->xc_lock); + if (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) { + mtx_unlock(&ctx->xc_lock); + return (false); + } ctx->xc_flags |= VMBUS_XACT_CTXF_DESTROY; mtx_unlock(&ctx->xc_lock); + wakeup(&ctx->xc_free); + wakeup(&ctx->xc_active); - xact = vmbus_xact_get1(ctx, 0); - if (xact == NULL) + ctx->xc_orphan = vmbus_xact_get1(ctx, 0); + if (ctx->xc_orphan == NULL) panic("can't get xact"); + return (true); +} + +static void +vmbus_xact_ctx_free(struct vmbus_xact_ctx *ctx) +{ + KASSERT(ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY, + ("xact ctx was not orphaned")); + KASSERT(ctx->xc_orphan != NULL, ("no orphaned xact")); - vmbus_xact_free(xact); + vmbus_xact_free(ctx->xc_orphan); mtx_destroy(&ctx->xc_lock); free(ctx, M_DEVBUF); } +void +vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx) +{ + + vmbus_xact_ctx_orphan(ctx); + vmbus_xact_ctx_free(ctx); +} + struct vmbus_xact * vmbus_xact_get(struct vmbus_xact_ctx *ctx, size_t req_len) { @@ -259,7 +287,8 @@ vmbus_xact_wait1(struct vmbus_xact *xact mtx_lock(&ctx->xc_lock); KASSERT(ctx->xc_active == xact, ("xact mismatch")); - while (xact->x_resp == NULL) { + 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); @@ -269,6 +298,20 @@ vmbus_xact_wait1(struct vmbus_xact *xact mtx_lock(&ctx->xc_lock); } } + KASSERT(ctx->xc_active == xact, ("xact trashed")); + + if ((ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) && xact->x_resp == NULL) { + uint8_t b = 0; + + /* + * Orphaned and no response was received yet; fake up + * an one byte response. + */ + printf("vmbus: xact ctx was orphaned w/ pending xact\n"); + vmbus_xact_save_resp(ctx->xc_active, &b, sizeof(b)); + } + KASSERT(xact->x_resp != NULL, ("no response")); + ctx->xc_active = NULL; resp = xact->x_resp; @@ -317,19 +360,47 @@ void vmbus_xact_wakeup(struct vmbus_xact *xact, const void *data, size_t dlen) { struct vmbus_xact_ctx *ctx = xact->x_ctx; + int do_wakeup = 0; mtx_lock(&ctx->xc_lock); - vmbus_xact_save_resp(xact, data, dlen); + /* + * NOTE: + * xc_active could be NULL, if the ctx has been orphaned. + */ + if (ctx->xc_active != NULL) { + vmbus_xact_save_resp(xact, data, dlen); + do_wakeup = 1; + } else { + KASSERT(ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY, + ("no active xact pending")); + printf("vmbus: drop xact response\n"); + } mtx_unlock(&ctx->xc_lock); - wakeup(&ctx->xc_active); + + if (do_wakeup) + wakeup(&ctx->xc_active); } void vmbus_xact_ctx_wakeup(struct vmbus_xact_ctx *ctx, const void *data, size_t dlen) { + int do_wakeup = 0; + mtx_lock(&ctx->xc_lock); - KASSERT(ctx->xc_active != NULL, ("no pending xact")); - vmbus_xact_save_resp(ctx->xc_active, data, dlen); + /* + * NOTE: + * xc_active could be NULL, if the ctx has been orphaned. + */ + if (ctx->xc_active != NULL) { + vmbus_xact_save_resp(ctx->xc_active, data, dlen); + do_wakeup = 1; + } else { + KASSERT(ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY, + ("no active xact pending")); + printf("vmbus: drop xact response\n"); + } mtx_unlock(&ctx->xc_lock); - wakeup(&ctx->xc_active); + + if (do_wakeup) + wakeup(&ctx->xc_active); }