Deleted Added
full compact
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}