Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/vmbus/vmbus_xact.c
Show All 33 Lines | |||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <dev/hyperv/include/hyperv_busdma.h> | #include <dev/hyperv/include/hyperv_busdma.h> | ||||
#include <dev/hyperv/include/vmbus_xact.h> | #include <dev/hyperv/include/vmbus_xact.h> | ||||
struct vmbus_xact { | struct vmbus_xact { | ||||
struct vmbus_xact_ctx *x_ctx; | struct vmbus_xact_ctx *x_ctx; | ||||
void *x_priv; | |||||
void *x_req; | void *x_req; | ||||
struct hyperv_dma x_req_dma; | struct hyperv_dma x_req_dma; | ||||
const void *x_resp; | const void *x_resp; | ||||
size_t x_resp_len; | size_t x_resp_len; | ||||
void *x_resp0; | void *x_resp0; | ||||
}; | }; | ||||
struct vmbus_xact_ctx { | struct vmbus_xact_ctx { | ||||
uint32_t xc_flags; | uint32_t xc_flags; | ||||
size_t xc_req_size; | size_t xc_req_size; | ||||
size_t xc_resp_size; | size_t xc_resp_size; | ||||
size_t xc_priv_size; | |||||
struct vmbus_xact *xc_free; | struct vmbus_xact *xc_free; | ||||
struct mtx xc_free_lock; | struct mtx xc_free_lock; | ||||
struct vmbus_xact *xc_active; | struct vmbus_xact *xc_active; | ||||
struct mtx xc_active_lock; | struct mtx xc_active_lock; | ||||
}; | }; | ||||
Show All 15 Lines | vmbus_xact_alloc(struct vmbus_xact_ctx *ctx, bus_dma_tag_t parent_dtag) | ||||
/* XXX assume that page aligned is enough */ | /* XXX assume that page aligned is enough */ | ||||
xact->x_req = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0, | xact->x_req = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0, | ||||
ctx->xc_req_size, &xact->x_req_dma, BUS_DMA_WAITOK); | ctx->xc_req_size, &xact->x_req_dma, BUS_DMA_WAITOK); | ||||
if (xact->x_req == NULL) { | if (xact->x_req == NULL) { | ||||
free(xact, M_DEVBUF); | free(xact, M_DEVBUF); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if (ctx->xc_priv_size != 0) | |||||
xact->x_priv = malloc(ctx->xc_priv_size, M_DEVBUF, M_WAITOK); | |||||
xact->x_resp0 = malloc(ctx->xc_resp_size, M_DEVBUF, M_WAITOK); | xact->x_resp0 = malloc(ctx->xc_resp_size, M_DEVBUF, M_WAITOK); | ||||
return (xact); | return (xact); | ||||
} | } | ||||
static void | static void | ||||
vmbus_xact_free(struct vmbus_xact *xact) | vmbus_xact_free(struct vmbus_xact *xact) | ||||
{ | { | ||||
hyperv_dmamem_free(&xact->x_req_dma, xact->x_req); | hyperv_dmamem_free(&xact->x_req_dma, xact->x_req); | ||||
free(xact->x_resp0, M_DEVBUF); | free(xact->x_resp0, M_DEVBUF); | ||||
if (xact->x_priv != NULL) | |||||
free(xact->x_priv, M_DEVBUF); | |||||
free(xact, M_DEVBUF); | free(xact, M_DEVBUF); | ||||
} | } | ||||
static struct vmbus_xact * | static struct vmbus_xact * | ||||
vmbus_xact_get1(struct vmbus_xact_ctx *ctx, uint32_t dtor_flag) | vmbus_xact_get1(struct vmbus_xact_ctx *ctx, uint32_t dtor_flag) | ||||
{ | { | ||||
struct vmbus_xact *xact; | struct vmbus_xact *xact; | ||||
Show All 12 Lines | vmbus_xact_get1(struct vmbus_xact_ctx *ctx, uint32_t dtor_flag) | ||||
} | } | ||||
mtx_unlock(&ctx->xc_free_lock); | mtx_unlock(&ctx->xc_free_lock); | ||||
return (xact); | return (xact); | ||||
} | } | ||||
struct vmbus_xact_ctx * | struct vmbus_xact_ctx * | ||||
vmbus_xact_ctx_create(bus_dma_tag_t dtag, size_t req_size, size_t resp_size) | vmbus_xact_ctx_create(bus_dma_tag_t dtag, size_t req_size, size_t resp_size, | ||||
size_t priv_size) | |||||
{ | { | ||||
struct vmbus_xact_ctx *ctx; | struct vmbus_xact_ctx *ctx; | ||||
ctx = malloc(sizeof(*ctx), M_DEVBUF, M_WAITOK | M_ZERO); | ctx = malloc(sizeof(*ctx), M_DEVBUF, M_WAITOK | M_ZERO); | ||||
ctx->xc_req_size = req_size; | ctx->xc_req_size = req_size; | ||||
ctx->xc_resp_size = resp_size; | ctx->xc_resp_size = resp_size; | ||||
ctx->xc_priv_size = priv_size; | |||||
ctx->xc_free = vmbus_xact_alloc(ctx, dtag); | ctx->xc_free = vmbus_xact_alloc(ctx, dtag); | ||||
if (ctx->xc_free == NULL) { | if (ctx->xc_free == NULL) { | ||||
free(ctx, M_DEVBUF); | free(ctx, M_DEVBUF); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
mtx_init(&ctx->xc_free_lock, "vmbus xact free", NULL, MTX_DEF); | mtx_init(&ctx->xc_free_lock, "vmbus xact free", NULL, MTX_DEF); | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | |||||
bus_addr_t | bus_addr_t | ||||
vmbus_xact_req_paddr(const struct vmbus_xact *xact) | vmbus_xact_req_paddr(const struct vmbus_xact *xact) | ||||
{ | { | ||||
return (xact->x_req_dma.hv_paddr); | return (xact->x_req_dma.hv_paddr); | ||||
} | } | ||||
void * | |||||
vmbus_xact_priv(const struct vmbus_xact *xact, size_t priv_len) | |||||
{ | |||||
if (priv_len > xact->x_ctx->xc_priv_size) | |||||
panic("invalid priv size %zu", priv_len); | |||||
return (xact->x_priv); | |||||
} | |||||
void | void | ||||
vmbus_xact_activate(struct vmbus_xact *xact) | vmbus_xact_activate(struct vmbus_xact *xact) | ||||
{ | { | ||||
struct vmbus_xact_ctx *ctx = xact->x_ctx; | struct vmbus_xact_ctx *ctx = xact->x_ctx; | ||||
KASSERT(xact->x_resp == NULL, ("xact has pending response")); | KASSERT(xact->x_resp == NULL, ("xact has pending response")); | ||||
mtx_lock(&ctx->xc_active_lock); | mtx_lock(&ctx->xc_active_lock); | ||||
Show All 31 Lines | vmbus_xact_wait(struct vmbus_xact *xact, size_t *resp_len) | ||||
resp = xact->x_resp; | resp = xact->x_resp; | ||||
*resp_len = xact->x_resp_len; | *resp_len = xact->x_resp_len; | ||||
mtx_unlock(&ctx->xc_active_lock); | mtx_unlock(&ctx->xc_active_lock); | ||||
return (resp); | return (resp); | ||||
} | } | ||||
void | static void | ||||
vmbus_xact_wakeup(struct vmbus_xact *xact, const void *data, size_t dlen) | vmbus_xact_save_resp(struct vmbus_xact *xact, const void *data, size_t dlen) | ||||
{ | { | ||||
struct vmbus_xact_ctx *ctx = xact->x_ctx; | struct vmbus_xact_ctx *ctx = xact->x_ctx; | ||||
size_t cplen = dlen; | size_t cplen = dlen; | ||||
mtx_assert(&ctx->xc_active_lock, MA_OWNED); | |||||
if (cplen > ctx->xc_resp_size) { | if (cplen > ctx->xc_resp_size) { | ||||
printf("vmbus: xact response truncated %zu -> %zu\n", | printf("vmbus: xact response truncated %zu -> %zu\n", | ||||
cplen, ctx->xc_resp_size); | cplen, ctx->xc_resp_size); | ||||
cplen = ctx->xc_resp_size; | cplen = ctx->xc_resp_size; | ||||
} | } | ||||
mtx_lock(&ctx->xc_active_lock); | |||||
KASSERT(ctx->xc_active == xact, ("xact mismatch")); | KASSERT(ctx->xc_active == xact, ("xact mismatch")); | ||||
memcpy(xact->x_resp0, data, cplen); | memcpy(xact->x_resp0, data, cplen); | ||||
xact->x_resp_len = cplen; | xact->x_resp_len = cplen; | ||||
xact->x_resp = xact->x_resp0; | xact->x_resp = xact->x_resp0; | ||||
} | |||||
void | |||||
vmbus_xact_wakeup(struct vmbus_xact *xact, const void *data, size_t dlen) | |||||
{ | |||||
struct vmbus_xact_ctx *ctx = xact->x_ctx; | |||||
mtx_lock(&ctx->xc_active_lock); | |||||
vmbus_xact_save_resp(xact, data, dlen); | |||||
mtx_unlock(&ctx->xc_active_lock); | |||||
wakeup(&ctx->xc_active); | |||||
} | |||||
void | |||||
vmbus_xact_ctx_wakeup(struct vmbus_xact_ctx *ctx, const void *data, size_t dlen) | |||||
{ | |||||
mtx_lock(&ctx->xc_active_lock); | |||||
KASSERT(ctx->xc_active != NULL, ("no pending xact")); | |||||
vmbus_xact_save_resp(ctx->xc_active, data, dlen); | |||||
mtx_unlock(&ctx->xc_active_lock); | mtx_unlock(&ctx->xc_active_lock); | ||||
wakeup(&ctx->xc_active); | wakeup(&ctx->xc_active); | ||||
} | } |