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
This commit is contained in:
parent
a839bad498
commit
3298d7d4fd
@ -39,6 +39,8 @@ struct vmbus_xact_ctx *vmbus_xact_ctx_create(bus_dma_tag_t dtag,
|
||||
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);
|
||||
|
@ -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_get1(struct vmbus_xact_ctx *,
|
||||
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, size_t req_size, size_t resp_size,
|
||||
{
|
||||
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,23 +159,44 @@ vmbus_xact_ctx_create(bus_dma_tag_t dtag, size_t req_size, size_t resp_size,
|
||||
return (ctx);
|
||||
}
|
||||
|
||||
bool
|
||||
vmbus_xact_ctx_orphan(struct vmbus_xact_ctx *ctx)
|
||||
{
|
||||
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);
|
||||
|
||||
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(ctx->xc_orphan);
|
||||
mtx_destroy(&ctx->xc_lock);
|
||||
free(ctx, M_DEVBUF);
|
||||
}
|
||||
|
||||
void
|
||||
vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx)
|
||||
{
|
||||
struct vmbus_xact *xact;
|
||||
|
||||
mtx_lock(&ctx->xc_lock);
|
||||
ctx->xc_flags |= VMBUS_XACT_CTXF_DESTROY;
|
||||
mtx_unlock(&ctx->xc_lock);
|
||||
wakeup(&ctx->xc_free);
|
||||
|
||||
xact = vmbus_xact_get1(ctx, 0);
|
||||
if (xact == NULL)
|
||||
panic("can't get xact");
|
||||
|
||||
vmbus_xact_free(xact);
|
||||
mtx_destroy(&ctx->xc_lock);
|
||||
free(ctx, M_DEVBUF);
|
||||
vmbus_xact_ctx_orphan(ctx);
|
||||
vmbus_xact_ctx_free(ctx);
|
||||
}
|
||||
|
||||
struct vmbus_xact *
|
||||
@ -259,7 +287,8 @@ vmbus_xact_wait1(struct vmbus_xact *xact, size_t *resp_len,
|
||||
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, size_t *resp_len,
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user