]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/hyperv/vmbus/vmbus_chan.c
MFC 309236,309237
[FreeBSD/stable/10.git] / sys / dev / hyperv / vmbus / vmbus_chan.c
1 /*-
2  * Copyright (c) 2009-2012,2016 Microsoft Corp.
3  * Copyright (c) 2012 NetApp Inc.
4  * Copyright (c) 2012 Citrix Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/kernel.h>
35 #include <sys/lock.h>
36 #include <sys/malloc.h>
37 #include <sys/mutex.h>
38 #include <sys/smp.h>
39 #include <sys/sysctl.h>
40 #include <sys/systm.h>
41
42 #include <machine/atomic.h>
43 #include <machine/stdarg.h>
44
45 #include <dev/hyperv/include/hyperv_busdma.h>
46 #include <dev/hyperv/include/vmbus_xact.h>
47 #include <dev/hyperv/vmbus/hyperv_var.h>
48 #include <dev/hyperv/vmbus/vmbus_reg.h>
49 #include <dev/hyperv/vmbus/vmbus_var.h>
50 #include <dev/hyperv/vmbus/vmbus_brvar.h>
51 #include <dev/hyperv/vmbus/vmbus_chanvar.h>
52
53 static void                     vmbus_chan_update_evtflagcnt(
54                                     struct vmbus_softc *,
55                                     const struct vmbus_channel *);
56 static int                      vmbus_chan_close_internal(
57                                     struct vmbus_channel *);
58 static int                      vmbus_chan_sysctl_mnf(SYSCTL_HANDLER_ARGS);
59 static void                     vmbus_chan_sysctl_create(
60                                     struct vmbus_channel *);
61 static struct vmbus_channel     *vmbus_chan_alloc(struct vmbus_softc *);
62 static void                     vmbus_chan_free(struct vmbus_channel *);
63 static int                      vmbus_chan_add(struct vmbus_channel *);
64 static void                     vmbus_chan_cpu_default(struct vmbus_channel *);
65 static int                      vmbus_chan_release(struct vmbus_channel *);
66 static void                     vmbus_chan_set_chmap(struct vmbus_channel *);
67 static void                     vmbus_chan_clear_chmap(struct vmbus_channel *);
68 static void                     vmbus_chan_detach(struct vmbus_channel *);
69 static bool                     vmbus_chan_wait_revoke(
70                                     const struct vmbus_channel *);
71
72 static void                     vmbus_chan_ins_prilist(struct vmbus_softc *,
73                                     struct vmbus_channel *);
74 static void                     vmbus_chan_rem_prilist(struct vmbus_softc *,
75                                     struct vmbus_channel *);
76 static void                     vmbus_chan_ins_list(struct vmbus_softc *,
77                                     struct vmbus_channel *);
78 static void                     vmbus_chan_rem_list(struct vmbus_softc *,
79                                     struct vmbus_channel *);
80 static void                     vmbus_chan_ins_sublist(struct vmbus_channel *,
81                                     struct vmbus_channel *);
82 static void                     vmbus_chan_rem_sublist(struct vmbus_channel *,
83                                     struct vmbus_channel *);
84
85 static void                     vmbus_chan_task(void *, int);
86 static void                     vmbus_chan_task_nobatch(void *, int);
87 static void                     vmbus_chan_clrchmap_task(void *, int);
88 static void                     vmbus_prichan_attach_task(void *, int);
89 static void                     vmbus_subchan_attach_task(void *, int);
90 static void                     vmbus_prichan_detach_task(void *, int);
91 static void                     vmbus_subchan_detach_task(void *, int);
92
93 static void                     vmbus_chan_msgproc_choffer(struct vmbus_softc *,
94                                     const struct vmbus_message *);
95 static void                     vmbus_chan_msgproc_chrescind(
96                                     struct vmbus_softc *,
97                                     const struct vmbus_message *);
98
99 static int                      vmbus_chan_printf(const struct vmbus_channel *,
100                                     const char *, ...) __printflike(2, 3);
101
102 /*
103  * Vmbus channel message processing.
104  */
105 static const vmbus_chanmsg_proc_t
106 vmbus_chan_msgprocs[VMBUS_CHANMSG_TYPE_MAX] = {
107         VMBUS_CHANMSG_PROC(CHOFFER,     vmbus_chan_msgproc_choffer),
108         VMBUS_CHANMSG_PROC(CHRESCIND,   vmbus_chan_msgproc_chrescind),
109
110         VMBUS_CHANMSG_PROC_WAKEUP(CHOPEN_RESP),
111         VMBUS_CHANMSG_PROC_WAKEUP(GPADL_CONNRESP),
112         VMBUS_CHANMSG_PROC_WAKEUP(GPADL_DISCONNRESP)
113 };
114
115 /*
116  * Notify host that there are data pending on our TX bufring.
117  */
118 static __inline void
119 vmbus_chan_signal_tx(const struct vmbus_channel *chan)
120 {
121         atomic_set_long(chan->ch_evtflag, chan->ch_evtflag_mask);
122         if (chan->ch_txflags & VMBUS_CHAN_TXF_HASMNF)
123                 atomic_set_int(chan->ch_montrig, chan->ch_montrig_mask);
124         else
125                 hypercall_signal_event(chan->ch_monprm_dma.hv_paddr);
126 }
127
128 static void
129 vmbus_chan_ins_prilist(struct vmbus_softc *sc, struct vmbus_channel *chan)
130 {
131
132         mtx_assert(&sc->vmbus_prichan_lock, MA_OWNED);
133         if (atomic_testandset_int(&chan->ch_stflags,
134             VMBUS_CHAN_ST_ONPRIL_SHIFT))
135                 panic("channel is already on the prilist");
136         TAILQ_INSERT_TAIL(&sc->vmbus_prichans, chan, ch_prilink);
137 }
138
139 static void
140 vmbus_chan_rem_prilist(struct vmbus_softc *sc, struct vmbus_channel *chan)
141 {
142
143         mtx_assert(&sc->vmbus_prichan_lock, MA_OWNED);
144         if (atomic_testandclear_int(&chan->ch_stflags,
145             VMBUS_CHAN_ST_ONPRIL_SHIFT) == 0)
146                 panic("channel is not on the prilist");
147         TAILQ_REMOVE(&sc->vmbus_prichans, chan, ch_prilink);
148 }
149
150 static void
151 vmbus_chan_ins_sublist(struct vmbus_channel *prichan,
152     struct vmbus_channel *chan)
153 {
154
155         mtx_assert(&prichan->ch_subchan_lock, MA_OWNED);
156
157         if (atomic_testandset_int(&chan->ch_stflags,
158             VMBUS_CHAN_ST_ONSUBL_SHIFT))
159                 panic("channel is already on the sublist");
160         TAILQ_INSERT_TAIL(&prichan->ch_subchans, chan, ch_sublink);
161
162         /* Bump sub-channel count. */
163         prichan->ch_subchan_cnt++;
164 }
165
166 static void
167 vmbus_chan_rem_sublist(struct vmbus_channel *prichan,
168     struct vmbus_channel *chan)
169 {
170
171         mtx_assert(&prichan->ch_subchan_lock, MA_OWNED);
172
173         KASSERT(prichan->ch_subchan_cnt > 0,
174             ("invalid subchan_cnt %d", prichan->ch_subchan_cnt));
175         prichan->ch_subchan_cnt--;
176
177         if (atomic_testandclear_int(&chan->ch_stflags,
178             VMBUS_CHAN_ST_ONSUBL_SHIFT) == 0)
179                 panic("channel is not on the sublist");
180         TAILQ_REMOVE(&prichan->ch_subchans, chan, ch_sublink);
181 }
182
183 static void
184 vmbus_chan_ins_list(struct vmbus_softc *sc, struct vmbus_channel *chan)
185 {
186
187         mtx_assert(&sc->vmbus_chan_lock, MA_OWNED);
188         if (atomic_testandset_int(&chan->ch_stflags,
189             VMBUS_CHAN_ST_ONLIST_SHIFT))
190                 panic("channel is already on the list");
191         TAILQ_INSERT_TAIL(&sc->vmbus_chans, chan, ch_link);
192 }
193
194 static void
195 vmbus_chan_rem_list(struct vmbus_softc *sc, struct vmbus_channel *chan)
196 {
197
198         mtx_assert(&sc->vmbus_chan_lock, MA_OWNED);
199         if (atomic_testandclear_int(&chan->ch_stflags,
200             VMBUS_CHAN_ST_ONLIST_SHIFT) == 0)
201                 panic("channel is not on the list");
202         TAILQ_REMOVE(&sc->vmbus_chans, chan, ch_link);
203 }
204
205 static int
206 vmbus_chan_sysctl_mnf(SYSCTL_HANDLER_ARGS)
207 {
208         struct vmbus_channel *chan = arg1;
209         int mnf = 0;
210
211         if (chan->ch_txflags & VMBUS_CHAN_TXF_HASMNF)
212                 mnf = 1;
213         return sysctl_handle_int(oidp, &mnf, 0, req);
214 }
215
216 static void
217 vmbus_chan_sysctl_create(struct vmbus_channel *chan)
218 {
219         struct sysctl_oid *ch_tree, *chid_tree, *br_tree;
220         struct sysctl_ctx_list *ctx;
221         uint32_t ch_id;
222         char name[16];
223
224         /*
225          * Add sysctl nodes related to this channel to this
226          * channel's sysctl ctx, so that they can be destroyed
227          * independently upon close of this channel, which can
228          * happen even if the device is not detached.
229          */
230         ctx = &chan->ch_sysctl_ctx;
231         sysctl_ctx_init(ctx);
232
233         /*
234          * Create dev.NAME.UNIT.channel tree.
235          */
236         ch_tree = SYSCTL_ADD_NODE(ctx,
237             SYSCTL_CHILDREN(device_get_sysctl_tree(chan->ch_dev)),
238             OID_AUTO, "channel", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
239         if (ch_tree == NULL)
240                 return;
241
242         /*
243          * Create dev.NAME.UNIT.channel.CHANID tree.
244          */
245         if (VMBUS_CHAN_ISPRIMARY(chan))
246                 ch_id = chan->ch_id;
247         else
248                 ch_id = chan->ch_prichan->ch_id;
249         snprintf(name, sizeof(name), "%d", ch_id);
250         chid_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(ch_tree),
251             OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
252         if (chid_tree == NULL)
253                 return;
254
255         if (!VMBUS_CHAN_ISPRIMARY(chan)) {
256                 /*
257                  * Create dev.NAME.UNIT.channel.CHANID.sub tree.
258                  */
259                 ch_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(chid_tree),
260                     OID_AUTO, "sub", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
261                 if (ch_tree == NULL)
262                         return;
263
264                 /*
265                  * Create dev.NAME.UNIT.channel.CHANID.sub.SUBIDX tree.
266                  *
267                  * NOTE:
268                  * chid_tree is changed to this new sysctl tree.
269                  */
270                 snprintf(name, sizeof(name), "%d", chan->ch_subidx);
271                 chid_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(ch_tree),
272                     OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
273                 if (chid_tree == NULL)
274                         return;
275
276                 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
277                     "chanid", CTLFLAG_RD, &chan->ch_id, 0, "channel id");
278         }
279
280         SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
281             "cpu", CTLFLAG_RD, &chan->ch_cpuid, 0, "owner CPU id");
282         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
283             "mnf", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
284             chan, 0, vmbus_chan_sysctl_mnf, "I",
285             "has monitor notification facilities");
286
287         br_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
288             "br", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
289         if (br_tree != NULL) {
290                 /*
291                  * Create sysctl tree for RX bufring.
292                  */
293                 vmbus_br_sysctl_create(ctx, br_tree, &chan->ch_rxbr.rxbr, "rx");
294                 /*
295                  * Create sysctl tree for TX bufring.
296                  */
297                 vmbus_br_sysctl_create(ctx, br_tree, &chan->ch_txbr.txbr, "tx");
298         }
299 }
300
301 int
302 vmbus_chan_open(struct vmbus_channel *chan, int txbr_size, int rxbr_size,
303     const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg)
304 {
305         struct vmbus_chan_br cbr;
306         int error;
307
308         /*
309          * Allocate the TX+RX bufrings.
310          */
311         KASSERT(chan->ch_bufring == NULL, ("bufrings are allocated"));
312         chan->ch_bufring = hyperv_dmamem_alloc(bus_get_dma_tag(chan->ch_dev),
313             PAGE_SIZE, 0, txbr_size + rxbr_size, &chan->ch_bufring_dma,
314             BUS_DMA_WAITOK);
315         if (chan->ch_bufring == NULL) {
316                 vmbus_chan_printf(chan, "bufring allocation failed\n");
317                 return (ENOMEM);
318         }
319
320         cbr.cbr = chan->ch_bufring;
321         cbr.cbr_paddr = chan->ch_bufring_dma.hv_paddr;
322         cbr.cbr_txsz = txbr_size;
323         cbr.cbr_rxsz = rxbr_size;
324
325         error = vmbus_chan_open_br(chan, &cbr, udata, udlen, cb, cbarg);
326         if (error) {
327                 if (error == EISCONN) {
328                         /*
329                          * XXX
330                          * The bufring GPADL is still connected; abandon
331                          * this bufring, instead of having mysterious
332                          * crash or trashed data later on.
333                          */
334                         vmbus_chan_printf(chan, "chan%u bufring GPADL "
335                             "is still connected upon channel open error; "
336                             "leak %d bytes memory\n", chan->ch_id,
337                             txbr_size + rxbr_size);
338                 } else {
339                         hyperv_dmamem_free(&chan->ch_bufring_dma,
340                             chan->ch_bufring);
341                 }
342                 chan->ch_bufring = NULL;
343         }
344         return (error);
345 }
346
347 int
348 vmbus_chan_open_br(struct vmbus_channel *chan, const struct vmbus_chan_br *cbr,
349     const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg)
350 {
351         struct vmbus_softc *sc = chan->ch_vmbus;
352         const struct vmbus_chanmsg_chopen_resp *resp;
353         const struct vmbus_message *msg;
354         struct vmbus_chanmsg_chopen *req;
355         struct vmbus_msghc *mh;
356         uint32_t status;
357         int error, txbr_size, rxbr_size;
358         task_fn_t *task_fn;
359         uint8_t *br;
360
361         if (udlen > VMBUS_CHANMSG_CHOPEN_UDATA_SIZE) {
362                 vmbus_chan_printf(chan,
363                     "invalid udata len %d for chan%u\n", udlen, chan->ch_id);
364                 return (EINVAL);
365         }
366
367         br = cbr->cbr;
368         txbr_size = cbr->cbr_txsz;
369         rxbr_size = cbr->cbr_rxsz;
370         KASSERT((txbr_size & PAGE_MASK) == 0,
371             ("send bufring size is not multiple page"));
372         KASSERT((rxbr_size & PAGE_MASK) == 0,
373             ("recv bufring size is not multiple page"));
374         KASSERT((cbr->cbr_paddr & PAGE_MASK) == 0,
375             ("bufring is not page aligned"));
376
377         /*
378          * Zero out the TX/RX bufrings, in case that they were used before.
379          */
380         memset(br, 0, txbr_size + rxbr_size);
381
382         if (atomic_testandset_int(&chan->ch_stflags,
383             VMBUS_CHAN_ST_OPENED_SHIFT))
384                 panic("double-open chan%u", chan->ch_id);
385
386         chan->ch_cb = cb;
387         chan->ch_cbarg = cbarg;
388
389         vmbus_chan_update_evtflagcnt(sc, chan);
390
391         chan->ch_tq = VMBUS_PCPU_GET(chan->ch_vmbus, event_tq, chan->ch_cpuid);
392         if (chan->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD)
393                 task_fn = vmbus_chan_task;
394         else
395                 task_fn = vmbus_chan_task_nobatch;
396         TASK_INIT(&chan->ch_task, 0, task_fn, chan);
397
398         /* TX bufring comes first */
399         vmbus_txbr_setup(&chan->ch_txbr, br, txbr_size);
400         /* RX bufring immediately follows TX bufring */
401         vmbus_rxbr_setup(&chan->ch_rxbr, br + txbr_size, rxbr_size);
402
403         /* Create sysctl tree for this channel */
404         vmbus_chan_sysctl_create(chan);
405
406         /*
407          * Connect the bufrings, both RX and TX, to this channel.
408          */
409         KASSERT(chan->ch_bufring_gpadl == 0,
410             ("bufring GPADL is still connected"));
411         error = vmbus_chan_gpadl_connect(chan, cbr->cbr_paddr,
412             txbr_size + rxbr_size, &chan->ch_bufring_gpadl);
413         if (error) {
414                 vmbus_chan_printf(chan,
415                     "failed to connect bufring GPADL to chan%u\n", chan->ch_id);
416                 goto failed;
417         }
418
419         /*
420          * Install this channel, before it is opened, but after everything
421          * else has been setup.
422          */
423         vmbus_chan_set_chmap(chan);
424
425         /*
426          * Open channel w/ the bufring GPADL on the target CPU.
427          */
428         mh = vmbus_msghc_get(sc, sizeof(*req));
429         if (mh == NULL) {
430                 vmbus_chan_printf(chan,
431                     "can not get msg hypercall for chopen(chan%u)\n",
432                     chan->ch_id);
433                 error = ENXIO;
434                 goto failed;
435         }
436
437         req = vmbus_msghc_dataptr(mh);
438         req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHOPEN;
439         req->chm_chanid = chan->ch_id;
440         req->chm_openid = chan->ch_id;
441         req->chm_gpadl = chan->ch_bufring_gpadl;
442         req->chm_vcpuid = chan->ch_vcpuid;
443         req->chm_txbr_pgcnt = txbr_size >> PAGE_SHIFT;
444         if (udlen > 0)
445                 memcpy(req->chm_udata, udata, udlen);
446
447         error = vmbus_msghc_exec(sc, mh);
448         if (error) {
449                 vmbus_chan_printf(chan,
450                     "chopen(chan%u) msg hypercall exec failed: %d\n",
451                     chan->ch_id, error);
452                 vmbus_msghc_put(sc, mh);
453                 goto failed;
454         }
455
456         msg = vmbus_msghc_wait_result(sc, mh);
457         resp = (const struct vmbus_chanmsg_chopen_resp *)msg->msg_data;
458         status = resp->chm_status;
459
460         vmbus_msghc_put(sc, mh);
461
462         if (status == 0) {
463                 if (bootverbose)
464                         vmbus_chan_printf(chan, "chan%u opened\n", chan->ch_id);
465                 return (0);
466         }
467
468         vmbus_chan_printf(chan, "failed to open chan%u\n", chan->ch_id);
469         error = ENXIO;
470
471 failed:
472         sysctl_ctx_free(&chan->ch_sysctl_ctx);
473         vmbus_chan_clear_chmap(chan);
474         if (chan->ch_bufring_gpadl != 0) {
475                 int error1;
476
477                 error1 = vmbus_chan_gpadl_disconnect(chan,
478                     chan->ch_bufring_gpadl);
479                 if (error1) {
480                         /*
481                          * Give caller a hint that the bufring GPADL is still
482                          * connected.
483                          */
484                         error = EISCONN;
485                 }
486                 chan->ch_bufring_gpadl = 0;
487         }
488         atomic_clear_int(&chan->ch_stflags, VMBUS_CHAN_ST_OPENED);
489         return (error);
490 }
491
492 int
493 vmbus_chan_gpadl_connect(struct vmbus_channel *chan, bus_addr_t paddr,
494     int size, uint32_t *gpadl0)
495 {
496         struct vmbus_softc *sc = chan->ch_vmbus;
497         struct vmbus_msghc *mh;
498         struct vmbus_chanmsg_gpadl_conn *req;
499         const struct vmbus_message *msg;
500         size_t reqsz;
501         uint32_t gpadl, status;
502         int page_count, range_len, i, cnt, error;
503         uint64_t page_id;
504
505         KASSERT(*gpadl0 == 0, ("GPADL is not zero"));
506
507         /*
508          * Preliminary checks.
509          */
510
511         KASSERT((size & PAGE_MASK) == 0,
512             ("invalid GPA size %d, not multiple page size", size));
513         page_count = size >> PAGE_SHIFT;
514
515         KASSERT((paddr & PAGE_MASK) == 0,
516             ("GPA is not page aligned %jx", (uintmax_t)paddr));
517         page_id = paddr >> PAGE_SHIFT;
518
519         range_len = __offsetof(struct vmbus_gpa_range, gpa_page[page_count]);
520         /*
521          * We don't support multiple GPA ranges.
522          */
523         if (range_len > UINT16_MAX) {
524                 vmbus_chan_printf(chan, "GPA too large, %d pages\n",
525                     page_count);
526                 return EOPNOTSUPP;
527         }
528
529         /*
530          * Allocate GPADL id.
531          */
532         gpadl = vmbus_gpadl_alloc(sc);
533
534         /*
535          * Connect this GPADL to the target channel.
536          *
537          * NOTE:
538          * Since each message can only hold small set of page
539          * addresses, several messages may be required to
540          * complete the connection.
541          */
542         if (page_count > VMBUS_CHANMSG_GPADL_CONN_PGMAX)
543                 cnt = VMBUS_CHANMSG_GPADL_CONN_PGMAX;
544         else
545                 cnt = page_count;
546         page_count -= cnt;
547
548         reqsz = __offsetof(struct vmbus_chanmsg_gpadl_conn,
549             chm_range.gpa_page[cnt]);
550         mh = vmbus_msghc_get(sc, reqsz);
551         if (mh == NULL) {
552                 vmbus_chan_printf(chan,
553                     "can not get msg hypercall for gpadl_conn(chan%u)\n",
554                     chan->ch_id);
555                 return EIO;
556         }
557
558         req = vmbus_msghc_dataptr(mh);
559         req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_CONN;
560         req->chm_chanid = chan->ch_id;
561         req->chm_gpadl = gpadl;
562         req->chm_range_len = range_len;
563         req->chm_range_cnt = 1;
564         req->chm_range.gpa_len = size;
565         req->chm_range.gpa_ofs = 0;
566         for (i = 0; i < cnt; ++i)
567                 req->chm_range.gpa_page[i] = page_id++;
568
569         error = vmbus_msghc_exec(sc, mh);
570         if (error) {
571                 vmbus_chan_printf(chan,
572                     "gpadl_conn(chan%u) msg hypercall exec failed: %d\n",
573                     chan->ch_id, error);
574                 vmbus_msghc_put(sc, mh);
575                 return error;
576         }
577
578         while (page_count > 0) {
579                 struct vmbus_chanmsg_gpadl_subconn *subreq;
580
581                 if (page_count > VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX)
582                         cnt = VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX;
583                 else
584                         cnt = page_count;
585                 page_count -= cnt;
586
587                 reqsz = __offsetof(struct vmbus_chanmsg_gpadl_subconn,
588                     chm_gpa_page[cnt]);
589                 vmbus_msghc_reset(mh, reqsz);
590
591                 subreq = vmbus_msghc_dataptr(mh);
592                 subreq->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_SUBCONN;
593                 subreq->chm_gpadl = gpadl;
594                 for (i = 0; i < cnt; ++i)
595                         subreq->chm_gpa_page[i] = page_id++;
596
597                 vmbus_msghc_exec_noresult(mh);
598         }
599         KASSERT(page_count == 0, ("invalid page count %d", page_count));
600
601         msg = vmbus_msghc_wait_result(sc, mh);
602         status = ((const struct vmbus_chanmsg_gpadl_connresp *)
603             msg->msg_data)->chm_status;
604
605         vmbus_msghc_put(sc, mh);
606
607         if (status != 0) {
608                 vmbus_chan_printf(chan, "gpadl_conn(chan%u) failed: %u\n",
609                     chan->ch_id, status);
610                 return EIO;
611         }
612
613         /* Done; commit the GPADL id. */
614         *gpadl0 = gpadl;
615         if (bootverbose) {
616                 vmbus_chan_printf(chan, "gpadl_conn(chan%u) succeeded\n",
617                     chan->ch_id);
618         }
619         return 0;
620 }
621
622 static bool
623 vmbus_chan_wait_revoke(const struct vmbus_channel *chan)
624 {
625 #define WAIT_COUNT      200     /* 200ms */
626
627         int i;
628
629         for (i = 0; i < WAIT_COUNT; ++i) {
630                 if (vmbus_chan_is_revoked(chan))
631                         return (true);
632                 /* Not sure about the context; use busy-wait. */
633                 DELAY(1000);
634         }
635         return (false);
636
637 #undef WAIT_COUNT
638 }
639
640 /*
641  * Disconnect the GPA from the target channel
642  */
643 int
644 vmbus_chan_gpadl_disconnect(struct vmbus_channel *chan, uint32_t gpadl)
645 {
646         struct vmbus_softc *sc = chan->ch_vmbus;
647         struct vmbus_msghc *mh;
648         struct vmbus_chanmsg_gpadl_disconn *req;
649         int error;
650
651         KASSERT(gpadl != 0, ("GPADL is zero"));
652
653         mh = vmbus_msghc_get(sc, sizeof(*req));
654         if (mh == NULL) {
655                 vmbus_chan_printf(chan,
656                     "can not get msg hypercall for gpadl_disconn(chan%u)\n",
657                     chan->ch_id);
658                 return (EBUSY);
659         }
660
661         req = vmbus_msghc_dataptr(mh);
662         req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_DISCONN;
663         req->chm_chanid = chan->ch_id;
664         req->chm_gpadl = gpadl;
665
666         error = vmbus_msghc_exec(sc, mh);
667         if (error) {
668                 vmbus_msghc_put(sc, mh);
669
670                 if (vmbus_chan_wait_revoke(chan)) {
671                         /*
672                          * Error is benign; this channel is revoked,
673                          * so this GPADL will not be touched anymore.
674                          */
675                         vmbus_chan_printf(chan,
676                             "gpadl_disconn(revoked chan%u) msg hypercall "
677                             "exec failed: %d\n", chan->ch_id, error);
678                         return (0);
679                 }
680                 vmbus_chan_printf(chan,
681                     "gpadl_disconn(chan%u) msg hypercall exec failed: %d\n",
682                     chan->ch_id, error);
683                 return (error);
684         }
685
686         vmbus_msghc_wait_result(sc, mh);
687         /* Discard result; no useful information */
688         vmbus_msghc_put(sc, mh);
689
690         return (0);
691 }
692
693 static void
694 vmbus_chan_detach(struct vmbus_channel *chan)
695 {
696         int refs;
697
698         KASSERT(chan->ch_refs > 0, ("chan%u: invalid refcnt %d",
699             chan->ch_id, chan->ch_refs));
700         refs = atomic_fetchadd_int(&chan->ch_refs, -1);
701 #ifdef INVARIANTS
702         if (VMBUS_CHAN_ISPRIMARY(chan)) {
703                 KASSERT(refs == 1, ("chan%u: invalid refcnt %d for prichan",
704                     chan->ch_id, refs + 1));
705         }
706 #endif
707         if (refs == 1) {
708                 /*
709                  * Detach the target channel.
710                  */
711                 if (bootverbose) {
712                         vmbus_chan_printf(chan, "chan%u detached\n",
713                             chan->ch_id);
714                 }
715                 taskqueue_enqueue(chan->ch_mgmt_tq, &chan->ch_detach_task);
716         }
717 }
718
719 static void
720 vmbus_chan_clrchmap_task(void *xchan, int pending __unused)
721 {
722         struct vmbus_channel *chan = xchan;
723
724         critical_enter();
725         chan->ch_vmbus->vmbus_chmap[chan->ch_id] = NULL;
726         critical_exit();
727 }
728
729 static void
730 vmbus_chan_clear_chmap(struct vmbus_channel *chan)
731 {
732         struct task chmap_task;
733
734         TASK_INIT(&chmap_task, 0, vmbus_chan_clrchmap_task, chan);
735         taskqueue_enqueue(chan->ch_tq, &chmap_task);
736         taskqueue_drain(chan->ch_tq, &chmap_task);
737 }
738
739 static void
740 vmbus_chan_set_chmap(struct vmbus_channel *chan)
741 {
742         __compiler_membar();
743         chan->ch_vmbus->vmbus_chmap[chan->ch_id] = chan;
744 }
745
746 static int
747 vmbus_chan_close_internal(struct vmbus_channel *chan)
748 {
749         struct vmbus_softc *sc = chan->ch_vmbus;
750         struct vmbus_msghc *mh;
751         struct vmbus_chanmsg_chclose *req;
752         uint32_t old_stflags;
753         int error;
754
755         /*
756          * NOTE:
757          * Sub-channels are closed upon their primary channel closing,
758          * so they can be closed even before they are opened.
759          */
760         for (;;) {
761                 old_stflags = chan->ch_stflags;
762                 if (atomic_cmpset_int(&chan->ch_stflags, old_stflags,
763                     old_stflags & ~VMBUS_CHAN_ST_OPENED))
764                         break;
765         }
766         if ((old_stflags & VMBUS_CHAN_ST_OPENED) == 0) {
767                 /* Not opened yet; done */
768                 if (bootverbose) {
769                         vmbus_chan_printf(chan, "chan%u not opened\n",
770                             chan->ch_id);
771                 }
772                 return (0);
773         }
774
775         /*
776          * Free this channel's sysctl tree attached to its device's
777          * sysctl tree.
778          */
779         sysctl_ctx_free(&chan->ch_sysctl_ctx);
780
781         /*
782          * NOTE:
783          * Order is critical.  This channel _must_ be uninstalled first,
784          * else the channel task may be enqueued by the IDT after it has
785          * been drained.
786          */
787         vmbus_chan_clear_chmap(chan);
788         taskqueue_drain(chan->ch_tq, &chan->ch_task);
789         chan->ch_tq = NULL;
790
791         /*
792          * Close this channel.
793          */
794         mh = vmbus_msghc_get(sc, sizeof(*req));
795         if (mh == NULL) {
796                 vmbus_chan_printf(chan,
797                     "can not get msg hypercall for chclose(chan%u)\n",
798                     chan->ch_id);
799                 error = ENXIO;
800                 goto disconnect;
801         }
802
803         req = vmbus_msghc_dataptr(mh);
804         req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHCLOSE;
805         req->chm_chanid = chan->ch_id;
806
807         error = vmbus_msghc_exec_noresult(mh);
808         vmbus_msghc_put(sc, mh);
809
810         if (error) {
811                 vmbus_chan_printf(chan,
812                     "chclose(chan%u) msg hypercall exec failed: %d\n",
813                     chan->ch_id, error);
814                 goto disconnect;
815         }
816
817         if (bootverbose)
818                 vmbus_chan_printf(chan, "chan%u closed\n", chan->ch_id);
819
820 disconnect:
821         /*
822          * Disconnect the TX+RX bufrings from this channel.
823          */
824         if (chan->ch_bufring_gpadl != 0) {
825                 int error1;
826
827                 error1 = vmbus_chan_gpadl_disconnect(chan,
828                     chan->ch_bufring_gpadl);
829                 if (error1) {
830                         /*
831                          * XXX
832                          * The bufring GPADL is still connected; abandon
833                          * this bufring, instead of having mysterious
834                          * crash or trashed data later on.
835                          */
836                         vmbus_chan_printf(chan, "chan%u bufring GPADL "
837                             "is still connected after close\n", chan->ch_id);
838                         chan->ch_bufring = NULL;
839                         /*
840                          * Give caller a hint that the bufring GPADL is
841                          * still connected.
842                          */
843                         error = EISCONN;
844                 }
845                 chan->ch_bufring_gpadl = 0;
846         }
847
848         /*
849          * Destroy the TX+RX bufrings.
850          */
851         if (chan->ch_bufring != NULL) {
852                 hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring);
853                 chan->ch_bufring = NULL;
854         }
855         return (error);
856 }
857
858 int
859 vmbus_chan_close_direct(struct vmbus_channel *chan)
860 {
861         int error;
862
863 #ifdef INVARIANTS
864         if (VMBUS_CHAN_ISPRIMARY(chan)) {
865                 struct vmbus_channel *subchan;
866
867                 /*
868                  * All sub-channels _must_ have been closed, or are _not_
869                  * opened at all.
870                  */
871                 mtx_lock(&chan->ch_subchan_lock);
872                 TAILQ_FOREACH(subchan, &chan->ch_subchans, ch_sublink) {
873                         KASSERT(
874                            (subchan->ch_stflags & VMBUS_CHAN_ST_OPENED) == 0,
875                            ("chan%u: subchan%u is still opened",
876                             chan->ch_id, subchan->ch_subidx));
877                 }
878                 mtx_unlock(&chan->ch_subchan_lock);
879         }
880 #endif
881
882         error = vmbus_chan_close_internal(chan);
883         if (!VMBUS_CHAN_ISPRIMARY(chan)) {
884                 /*
885                  * This sub-channel is referenced, when it is linked to
886                  * the primary channel; drop that reference now.
887                  */
888                 vmbus_chan_detach(chan);
889         }
890         return (error);
891 }
892
893 /*
894  * Caller should make sure that all sub-channels have
895  * been added to 'chan' and all to-be-closed channels
896  * are not being opened.
897  */
898 void
899 vmbus_chan_close(struct vmbus_channel *chan)
900 {
901         int subchan_cnt;
902
903         if (!VMBUS_CHAN_ISPRIMARY(chan)) {
904                 /*
905                  * Sub-channel is closed when its primary channel
906                  * is closed; done.
907                  */
908                 return;
909         }
910
911         /*
912          * Close all sub-channels, if any.
913          */
914         subchan_cnt = chan->ch_subchan_cnt;
915         if (subchan_cnt > 0) {
916                 struct vmbus_channel **subchan;
917                 int i;
918
919                 subchan = vmbus_subchan_get(chan, subchan_cnt);
920                 for (i = 0; i < subchan_cnt; ++i) {
921                         vmbus_chan_close_internal(subchan[i]);
922                         /*
923                          * This sub-channel is referenced, when it is
924                          * linked to the primary channel; drop that
925                          * reference now.
926                          */
927                         vmbus_chan_detach(subchan[i]);
928                 }
929                 vmbus_subchan_rel(subchan, subchan_cnt);
930         }
931
932         /* Then close the primary channel. */
933         vmbus_chan_close_internal(chan);
934 }
935
936 void
937 vmbus_chan_intr_drain(struct vmbus_channel *chan)
938 {
939
940         taskqueue_drain(chan->ch_tq, &chan->ch_task);
941 }
942
943 int
944 vmbus_chan_send(struct vmbus_channel *chan, uint16_t type, uint16_t flags,
945     void *data, int dlen, uint64_t xactid)
946 {
947         struct vmbus_chanpkt pkt;
948         int pktlen, pad_pktlen, hlen, error;
949         uint64_t pad = 0;
950         struct iovec iov[3];
951         boolean_t send_evt;
952
953         hlen = sizeof(pkt);
954         pktlen = hlen + dlen;
955         pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen);
956         KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr),
957             ("invalid packet size %d", pad_pktlen));
958
959         pkt.cp_hdr.cph_type = type;
960         pkt.cp_hdr.cph_flags = flags;
961         VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_hlen, hlen);
962         VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_tlen, pad_pktlen);
963         pkt.cp_hdr.cph_xactid = xactid;
964
965         iov[0].iov_base = &pkt;
966         iov[0].iov_len = hlen;
967         iov[1].iov_base = data;
968         iov[1].iov_len = dlen;
969         iov[2].iov_base = &pad;
970         iov[2].iov_len = pad_pktlen - pktlen;
971
972         error = vmbus_txbr_write(&chan->ch_txbr, iov, 3, &send_evt);
973         if (!error && send_evt)
974                 vmbus_chan_signal_tx(chan);
975         return error;
976 }
977
978 int
979 vmbus_chan_send_sglist(struct vmbus_channel *chan,
980     struct vmbus_gpa sg[], int sglen, void *data, int dlen, uint64_t xactid)
981 {
982         struct vmbus_chanpkt_sglist pkt;
983         int pktlen, pad_pktlen, hlen, error;
984         struct iovec iov[4];
985         boolean_t send_evt;
986         uint64_t pad = 0;
987
988         hlen = __offsetof(struct vmbus_chanpkt_sglist, cp_gpa[sglen]);
989         pktlen = hlen + dlen;
990         pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen);
991         KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr),
992             ("invalid packet size %d", pad_pktlen));
993
994         pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA;
995         pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC;
996         VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_hlen, hlen);
997         VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_tlen, pad_pktlen);
998         pkt.cp_hdr.cph_xactid = xactid;
999         pkt.cp_rsvd = 0;
1000         pkt.cp_gpa_cnt = sglen;
1001
1002         iov[0].iov_base = &pkt;
1003         iov[0].iov_len = sizeof(pkt);
1004         iov[1].iov_base = sg;
1005         iov[1].iov_len = sizeof(struct vmbus_gpa) * sglen;
1006         iov[2].iov_base = data;
1007         iov[2].iov_len = dlen;
1008         iov[3].iov_base = &pad;
1009         iov[3].iov_len = pad_pktlen - pktlen;
1010
1011         error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt);
1012         if (!error && send_evt)
1013                 vmbus_chan_signal_tx(chan);
1014         return error;
1015 }
1016
1017 int
1018 vmbus_chan_send_prplist(struct vmbus_channel *chan,
1019     struct vmbus_gpa_range *prp, int prp_cnt, void *data, int dlen,
1020     uint64_t xactid)
1021 {
1022         struct vmbus_chanpkt_prplist pkt;
1023         int pktlen, pad_pktlen, hlen, error;
1024         struct iovec iov[4];
1025         boolean_t send_evt;
1026         uint64_t pad = 0;
1027
1028         hlen = __offsetof(struct vmbus_chanpkt_prplist,
1029             cp_range[0].gpa_page[prp_cnt]);
1030         pktlen = hlen + dlen;
1031         pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen);
1032         KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr),
1033             ("invalid packet size %d", pad_pktlen));
1034
1035         pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA;
1036         pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC;
1037         VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_hlen, hlen);
1038         VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_tlen, pad_pktlen);
1039         pkt.cp_hdr.cph_xactid = xactid;
1040         pkt.cp_rsvd = 0;
1041         pkt.cp_range_cnt = 1;
1042
1043         iov[0].iov_base = &pkt;
1044         iov[0].iov_len = sizeof(pkt);
1045         iov[1].iov_base = prp;
1046         iov[1].iov_len = __offsetof(struct vmbus_gpa_range, gpa_page[prp_cnt]);
1047         iov[2].iov_base = data;
1048         iov[2].iov_len = dlen;
1049         iov[3].iov_base = &pad;
1050         iov[3].iov_len = pad_pktlen - pktlen;
1051
1052         error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt);
1053         if (!error && send_evt)
1054                 vmbus_chan_signal_tx(chan);
1055         return error;
1056 }
1057
1058 int
1059 vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0,
1060     uint64_t *xactid)
1061 {
1062         struct vmbus_chanpkt_hdr pkt;
1063         int error, dlen, hlen;
1064
1065         error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt));
1066         if (error)
1067                 return (error);
1068
1069         if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) {
1070                 vmbus_chan_printf(chan, "invalid hlen %u\n", pkt.cph_hlen);
1071                 /* XXX this channel is dead actually. */
1072                 return (EIO);
1073         }
1074         if (__predict_false(pkt.cph_hlen > pkt.cph_tlen)) {
1075                 vmbus_chan_printf(chan, "invalid hlen %u and tlen %u\n",
1076                     pkt.cph_hlen, pkt.cph_tlen);
1077                 /* XXX this channel is dead actually. */
1078                 return (EIO);
1079         }
1080
1081         hlen = VMBUS_CHANPKT_GETLEN(pkt.cph_hlen);
1082         dlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen) - hlen;
1083
1084         if (*dlen0 < dlen) {
1085                 /* Return the size of this packet's data. */
1086                 *dlen0 = dlen;
1087                 return (ENOBUFS);
1088         }
1089
1090         *xactid = pkt.cph_xactid;
1091         *dlen0 = dlen;
1092
1093         /* Skip packet header */
1094         error = vmbus_rxbr_read(&chan->ch_rxbr, data, dlen, hlen);
1095         KASSERT(!error, ("vmbus_rxbr_read failed"));
1096
1097         return (0);
1098 }
1099
1100 int
1101 vmbus_chan_recv_pkt(struct vmbus_channel *chan,
1102     struct vmbus_chanpkt_hdr *pkt, int *pktlen0)
1103 {
1104         int error, pktlen, pkt_hlen;
1105
1106         pkt_hlen = sizeof(*pkt);
1107         error = vmbus_rxbr_peek(&chan->ch_rxbr, pkt, pkt_hlen);
1108         if (error)
1109                 return (error);
1110
1111         if (__predict_false(pkt->cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) {
1112                 vmbus_chan_printf(chan, "invalid hlen %u\n", pkt->cph_hlen);
1113                 /* XXX this channel is dead actually. */
1114                 return (EIO);
1115         }
1116         if (__predict_false(pkt->cph_hlen > pkt->cph_tlen)) {
1117                 vmbus_chan_printf(chan, "invalid hlen %u and tlen %u\n",
1118                     pkt->cph_hlen, pkt->cph_tlen);
1119                 /* XXX this channel is dead actually. */
1120                 return (EIO);
1121         }
1122
1123         pktlen = VMBUS_CHANPKT_GETLEN(pkt->cph_tlen);
1124         if (*pktlen0 < pktlen) {
1125                 /* Return the size of this packet. */
1126                 *pktlen0 = pktlen;
1127                 return (ENOBUFS);
1128         }
1129         *pktlen0 = pktlen;
1130
1131         /*
1132          * Skip the fixed-size packet header, which has been filled
1133          * by the above vmbus_rxbr_peek().
1134          */
1135         error = vmbus_rxbr_read(&chan->ch_rxbr, pkt + 1,
1136             pktlen - pkt_hlen, pkt_hlen);
1137         KASSERT(!error, ("vmbus_rxbr_read failed"));
1138
1139         return (0);
1140 }
1141
1142 static void
1143 vmbus_chan_task(void *xchan, int pending __unused)
1144 {
1145         struct vmbus_channel *chan = xchan;
1146         vmbus_chan_callback_t cb = chan->ch_cb;
1147         void *cbarg = chan->ch_cbarg;
1148
1149         /*
1150          * Optimize host to guest signaling by ensuring:
1151          * 1. While reading the channel, we disable interrupts from
1152          *    host.
1153          * 2. Ensure that we process all posted messages from the host
1154          *    before returning from this callback.
1155          * 3. Once we return, enable signaling from the host. Once this
1156          *    state is set we check to see if additional packets are
1157          *    available to read. In this case we repeat the process.
1158          *
1159          * NOTE: Interrupt has been disabled in the ISR.
1160          */
1161         for (;;) {
1162                 uint32_t left;
1163
1164                 cb(chan, cbarg);
1165
1166                 left = vmbus_rxbr_intr_unmask(&chan->ch_rxbr);
1167                 if (left == 0) {
1168                         /* No more data in RX bufring; done */
1169                         break;
1170                 }
1171                 vmbus_rxbr_intr_mask(&chan->ch_rxbr);
1172         }
1173 }
1174
1175 static void
1176 vmbus_chan_task_nobatch(void *xchan, int pending __unused)
1177 {
1178         struct vmbus_channel *chan = xchan;
1179
1180         chan->ch_cb(chan, chan->ch_cbarg);
1181 }
1182
1183 static __inline void
1184 vmbus_event_flags_proc(struct vmbus_softc *sc, volatile u_long *event_flags,
1185     int flag_cnt)
1186 {
1187         int f;
1188
1189         for (f = 0; f < flag_cnt; ++f) {
1190                 uint32_t chid_base;
1191                 u_long flags;
1192                 int chid_ofs;
1193
1194                 if (event_flags[f] == 0)
1195                         continue;
1196
1197                 flags = atomic_swap_long(&event_flags[f], 0);
1198                 chid_base = f << VMBUS_EVTFLAG_SHIFT;
1199
1200                 while ((chid_ofs = ffsl(flags)) != 0) {
1201                         struct vmbus_channel *chan;
1202
1203                         --chid_ofs; /* NOTE: ffsl is 1-based */
1204                         flags &= ~(1UL << chid_ofs);
1205
1206                         chan = sc->vmbus_chmap[chid_base + chid_ofs];
1207                         if (__predict_false(chan == NULL)) {
1208                                 /* Channel is closed. */
1209                                 continue;
1210                         }
1211                         __compiler_membar();
1212
1213                         if (chan->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD)
1214                                 vmbus_rxbr_intr_mask(&chan->ch_rxbr);
1215                         taskqueue_enqueue(chan->ch_tq, &chan->ch_task);
1216                 }
1217         }
1218 }
1219
1220 void
1221 vmbus_event_proc(struct vmbus_softc *sc, int cpu)
1222 {
1223         struct vmbus_evtflags *eventf;
1224
1225         /*
1226          * On Host with Win8 or above, the event page can be checked directly
1227          * to get the id of the channel that has the pending interrupt.
1228          */
1229         eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE;
1230         vmbus_event_flags_proc(sc, eventf->evt_flags,
1231             VMBUS_PCPU_GET(sc, event_flags_cnt, cpu));
1232 }
1233
1234 void
1235 vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu)
1236 {
1237         struct vmbus_evtflags *eventf;
1238
1239         eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE;
1240         if (atomic_testandclear_long(&eventf->evt_flags[0], 0)) {
1241                 vmbus_event_flags_proc(sc, sc->vmbus_rx_evtflags,
1242                     VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT);
1243         }
1244 }
1245
1246 static void
1247 vmbus_chan_update_evtflagcnt(struct vmbus_softc *sc,
1248     const struct vmbus_channel *chan)
1249 {
1250         volatile int *flag_cnt_ptr;
1251         int flag_cnt;
1252
1253         flag_cnt = (chan->ch_id / VMBUS_EVTFLAG_LEN) + 1;
1254         flag_cnt_ptr = VMBUS_PCPU_PTR(sc, event_flags_cnt, chan->ch_cpuid);
1255
1256         for (;;) {
1257                 int old_flag_cnt;
1258
1259                 old_flag_cnt = *flag_cnt_ptr;
1260                 if (old_flag_cnt >= flag_cnt)
1261                         break;
1262                 if (atomic_cmpset_int(flag_cnt_ptr, old_flag_cnt, flag_cnt)) {
1263                         if (bootverbose) {
1264                                 vmbus_chan_printf(chan,
1265                                     "chan%u update cpu%d flag_cnt to %d\n",
1266                                     chan->ch_id, chan->ch_cpuid, flag_cnt);
1267                         }
1268                         break;
1269                 }
1270         }
1271 }
1272
1273 static struct vmbus_channel *
1274 vmbus_chan_alloc(struct vmbus_softc *sc)
1275 {
1276         struct vmbus_channel *chan;
1277
1278         chan = malloc(sizeof(*chan), M_DEVBUF, M_WAITOK | M_ZERO);
1279
1280         chan->ch_monprm = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
1281             HYPERCALL_PARAM_ALIGN, 0, sizeof(struct hyperv_mon_param),
1282             &chan->ch_monprm_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
1283         if (chan->ch_monprm == NULL) {
1284                 device_printf(sc->vmbus_dev, "monprm alloc failed\n");
1285                 free(chan, M_DEVBUF);
1286                 return NULL;
1287         }
1288
1289         chan->ch_refs = 1;
1290         chan->ch_vmbus = sc;
1291         mtx_init(&chan->ch_subchan_lock, "vmbus subchan", NULL, MTX_DEF);
1292         sx_init(&chan->ch_orphan_lock, "vmbus chorphan");
1293         TAILQ_INIT(&chan->ch_subchans);
1294         vmbus_rxbr_init(&chan->ch_rxbr);
1295         vmbus_txbr_init(&chan->ch_txbr);
1296
1297         return chan;
1298 }
1299
1300 static void
1301 vmbus_chan_free(struct vmbus_channel *chan)
1302 {
1303
1304         KASSERT(TAILQ_EMPTY(&chan->ch_subchans) && chan->ch_subchan_cnt == 0,
1305             ("still owns sub-channels"));
1306         KASSERT((chan->ch_stflags &
1307             (VMBUS_CHAN_ST_OPENED |
1308              VMBUS_CHAN_ST_ONPRIL |
1309              VMBUS_CHAN_ST_ONSUBL |
1310              VMBUS_CHAN_ST_ONLIST)) == 0, ("free busy channel"));
1311         KASSERT(chan->ch_orphan_xact == NULL,
1312             ("still has orphan xact installed"));
1313         KASSERT(chan->ch_refs == 0, ("chan%u: invalid refcnt %d",
1314             chan->ch_id, chan->ch_refs));
1315
1316         hyperv_dmamem_free(&chan->ch_monprm_dma, chan->ch_monprm);
1317         mtx_destroy(&chan->ch_subchan_lock);
1318         sx_destroy(&chan->ch_orphan_lock);
1319         vmbus_rxbr_deinit(&chan->ch_rxbr);
1320         vmbus_txbr_deinit(&chan->ch_txbr);
1321         free(chan, M_DEVBUF);
1322 }
1323
1324 static int
1325 vmbus_chan_add(struct vmbus_channel *newchan)
1326 {
1327         struct vmbus_softc *sc = newchan->ch_vmbus;
1328         struct vmbus_channel *prichan;
1329
1330         if (newchan->ch_id == 0) {
1331                 /*
1332                  * XXX
1333                  * Chan0 will neither be processed nor should be offered;
1334                  * skip it.
1335                  */
1336                 device_printf(sc->vmbus_dev, "got chan0 offer, discard\n");
1337                 return EINVAL;
1338         } else if (newchan->ch_id >= VMBUS_CHAN_MAX) {
1339                 device_printf(sc->vmbus_dev, "invalid chan%u offer\n",
1340                     newchan->ch_id);
1341                 return EINVAL;
1342         }
1343
1344         mtx_lock(&sc->vmbus_prichan_lock);
1345         TAILQ_FOREACH(prichan, &sc->vmbus_prichans, ch_prilink) {
1346                 /*
1347                  * Sub-channel will have the same type GUID and instance
1348                  * GUID as its primary channel.
1349                  */
1350                 if (memcmp(&prichan->ch_guid_type, &newchan->ch_guid_type,
1351                     sizeof(struct hyperv_guid)) == 0 &&
1352                     memcmp(&prichan->ch_guid_inst, &newchan->ch_guid_inst,
1353                     sizeof(struct hyperv_guid)) == 0)
1354                         break;
1355         }
1356         if (VMBUS_CHAN_ISPRIMARY(newchan)) {
1357                 if (prichan == NULL) {
1358                         /* Install the new primary channel */
1359                         vmbus_chan_ins_prilist(sc, newchan);
1360                         mtx_unlock(&sc->vmbus_prichan_lock);
1361                         goto done;
1362                 } else {
1363                         mtx_unlock(&sc->vmbus_prichan_lock);
1364                         device_printf(sc->vmbus_dev,
1365                             "duplicated primary chan%u\n", newchan->ch_id);
1366                         return EINVAL;
1367                 }
1368         } else { /* Sub-channel */
1369                 if (prichan == NULL) {
1370                         mtx_unlock(&sc->vmbus_prichan_lock);
1371                         device_printf(sc->vmbus_dev,
1372                             "no primary chan for chan%u\n", newchan->ch_id);
1373                         return EINVAL;
1374                 }
1375                 /*
1376                  * Found the primary channel for this sub-channel and
1377                  * move on.
1378                  *
1379                  * XXX refcnt prichan
1380                  */
1381         }
1382         mtx_unlock(&sc->vmbus_prichan_lock);
1383
1384         /*
1385          * This is a sub-channel; link it with the primary channel.
1386          */
1387         KASSERT(!VMBUS_CHAN_ISPRIMARY(newchan),
1388             ("new channel is not sub-channel"));
1389         KASSERT(prichan != NULL, ("no primary channel"));
1390
1391         /*
1392          * Reference count this sub-channel; it will be dereferenced
1393          * when this sub-channel is closed.
1394          */
1395         KASSERT(newchan->ch_refs == 1, ("chan%u: invalid refcnt %d",
1396             newchan->ch_id, newchan->ch_refs));
1397         atomic_add_int(&newchan->ch_refs, 1);
1398
1399         newchan->ch_prichan = prichan;
1400         newchan->ch_dev = prichan->ch_dev;
1401
1402         mtx_lock(&prichan->ch_subchan_lock);
1403         vmbus_chan_ins_sublist(prichan, newchan);
1404         mtx_unlock(&prichan->ch_subchan_lock);
1405         /*
1406          * Notify anyone that is interested in this sub-channel,
1407          * after this sub-channel is setup.
1408          */
1409         wakeup(prichan);
1410 done:
1411         /*
1412          * Hook this channel up for later revocation.
1413          */
1414         mtx_lock(&sc->vmbus_chan_lock);
1415         vmbus_chan_ins_list(sc, newchan);
1416         mtx_unlock(&sc->vmbus_chan_lock);
1417
1418         if (bootverbose) {
1419                 vmbus_chan_printf(newchan, "chan%u subidx%u offer\n",
1420                     newchan->ch_id, newchan->ch_subidx);
1421         }
1422
1423         /* Select default cpu for this channel. */
1424         vmbus_chan_cpu_default(newchan);
1425
1426         return 0;
1427 }
1428
1429 void
1430 vmbus_chan_cpu_set(struct vmbus_channel *chan, int cpu)
1431 {
1432         KASSERT(cpu >= 0 && cpu < mp_ncpus, ("invalid cpu %d", cpu));
1433
1434         if (chan->ch_vmbus->vmbus_version == VMBUS_VERSION_WS2008 ||
1435             chan->ch_vmbus->vmbus_version == VMBUS_VERSION_WIN7) {
1436                 /* Only cpu0 is supported */
1437                 cpu = 0;
1438         }
1439
1440         chan->ch_cpuid = cpu;
1441         chan->ch_vcpuid = VMBUS_PCPU_GET(chan->ch_vmbus, vcpuid, cpu);
1442
1443         if (bootverbose) {
1444                 vmbus_chan_printf(chan,
1445                     "chan%u assigned to cpu%u [vcpu%u]\n",
1446                     chan->ch_id, chan->ch_cpuid, chan->ch_vcpuid);
1447         }
1448 }
1449
1450 void
1451 vmbus_chan_cpu_rr(struct vmbus_channel *chan)
1452 {
1453         static uint32_t vmbus_chan_nextcpu;
1454         int cpu;
1455
1456         cpu = atomic_fetchadd_int(&vmbus_chan_nextcpu, 1) % mp_ncpus;
1457         vmbus_chan_cpu_set(chan, cpu);
1458 }
1459
1460 static void
1461 vmbus_chan_cpu_default(struct vmbus_channel *chan)
1462 {
1463         /*
1464          * By default, pin the channel to cpu0.  Devices having
1465          * special channel-cpu mapping requirement should call
1466          * vmbus_chan_cpu_{set,rr}().
1467          */
1468         vmbus_chan_cpu_set(chan, 0);
1469 }
1470
1471 static void
1472 vmbus_chan_msgproc_choffer(struct vmbus_softc *sc,
1473     const struct vmbus_message *msg)
1474 {
1475         const struct vmbus_chanmsg_choffer *offer;
1476         struct vmbus_channel *chan;
1477         task_fn_t *detach_fn, *attach_fn;
1478         int error;
1479
1480         offer = (const struct vmbus_chanmsg_choffer *)msg->msg_data;
1481
1482         chan = vmbus_chan_alloc(sc);
1483         if (chan == NULL) {
1484                 device_printf(sc->vmbus_dev, "allocate chan%u failed\n",
1485                     offer->chm_chanid);
1486                 return;
1487         }
1488
1489         chan->ch_id = offer->chm_chanid;
1490         chan->ch_subidx = offer->chm_subidx;
1491         chan->ch_guid_type = offer->chm_chtype;
1492         chan->ch_guid_inst = offer->chm_chinst;
1493
1494         /* Batch reading is on by default */
1495         chan->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD;
1496
1497         chan->ch_monprm->mp_connid = VMBUS_CONNID_EVENT;
1498         if (sc->vmbus_version != VMBUS_VERSION_WS2008)
1499                 chan->ch_monprm->mp_connid = offer->chm_connid;
1500
1501         if (offer->chm_flags1 & VMBUS_CHOFFER_FLAG1_HASMNF) {
1502                 int trig_idx;
1503
1504                 /*
1505                  * Setup MNF stuffs.
1506                  */
1507                 chan->ch_txflags |= VMBUS_CHAN_TXF_HASMNF;
1508
1509                 trig_idx = offer->chm_montrig / VMBUS_MONTRIG_LEN;
1510                 if (trig_idx >= VMBUS_MONTRIGS_MAX)
1511                         panic("invalid monitor trigger %u", offer->chm_montrig);
1512                 chan->ch_montrig =
1513                     &sc->vmbus_mnf2->mnf_trigs[trig_idx].mt_pending;
1514
1515                 chan->ch_montrig_mask =
1516                     1 << (offer->chm_montrig % VMBUS_MONTRIG_LEN);
1517         }
1518
1519         /*
1520          * Setup event flag.
1521          */
1522         chan->ch_evtflag =
1523             &sc->vmbus_tx_evtflags[chan->ch_id >> VMBUS_EVTFLAG_SHIFT];
1524         chan->ch_evtflag_mask = 1UL << (chan->ch_id & VMBUS_EVTFLAG_MASK);
1525
1526         /*
1527          * Setup attach and detach tasks.
1528          */
1529         if (VMBUS_CHAN_ISPRIMARY(chan)) {
1530                 chan->ch_mgmt_tq = sc->vmbus_devtq;
1531                 attach_fn = vmbus_prichan_attach_task;
1532                 detach_fn = vmbus_prichan_detach_task;
1533         } else {
1534                 chan->ch_mgmt_tq = sc->vmbus_subchtq;
1535                 attach_fn = vmbus_subchan_attach_task;
1536                 detach_fn = vmbus_subchan_detach_task;
1537         }
1538         TASK_INIT(&chan->ch_attach_task, 0, attach_fn, chan);
1539         TASK_INIT(&chan->ch_detach_task, 0, detach_fn, chan);
1540
1541         error = vmbus_chan_add(chan);
1542         if (error) {
1543                 device_printf(sc->vmbus_dev, "add chan%u failed: %d\n",
1544                     chan->ch_id, error);
1545                 atomic_subtract_int(&chan->ch_refs, 1);
1546                 vmbus_chan_free(chan);
1547                 return;
1548         }
1549         taskqueue_enqueue(chan->ch_mgmt_tq, &chan->ch_attach_task);
1550 }
1551
1552 static void
1553 vmbus_chan_msgproc_chrescind(struct vmbus_softc *sc,
1554     const struct vmbus_message *msg)
1555 {
1556         const struct vmbus_chanmsg_chrescind *note;
1557         struct vmbus_channel *chan;
1558
1559         note = (const struct vmbus_chanmsg_chrescind *)msg->msg_data;
1560         if (note->chm_chanid > VMBUS_CHAN_MAX) {
1561                 device_printf(sc->vmbus_dev, "invalid revoked chan%u\n",
1562                     note->chm_chanid);
1563                 return;
1564         }
1565
1566         /*
1567          * Find and remove the target channel from the channel list.
1568          */
1569         mtx_lock(&sc->vmbus_chan_lock);
1570         TAILQ_FOREACH(chan, &sc->vmbus_chans, ch_link) {
1571                 if (chan->ch_id == note->chm_chanid)
1572                         break;
1573         }
1574         if (chan == NULL) {
1575                 mtx_unlock(&sc->vmbus_chan_lock);
1576                 device_printf(sc->vmbus_dev, "chan%u is not offered\n",
1577                     note->chm_chanid);
1578                 return;
1579         }
1580         vmbus_chan_rem_list(sc, chan);
1581         mtx_unlock(&sc->vmbus_chan_lock);
1582
1583         if (VMBUS_CHAN_ISPRIMARY(chan)) {
1584                 /*
1585                  * The target channel is a primary channel; remove the
1586                  * target channel from the primary channel list now,
1587                  * instead of later, so that it will not be found by
1588                  * other sub-channel offers, which are processed in
1589                  * this thread.
1590                  */
1591                 mtx_lock(&sc->vmbus_prichan_lock);
1592                 vmbus_chan_rem_prilist(sc, chan);
1593                 mtx_unlock(&sc->vmbus_prichan_lock);
1594         }
1595
1596         /*
1597          * NOTE:
1598          * The following processing order is critical:
1599          * Set the REVOKED state flag before orphaning the installed xact.
1600          */
1601
1602         if (atomic_testandset_int(&chan->ch_stflags,
1603             VMBUS_CHAN_ST_REVOKED_SHIFT))
1604                 panic("channel has already been revoked");
1605
1606         sx_xlock(&chan->ch_orphan_lock);
1607         if (chan->ch_orphan_xact != NULL)
1608                 vmbus_xact_ctx_orphan(chan->ch_orphan_xact);
1609         sx_xunlock(&chan->ch_orphan_lock);
1610
1611         if (bootverbose)
1612                 vmbus_chan_printf(chan, "chan%u revoked\n", note->chm_chanid);
1613         vmbus_chan_detach(chan);
1614 }
1615
1616 static int
1617 vmbus_chan_release(struct vmbus_channel *chan)
1618 {
1619         struct vmbus_softc *sc = chan->ch_vmbus;
1620         struct vmbus_chanmsg_chfree *req;
1621         struct vmbus_msghc *mh;
1622         int error;
1623
1624         mh = vmbus_msghc_get(sc, sizeof(*req));
1625         if (mh == NULL) {
1626                 vmbus_chan_printf(chan,
1627                     "can not get msg hypercall for chfree(chan%u)\n",
1628                     chan->ch_id);
1629                 return (ENXIO);
1630         }
1631
1632         req = vmbus_msghc_dataptr(mh);
1633         req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHFREE;
1634         req->chm_chanid = chan->ch_id;
1635
1636         error = vmbus_msghc_exec_noresult(mh);
1637         vmbus_msghc_put(sc, mh);
1638
1639         if (error) {
1640                 vmbus_chan_printf(chan,
1641                     "chfree(chan%u) msg hypercall exec failed: %d\n",
1642                     chan->ch_id, error);
1643         } else {
1644                 if (bootverbose)
1645                         vmbus_chan_printf(chan, "chan%u freed\n", chan->ch_id);
1646         }
1647         return (error);
1648 }
1649
1650 static void
1651 vmbus_prichan_detach_task(void *xchan, int pending __unused)
1652 {
1653         struct vmbus_channel *chan = xchan;
1654
1655         KASSERT(VMBUS_CHAN_ISPRIMARY(chan),
1656             ("chan%u is not primary channel", chan->ch_id));
1657
1658         /* Delete and detach the device associated with this channel. */
1659         vmbus_delete_child(chan);
1660
1661         /* Release this channel (back to vmbus). */
1662         vmbus_chan_release(chan);
1663
1664         /* Free this channel's resource. */
1665         vmbus_chan_free(chan);
1666 }
1667
1668 static void
1669 vmbus_subchan_detach_task(void *xchan, int pending __unused)
1670 {
1671         struct vmbus_channel *chan = xchan;
1672         struct vmbus_channel *pri_chan = chan->ch_prichan;
1673
1674         KASSERT(!VMBUS_CHAN_ISPRIMARY(chan),
1675             ("chan%u is primary channel", chan->ch_id));
1676
1677         /* Release this channel (back to vmbus). */
1678         vmbus_chan_release(chan);
1679
1680         /* Unlink from its primary channel's sub-channel list. */
1681         mtx_lock(&pri_chan->ch_subchan_lock);
1682         vmbus_chan_rem_sublist(pri_chan, chan);
1683         mtx_unlock(&pri_chan->ch_subchan_lock);
1684         /* Notify anyone that is waiting for this sub-channel to vanish. */
1685         wakeup(pri_chan);
1686
1687         /* Free this channel's resource. */
1688         vmbus_chan_free(chan);
1689 }
1690
1691 static void
1692 vmbus_prichan_attach_task(void *xchan, int pending __unused)
1693 {
1694
1695         /*
1696          * Add device for this primary channel.
1697          */
1698         vmbus_add_child(xchan);
1699 }
1700
1701 static void
1702 vmbus_subchan_attach_task(void *xchan __unused, int pending __unused)
1703 {
1704
1705         /* Nothing */
1706 }
1707
1708 void
1709 vmbus_chan_destroy_all(struct vmbus_softc *sc)
1710 {
1711
1712         /*
1713          * Detach all devices and destroy the corresponding primary
1714          * channels.
1715          */
1716         for (;;) {
1717                 struct vmbus_channel *chan;
1718
1719                 mtx_lock(&sc->vmbus_chan_lock);
1720                 TAILQ_FOREACH(chan, &sc->vmbus_chans, ch_link) {
1721                         if (VMBUS_CHAN_ISPRIMARY(chan))
1722                                 break;
1723                 }
1724                 if (chan == NULL) {
1725                         /* No more primary channels; done. */
1726                         mtx_unlock(&sc->vmbus_chan_lock);
1727                         break;
1728                 }
1729                 vmbus_chan_rem_list(sc, chan);
1730                 mtx_unlock(&sc->vmbus_chan_lock);
1731
1732                 mtx_lock(&sc->vmbus_prichan_lock);
1733                 vmbus_chan_rem_prilist(sc, chan);
1734                 mtx_unlock(&sc->vmbus_prichan_lock);
1735
1736                 taskqueue_enqueue(chan->ch_mgmt_tq, &chan->ch_detach_task);
1737         }
1738 }
1739
1740 struct vmbus_channel **
1741 vmbus_subchan_get(struct vmbus_channel *pri_chan, int subchan_cnt)
1742 {
1743         struct vmbus_channel **ret, *chan;
1744         int i;
1745
1746         KASSERT(subchan_cnt > 0, ("invalid sub-channel count %d", subchan_cnt));
1747
1748         ret = malloc(subchan_cnt * sizeof(struct vmbus_channel *), M_TEMP,
1749             M_WAITOK);
1750
1751         mtx_lock(&pri_chan->ch_subchan_lock);
1752
1753         while (pri_chan->ch_subchan_cnt < subchan_cnt)
1754                 mtx_sleep(pri_chan, &pri_chan->ch_subchan_lock, 0, "subch", 0);
1755
1756         i = 0;
1757         TAILQ_FOREACH(chan, &pri_chan->ch_subchans, ch_sublink) {
1758                 /* TODO: refcnt chan */
1759                 ret[i] = chan;
1760
1761                 ++i;
1762                 if (i == subchan_cnt)
1763                         break;
1764         }
1765         KASSERT(i == subchan_cnt, ("invalid subchan count %d, should be %d",
1766             pri_chan->ch_subchan_cnt, subchan_cnt));
1767
1768         mtx_unlock(&pri_chan->ch_subchan_lock);
1769
1770         return ret;
1771 }
1772
1773 void
1774 vmbus_subchan_rel(struct vmbus_channel **subchan, int subchan_cnt __unused)
1775 {
1776
1777         free(subchan, M_TEMP);
1778 }
1779
1780 void
1781 vmbus_subchan_drain(struct vmbus_channel *pri_chan)
1782 {
1783         mtx_lock(&pri_chan->ch_subchan_lock);
1784         while (pri_chan->ch_subchan_cnt > 0)
1785                 mtx_sleep(pri_chan, &pri_chan->ch_subchan_lock, 0, "dsubch", 0);
1786         mtx_unlock(&pri_chan->ch_subchan_lock);
1787 }
1788
1789 void
1790 vmbus_chan_msgproc(struct vmbus_softc *sc, const struct vmbus_message *msg)
1791 {
1792         vmbus_chanmsg_proc_t msg_proc;
1793         uint32_t msg_type;
1794
1795         msg_type = ((const struct vmbus_chanmsg_hdr *)msg->msg_data)->chm_type;
1796         KASSERT(msg_type < VMBUS_CHANMSG_TYPE_MAX,
1797             ("invalid message type %u", msg_type));
1798
1799         msg_proc = vmbus_chan_msgprocs[msg_type];
1800         if (msg_proc != NULL)
1801                 msg_proc(sc, msg);
1802 }
1803
1804 void
1805 vmbus_chan_set_readbatch(struct vmbus_channel *chan, bool on)
1806 {
1807         if (!on)
1808                 chan->ch_flags &= ~VMBUS_CHAN_FLAG_BATCHREAD;
1809         else
1810                 chan->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD;
1811 }
1812
1813 uint32_t
1814 vmbus_chan_id(const struct vmbus_channel *chan)
1815 {
1816         return chan->ch_id;
1817 }
1818
1819 uint32_t
1820 vmbus_chan_subidx(const struct vmbus_channel *chan)
1821 {
1822         return chan->ch_subidx;
1823 }
1824
1825 bool
1826 vmbus_chan_is_primary(const struct vmbus_channel *chan)
1827 {
1828         if (VMBUS_CHAN_ISPRIMARY(chan))
1829                 return true;
1830         else
1831                 return false;
1832 }
1833
1834 const struct hyperv_guid *
1835 vmbus_chan_guid_inst(const struct vmbus_channel *chan)
1836 {
1837         return &chan->ch_guid_inst;
1838 }
1839
1840 int
1841 vmbus_chan_prplist_nelem(int br_size, int prpcnt_max, int dlen_max)
1842 {
1843         int elem_size;
1844
1845         elem_size = __offsetof(struct vmbus_chanpkt_prplist,
1846             cp_range[0].gpa_page[prpcnt_max]);
1847         elem_size += dlen_max;
1848         elem_size = VMBUS_CHANPKT_TOTLEN(elem_size);
1849
1850         return (vmbus_br_nelem(br_size, elem_size));
1851 }
1852
1853 bool
1854 vmbus_chan_tx_empty(const struct vmbus_channel *chan)
1855 {
1856
1857         return (vmbus_txbr_empty(&chan->ch_txbr));
1858 }
1859
1860 bool
1861 vmbus_chan_rx_empty(const struct vmbus_channel *chan)
1862 {
1863
1864         return (vmbus_rxbr_empty(&chan->ch_rxbr));
1865 }
1866
1867 static int
1868 vmbus_chan_printf(const struct vmbus_channel *chan, const char *fmt, ...)
1869 {
1870         va_list ap;
1871         device_t dev;
1872         int retval;
1873
1874         if (chan->ch_dev == NULL || !device_is_alive(chan->ch_dev))
1875                 dev = chan->ch_vmbus->vmbus_dev;
1876         else
1877                 dev = chan->ch_dev;
1878
1879         retval = device_print_prettyname(dev);
1880         va_start(ap, fmt);
1881         retval += vprintf(fmt, ap);
1882         va_end(ap);
1883
1884         return (retval);
1885 }
1886
1887 void
1888 vmbus_chan_run_task(struct vmbus_channel *chan, struct task *task)
1889 {
1890
1891         taskqueue_enqueue(chan->ch_tq, task);
1892         taskqueue_drain(chan->ch_tq, task);
1893 }
1894
1895 struct taskqueue *
1896 vmbus_chan_mgmt_tq(const struct vmbus_channel *chan)
1897 {
1898
1899         return (chan->ch_mgmt_tq);
1900 }
1901
1902 bool
1903 vmbus_chan_is_revoked(const struct vmbus_channel *chan)
1904 {
1905
1906         if (chan->ch_stflags & VMBUS_CHAN_ST_REVOKED)
1907                 return (true);
1908         return (false);
1909 }
1910
1911 void
1912 vmbus_chan_set_orphan(struct vmbus_channel *chan, struct vmbus_xact_ctx *xact)
1913 {
1914
1915         sx_xlock(&chan->ch_orphan_lock);
1916         chan->ch_orphan_xact = xact;
1917         sx_xunlock(&chan->ch_orphan_lock);
1918 }
1919
1920 void
1921 vmbus_chan_unset_orphan(struct vmbus_channel *chan)
1922 {
1923
1924         sx_xlock(&chan->ch_orphan_lock);
1925         chan->ch_orphan_xact = NULL;
1926         sx_xunlock(&chan->ch_orphan_lock);
1927 }
1928
1929 const void *
1930 vmbus_chan_xact_wait(const struct vmbus_channel *chan,
1931     struct vmbus_xact *xact, size_t *resp_len, bool can_sleep)
1932 {
1933         const void *ret;
1934
1935         if (can_sleep)
1936                 ret = vmbus_xact_wait(xact, resp_len);
1937         else
1938                 ret = vmbus_xact_busywait(xact, resp_len);
1939         if (vmbus_chan_is_revoked(chan)) {
1940                 /*
1941                  * This xact probably is interrupted, and the
1942                  * interruption can race the reply reception,
1943                  * so we have to make sure that there are nothing
1944                  * left on the RX bufring, i.e. this xact will
1945                  * not be touched, once this function returns.
1946                  *
1947                  * Since the hypervisor will not put more data
1948                  * onto the RX bufring once the channel is revoked,
1949                  * the following loop will be terminated, once all
1950                  * data are drained by the driver's channel
1951                  * callback.
1952                  */
1953                 while (!vmbus_chan_rx_empty(chan)) {
1954                         if (can_sleep)
1955                                 pause("chxact", 1);
1956                         else
1957                                 DELAY(1000);
1958                 }
1959         }
1960         return (ret);
1961 }