vmbus_xact.c (311356) | vmbus_xact.c (311359) |
---|---|
1/*- 2 * Copyright (c) 2016 Microsoft Corp. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2016 Microsoft Corp. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: stable/11/sys/dev/hyperv/vmbus/vmbus_xact.c 311356 2017-01-05 03:32:13Z sephe $"); | 28__FBSDID("$FreeBSD: stable/11/sys/dev/hyperv/vmbus/vmbus_xact.c 311359 2017-01-05 04:22:03Z sephe $"); |
29 30#include <sys/param.h> 31#include <sys/lock.h> 32#include <sys/malloc.h> 33#include <sys/mutex.h> 34#include <sys/proc.h> 35#include <sys/systm.h> 36 --- 8 unchanged lines hidden (view full) --- 45 struct hyperv_dma x_req_dma; 46 47 const void *x_resp; 48 size_t x_resp_len; 49 void *x_resp0; 50}; 51 52struct vmbus_xact_ctx { | 29 30#include <sys/param.h> 31#include <sys/lock.h> 32#include <sys/malloc.h> 33#include <sys/mutex.h> 34#include <sys/proc.h> 35#include <sys/systm.h> 36 --- 8 unchanged lines hidden (view full) --- 45 struct hyperv_dma x_req_dma; 46 47 const void *x_resp; 48 size_t x_resp_len; 49 void *x_resp0; 50}; 51 52struct vmbus_xact_ctx { |
53 uint32_t xc_flags; | |
54 size_t xc_req_size; 55 size_t xc_resp_size; 56 size_t xc_priv_size; 57 | 53 size_t xc_req_size; 54 size_t xc_resp_size; 55 size_t xc_priv_size; 56 |
57 struct mtx xc_lock; 58 /* 59 * Protected by xc_lock. 60 */ 61 uint32_t xc_flags; /* VMBUS_XACT_CTXF_ */ |
|
58 struct vmbus_xact *xc_free; | 62 struct vmbus_xact *xc_free; |
59 struct mtx xc_free_lock; 60 | |
61 struct vmbus_xact *xc_active; | 63 struct vmbus_xact *xc_active; |
62 struct mtx xc_active_lock; | 64 struct vmbus_xact *xc_orphan; |
63}; 64 65#define VMBUS_XACT_CTXF_DESTROY 0x0001 66 67static struct vmbus_xact *vmbus_xact_alloc(struct vmbus_xact_ctx *, 68 bus_dma_tag_t); 69static void vmbus_xact_free(struct vmbus_xact *); 70static struct vmbus_xact *vmbus_xact_get1(struct vmbus_xact_ctx *, 71 uint32_t); 72const void *vmbus_xact_wait1(struct vmbus_xact *, size_t *, 73 bool); | 65}; 66 67#define VMBUS_XACT_CTXF_DESTROY 0x0001 68 69static struct vmbus_xact *vmbus_xact_alloc(struct vmbus_xact_ctx *, 70 bus_dma_tag_t); 71static void vmbus_xact_free(struct vmbus_xact *); 72static struct vmbus_xact *vmbus_xact_get1(struct vmbus_xact_ctx *, 73 uint32_t); 74const void *vmbus_xact_wait1(struct vmbus_xact *, size_t *, 75 bool); |
76static void vmbus_xact_save_resp(struct vmbus_xact *, 77 const void *, size_t); 78static void vmbus_xact_ctx_free(struct vmbus_xact_ctx *); |
|
74 75static struct vmbus_xact * 76vmbus_xact_alloc(struct vmbus_xact_ctx *ctx, bus_dma_tag_t parent_dtag) 77{ 78 struct vmbus_xact *xact; 79 80 xact = malloc(sizeof(*xact), M_DEVBUF, M_WAITOK | M_ZERO); 81 xact->x_ctx = ctx; --- 23 unchanged lines hidden (view full) --- 105 free(xact, M_DEVBUF); 106} 107 108static struct vmbus_xact * 109vmbus_xact_get1(struct vmbus_xact_ctx *ctx, uint32_t dtor_flag) 110{ 111 struct vmbus_xact *xact; 112 | 79 80static struct vmbus_xact * 81vmbus_xact_alloc(struct vmbus_xact_ctx *ctx, bus_dma_tag_t parent_dtag) 82{ 83 struct vmbus_xact *xact; 84 85 xact = malloc(sizeof(*xact), M_DEVBUF, M_WAITOK | M_ZERO); 86 xact->x_ctx = ctx; --- 23 unchanged lines hidden (view full) --- 110 free(xact, M_DEVBUF); 111} 112 113static struct vmbus_xact * 114vmbus_xact_get1(struct vmbus_xact_ctx *ctx, uint32_t dtor_flag) 115{ 116 struct vmbus_xact *xact; 117 |
113 mtx_lock(&ctx->xc_free_lock); | 118 mtx_lock(&ctx->xc_lock); |
114 115 while ((ctx->xc_flags & dtor_flag) == 0 && ctx->xc_free == NULL) | 119 120 while ((ctx->xc_flags & dtor_flag) == 0 && ctx->xc_free == NULL) |
116 mtx_sleep(&ctx->xc_free, &ctx->xc_free_lock, 0, "gxact", 0); | 121 mtx_sleep(&ctx->xc_free, &ctx->xc_lock, 0, "gxact", 0); |
117 if (ctx->xc_flags & dtor_flag) { 118 /* Being destroyed */ 119 xact = NULL; 120 } else { 121 xact = ctx->xc_free; 122 KASSERT(xact != NULL, ("no free xact")); 123 KASSERT(xact->x_resp == NULL, ("xact has pending response")); 124 ctx->xc_free = NULL; 125 } 126 | 122 if (ctx->xc_flags & dtor_flag) { 123 /* Being destroyed */ 124 xact = NULL; 125 } else { 126 xact = ctx->xc_free; 127 KASSERT(xact != NULL, ("no free xact")); 128 KASSERT(xact->x_resp == NULL, ("xact has pending response")); 129 ctx->xc_free = NULL; 130 } 131 |
127 mtx_unlock(&ctx->xc_free_lock); | 132 mtx_unlock(&ctx->xc_lock); |
128 129 return (xact); 130} 131 132struct vmbus_xact_ctx * 133vmbus_xact_ctx_create(bus_dma_tag_t dtag, size_t req_size, size_t resp_size, 134 size_t priv_size) 135{ 136 struct vmbus_xact_ctx *ctx; 137 | 133 134 return (xact); 135} 136 137struct vmbus_xact_ctx * 138vmbus_xact_ctx_create(bus_dma_tag_t dtag, size_t req_size, size_t resp_size, 139 size_t priv_size) 140{ 141 struct vmbus_xact_ctx *ctx; 142 |
143 KASSERT(req_size > 0, ("request size is 0")); 144 KASSERT(resp_size > 0, ("response size is 0")); 145 |
|
138 ctx = malloc(sizeof(*ctx), M_DEVBUF, M_WAITOK | M_ZERO); 139 ctx->xc_req_size = req_size; 140 ctx->xc_resp_size = resp_size; 141 ctx->xc_priv_size = priv_size; 142 143 ctx->xc_free = vmbus_xact_alloc(ctx, dtag); 144 if (ctx->xc_free == NULL) { 145 free(ctx, M_DEVBUF); 146 return (NULL); 147 } 148 | 146 ctx = malloc(sizeof(*ctx), M_DEVBUF, M_WAITOK | M_ZERO); 147 ctx->xc_req_size = req_size; 148 ctx->xc_resp_size = resp_size; 149 ctx->xc_priv_size = priv_size; 150 151 ctx->xc_free = vmbus_xact_alloc(ctx, dtag); 152 if (ctx->xc_free == NULL) { 153 free(ctx, M_DEVBUF); 154 return (NULL); 155 } 156 |
149 mtx_init(&ctx->xc_free_lock, "vmbus xact free", NULL, MTX_DEF); 150 mtx_init(&ctx->xc_active_lock, "vmbus xact active", NULL, MTX_DEF); | 157 mtx_init(&ctx->xc_lock, "vmbus xact", NULL, MTX_DEF); |
151 152 return (ctx); 153} 154 | 158 159 return (ctx); 160} 161 |
155void 156vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx) | 162bool 163vmbus_xact_ctx_orphan(struct vmbus_xact_ctx *ctx) |
157{ | 164{ |
158 struct vmbus_xact *xact; 159 160 mtx_lock(&ctx->xc_free_lock); | 165 mtx_lock(&ctx->xc_lock); 166 if (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) { 167 mtx_unlock(&ctx->xc_lock); 168 return (false); 169 } |
161 ctx->xc_flags |= VMBUS_XACT_CTXF_DESTROY; | 170 ctx->xc_flags |= VMBUS_XACT_CTXF_DESTROY; |
162 mtx_unlock(&ctx->xc_free_lock); | 171 mtx_unlock(&ctx->xc_lock); 172 |
163 wakeup(&ctx->xc_free); | 173 wakeup(&ctx->xc_free); |
174 wakeup(&ctx->xc_active); |
|
164 | 175 |
165 xact = vmbus_xact_get1(ctx, 0); 166 if (xact == NULL) | 176 ctx->xc_orphan = vmbus_xact_get1(ctx, 0); 177 if (ctx->xc_orphan == NULL) |
167 panic("can't get xact"); | 178 panic("can't get xact"); |
179 return (true); 180} |
|
168 | 181 |
169 vmbus_xact_free(xact); 170 mtx_destroy(&ctx->xc_free_lock); 171 mtx_destroy(&ctx->xc_active_lock); | 182static void 183vmbus_xact_ctx_free(struct vmbus_xact_ctx *ctx) 184{ 185 KASSERT(ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY, 186 ("xact ctx was not orphaned")); 187 KASSERT(ctx->xc_orphan != NULL, ("no orphaned xact")); 188 189 vmbus_xact_free(ctx->xc_orphan); 190 mtx_destroy(&ctx->xc_lock); |
172 free(ctx, M_DEVBUF); 173} 174 | 191 free(ctx, M_DEVBUF); 192} 193 |
194void 195vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx) 196{ 197 198 vmbus_xact_ctx_orphan(ctx); 199 vmbus_xact_ctx_free(ctx); 200} 201 |
|
175struct vmbus_xact * 176vmbus_xact_get(struct vmbus_xact_ctx *ctx, size_t req_len) 177{ 178 struct vmbus_xact *xact; 179 180 if (req_len > ctx->xc_req_size) 181 panic("invalid request size %zu", req_len); 182 --- 8 unchanged lines hidden (view full) --- 191void 192vmbus_xact_put(struct vmbus_xact *xact) 193{ 194 struct vmbus_xact_ctx *ctx = xact->x_ctx; 195 196 KASSERT(ctx->xc_active == NULL, ("pending active xact")); 197 xact->x_resp = NULL; 198 | 202struct vmbus_xact * 203vmbus_xact_get(struct vmbus_xact_ctx *ctx, size_t req_len) 204{ 205 struct vmbus_xact *xact; 206 207 if (req_len > ctx->xc_req_size) 208 panic("invalid request size %zu", req_len); 209 --- 8 unchanged lines hidden (view full) --- 218void 219vmbus_xact_put(struct vmbus_xact *xact) 220{ 221 struct vmbus_xact_ctx *ctx = xact->x_ctx; 222 223 KASSERT(ctx->xc_active == NULL, ("pending active xact")); 224 xact->x_resp = NULL; 225 |
199 mtx_lock(&ctx->xc_free_lock); | 226 mtx_lock(&ctx->xc_lock); |
200 KASSERT(ctx->xc_free == NULL, ("has free xact")); 201 ctx->xc_free = xact; | 227 KASSERT(ctx->xc_free == NULL, ("has free xact")); 228 ctx->xc_free = xact; |
202 mtx_unlock(&ctx->xc_free_lock); | 229 mtx_unlock(&ctx->xc_lock); |
203 wakeup(&ctx->xc_free); 204} 205 206void * 207vmbus_xact_req_data(const struct vmbus_xact *xact) 208{ 209 210 return (xact->x_req); --- 17 unchanged lines hidden (view full) --- 228 229void 230vmbus_xact_activate(struct vmbus_xact *xact) 231{ 232 struct vmbus_xact_ctx *ctx = xact->x_ctx; 233 234 KASSERT(xact->x_resp == NULL, ("xact has pending response")); 235 | 230 wakeup(&ctx->xc_free); 231} 232 233void * 234vmbus_xact_req_data(const struct vmbus_xact *xact) 235{ 236 237 return (xact->x_req); --- 17 unchanged lines hidden (view full) --- 255 256void 257vmbus_xact_activate(struct vmbus_xact *xact) 258{ 259 struct vmbus_xact_ctx *ctx = xact->x_ctx; 260 261 KASSERT(xact->x_resp == NULL, ("xact has pending response")); 262 |
236 mtx_lock(&ctx->xc_active_lock); | 263 mtx_lock(&ctx->xc_lock); |
237 KASSERT(ctx->xc_active == NULL, ("pending active xact")); 238 ctx->xc_active = xact; | 264 KASSERT(ctx->xc_active == NULL, ("pending active xact")); 265 ctx->xc_active = xact; |
239 mtx_unlock(&ctx->xc_active_lock); | 266 mtx_unlock(&ctx->xc_lock); |
240} 241 242void 243vmbus_xact_deactivate(struct vmbus_xact *xact) 244{ 245 struct vmbus_xact_ctx *ctx = xact->x_ctx; 246 | 267} 268 269void 270vmbus_xact_deactivate(struct vmbus_xact *xact) 271{ 272 struct vmbus_xact_ctx *ctx = xact->x_ctx; 273 |
247 mtx_lock(&ctx->xc_active_lock); | 274 mtx_lock(&ctx->xc_lock); |
248 KASSERT(ctx->xc_active == xact, ("xact mismatch")); 249 ctx->xc_active = NULL; | 275 KASSERT(ctx->xc_active == xact, ("xact mismatch")); 276 ctx->xc_active = NULL; |
250 mtx_unlock(&ctx->xc_active_lock); | 277 mtx_unlock(&ctx->xc_lock); |
251} 252 253const void * 254vmbus_xact_wait1(struct vmbus_xact *xact, size_t *resp_len, 255 bool can_sleep) 256{ 257 struct vmbus_xact_ctx *ctx = xact->x_ctx; 258 const void *resp; 259 | 278} 279 280const void * 281vmbus_xact_wait1(struct vmbus_xact *xact, size_t *resp_len, 282 bool can_sleep) 283{ 284 struct vmbus_xact_ctx *ctx = xact->x_ctx; 285 const void *resp; 286 |
260 mtx_lock(&ctx->xc_active_lock); | 287 mtx_lock(&ctx->xc_lock); |
261 262 KASSERT(ctx->xc_active == xact, ("xact mismatch")); | 288 289 KASSERT(ctx->xc_active == xact, ("xact mismatch")); |
263 while (xact->x_resp == NULL) { | 290 while (xact->x_resp == NULL && 291 (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) == 0) { |
264 if (can_sleep) { | 292 if (can_sleep) { |
265 mtx_sleep(&ctx->xc_active, &ctx->xc_active_lock, 0, | 293 mtx_sleep(&ctx->xc_active, &ctx->xc_lock, 0, |
266 "wxact", 0); 267 } else { | 294 "wxact", 0); 295 } else { |
268 mtx_unlock(&ctx->xc_active_lock); | 296 mtx_unlock(&ctx->xc_lock); |
269 DELAY(1000); | 297 DELAY(1000); |
270 mtx_lock(&ctx->xc_active_lock); | 298 mtx_lock(&ctx->xc_lock); |
271 } 272 } | 299 } 300 } |
301 KASSERT(ctx->xc_active == xact, ("xact trashed")); 302 303 if ((ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) && xact->x_resp == NULL) { 304 uint8_t b = 0; 305 306 /* 307 * Orphaned and no response was received yet; fake up 308 * an one byte response. 309 */ 310 printf("vmbus: xact ctx was orphaned w/ pending xact\n"); 311 vmbus_xact_save_resp(ctx->xc_active, &b, sizeof(b)); 312 } 313 KASSERT(xact->x_resp != NULL, ("no response")); 314 |
|
273 ctx->xc_active = NULL; 274 275 resp = xact->x_resp; 276 *resp_len = xact->x_resp_len; 277 | 315 ctx->xc_active = NULL; 316 317 resp = xact->x_resp; 318 *resp_len = xact->x_resp_len; 319 |
278 mtx_unlock(&ctx->xc_active_lock); | 320 mtx_unlock(&ctx->xc_lock); |
279 280 return (resp); 281} 282 283const void * 284vmbus_xact_wait(struct vmbus_xact *xact, size_t *resp_len) 285{ 286 --- 8 unchanged lines hidden (view full) --- 295} 296 297static void 298vmbus_xact_save_resp(struct vmbus_xact *xact, const void *data, size_t dlen) 299{ 300 struct vmbus_xact_ctx *ctx = xact->x_ctx; 301 size_t cplen = dlen; 302 | 321 322 return (resp); 323} 324 325const void * 326vmbus_xact_wait(struct vmbus_xact *xact, size_t *resp_len) 327{ 328 --- 8 unchanged lines hidden (view full) --- 337} 338 339static void 340vmbus_xact_save_resp(struct vmbus_xact *xact, const void *data, size_t dlen) 341{ 342 struct vmbus_xact_ctx *ctx = xact->x_ctx; 343 size_t cplen = dlen; 344 |
303 mtx_assert(&ctx->xc_active_lock, MA_OWNED); | 345 mtx_assert(&ctx->xc_lock, MA_OWNED); |
304 305 if (cplen > ctx->xc_resp_size) { 306 printf("vmbus: xact response truncated %zu -> %zu\n", 307 cplen, ctx->xc_resp_size); 308 cplen = ctx->xc_resp_size; 309 } 310 311 KASSERT(ctx->xc_active == xact, ("xact mismatch")); 312 memcpy(xact->x_resp0, data, cplen); 313 xact->x_resp_len = cplen; 314 xact->x_resp = xact->x_resp0; 315} 316 317void 318vmbus_xact_wakeup(struct vmbus_xact *xact, const void *data, size_t dlen) 319{ 320 struct vmbus_xact_ctx *ctx = xact->x_ctx; | 346 347 if (cplen > ctx->xc_resp_size) { 348 printf("vmbus: xact response truncated %zu -> %zu\n", 349 cplen, ctx->xc_resp_size); 350 cplen = ctx->xc_resp_size; 351 } 352 353 KASSERT(ctx->xc_active == xact, ("xact mismatch")); 354 memcpy(xact->x_resp0, data, cplen); 355 xact->x_resp_len = cplen; 356 xact->x_resp = xact->x_resp0; 357} 358 359void 360vmbus_xact_wakeup(struct vmbus_xact *xact, const void *data, size_t dlen) 361{ 362 struct vmbus_xact_ctx *ctx = xact->x_ctx; |
363 int do_wakeup = 0; |
|
321 | 364 |
322 mtx_lock(&ctx->xc_active_lock); 323 vmbus_xact_save_resp(xact, data, dlen); 324 mtx_unlock(&ctx->xc_active_lock); 325 wakeup(&ctx->xc_active); | 365 mtx_lock(&ctx->xc_lock); 366 /* 367 * NOTE: 368 * xc_active could be NULL, if the ctx has been orphaned. 369 */ 370 if (ctx->xc_active != NULL) { 371 vmbus_xact_save_resp(xact, data, dlen); 372 do_wakeup = 1; 373 } else { 374 KASSERT(ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY, 375 ("no active xact pending")); 376 printf("vmbus: drop xact response\n"); 377 } 378 mtx_unlock(&ctx->xc_lock); 379 380 if (do_wakeup) 381 wakeup(&ctx->xc_active); |
326} 327 328void 329vmbus_xact_ctx_wakeup(struct vmbus_xact_ctx *ctx, const void *data, size_t dlen) 330{ | 382} 383 384void 385vmbus_xact_ctx_wakeup(struct vmbus_xact_ctx *ctx, const void *data, size_t dlen) 386{ |
331 mtx_lock(&ctx->xc_active_lock); 332 KASSERT(ctx->xc_active != NULL, ("no pending xact")); 333 vmbus_xact_save_resp(ctx->xc_active, data, dlen); 334 mtx_unlock(&ctx->xc_active_lock); 335 wakeup(&ctx->xc_active); | 387 int do_wakeup = 0; 388 389 mtx_lock(&ctx->xc_lock); 390 /* 391 * NOTE: 392 * xc_active could be NULL, if the ctx has been orphaned. 393 */ 394 if (ctx->xc_active != NULL) { 395 vmbus_xact_save_resp(ctx->xc_active, data, dlen); 396 do_wakeup = 1; 397 } else { 398 KASSERT(ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY, 399 ("no active xact pending")); 400 printf("vmbus: drop xact response\n"); 401 } 402 mtx_unlock(&ctx->xc_lock); 403 404 if (do_wakeup) 405 wakeup(&ctx->xc_active); |
336} | 406} |