vmbus_chan.c revision 311364
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: stable/11/sys/dev/hyperv/vmbus/vmbus_chan.c 311364 2017-01-05 05:24:30Z sephe $"); 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 53static void vmbus_chan_update_evtflagcnt( 54 struct vmbus_softc *, 55 const struct vmbus_channel *); 56static int vmbus_chan_close_internal( 57 struct vmbus_channel *); 58static int vmbus_chan_sysctl_mnf(SYSCTL_HANDLER_ARGS); 59static void vmbus_chan_sysctl_create( 60 struct vmbus_channel *); 61static struct vmbus_channel *vmbus_chan_alloc(struct vmbus_softc *); 62static void vmbus_chan_free(struct vmbus_channel *); 63static int vmbus_chan_add(struct vmbus_channel *); 64static void vmbus_chan_cpu_default(struct vmbus_channel *); 65static int vmbus_chan_release(struct vmbus_channel *); 66static void vmbus_chan_set_chmap(struct vmbus_channel *); 67static void vmbus_chan_clear_chmap(struct vmbus_channel *); 68static void vmbus_chan_detach(struct vmbus_channel *); 69static bool vmbus_chan_wait_revoke( 70 const struct vmbus_channel *); 71 72static void vmbus_chan_ins_prilist(struct vmbus_softc *, 73 struct vmbus_channel *); 74static void vmbus_chan_rem_prilist(struct vmbus_softc *, 75 struct vmbus_channel *); 76static void vmbus_chan_ins_list(struct vmbus_softc *, 77 struct vmbus_channel *); 78static void vmbus_chan_rem_list(struct vmbus_softc *, 79 struct vmbus_channel *); 80static void vmbus_chan_ins_sublist(struct vmbus_channel *, 81 struct vmbus_channel *); 82static void vmbus_chan_rem_sublist(struct vmbus_channel *, 83 struct vmbus_channel *); 84 85static void vmbus_chan_task(void *, int); 86static void vmbus_chan_task_nobatch(void *, int); 87static void vmbus_chan_clrchmap_task(void *, int); 88static void vmbus_prichan_attach_task(void *, int); 89static void vmbus_subchan_attach_task(void *, int); 90static void vmbus_prichan_detach_task(void *, int); 91static void vmbus_subchan_detach_task(void *, int); 92 93static void vmbus_chan_msgproc_choffer(struct vmbus_softc *, 94 const struct vmbus_message *); 95static void vmbus_chan_msgproc_chrescind( 96 struct vmbus_softc *, 97 const struct vmbus_message *); 98 99static int vmbus_chan_printf(const struct vmbus_channel *, 100 const char *, ...) __printflike(2, 3); 101 102/* 103 * Vmbus channel message processing. 104 */ 105static const vmbus_chanmsg_proc_t 106vmbus_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 */ 118static __inline void 119vmbus_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 128static void 129vmbus_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 139static void 140vmbus_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 150static void 151vmbus_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 166static void 167vmbus_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 183static void 184vmbus_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 194static void 195vmbus_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 205static int 206vmbus_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 216static void 217vmbus_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 301int 302vmbus_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 347int 348vmbus_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 471failed: 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 492int 493vmbus_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 /* 506 * Reset GPADL, so that the result would consistent, if error 507 * happened later on. 508 */ 509 *gpadl0 = 0; 510 511 /* 512 * Preliminary checks. 513 */ 514 515 KASSERT((size & PAGE_MASK) == 0, 516 ("invalid GPA size %d, not multiple page size", size)); 517 page_count = size >> PAGE_SHIFT; 518 519 KASSERT((paddr & PAGE_MASK) == 0, 520 ("GPA is not page aligned %jx", (uintmax_t)paddr)); 521 page_id = paddr >> PAGE_SHIFT; 522 523 range_len = __offsetof(struct vmbus_gpa_range, gpa_page[page_count]); 524 /* 525 * We don't support multiple GPA ranges. 526 */ 527 if (range_len > UINT16_MAX) { 528 vmbus_chan_printf(chan, "GPA too large, %d pages\n", 529 page_count); 530 return EOPNOTSUPP; 531 } 532 533 /* 534 * Allocate GPADL id. 535 */ 536 gpadl = vmbus_gpadl_alloc(sc); 537 538 /* 539 * Connect this GPADL to the target channel. 540 * 541 * NOTE: 542 * Since each message can only hold small set of page 543 * addresses, several messages may be required to 544 * complete the connection. 545 */ 546 if (page_count > VMBUS_CHANMSG_GPADL_CONN_PGMAX) 547 cnt = VMBUS_CHANMSG_GPADL_CONN_PGMAX; 548 else 549 cnt = page_count; 550 page_count -= cnt; 551 552 reqsz = __offsetof(struct vmbus_chanmsg_gpadl_conn, 553 chm_range.gpa_page[cnt]); 554 mh = vmbus_msghc_get(sc, reqsz); 555 if (mh == NULL) { 556 vmbus_chan_printf(chan, 557 "can not get msg hypercall for gpadl_conn(chan%u)\n", 558 chan->ch_id); 559 return EIO; 560 } 561 562 req = vmbus_msghc_dataptr(mh); 563 req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_CONN; 564 req->chm_chanid = chan->ch_id; 565 req->chm_gpadl = gpadl; 566 req->chm_range_len = range_len; 567 req->chm_range_cnt = 1; 568 req->chm_range.gpa_len = size; 569 req->chm_range.gpa_ofs = 0; 570 for (i = 0; i < cnt; ++i) 571 req->chm_range.gpa_page[i] = page_id++; 572 573 error = vmbus_msghc_exec(sc, mh); 574 if (error) { 575 vmbus_chan_printf(chan, 576 "gpadl_conn(chan%u) msg hypercall exec failed: %d\n", 577 chan->ch_id, error); 578 vmbus_msghc_put(sc, mh); 579 return error; 580 } 581 582 while (page_count > 0) { 583 struct vmbus_chanmsg_gpadl_subconn *subreq; 584 585 if (page_count > VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX) 586 cnt = VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX; 587 else 588 cnt = page_count; 589 page_count -= cnt; 590 591 reqsz = __offsetof(struct vmbus_chanmsg_gpadl_subconn, 592 chm_gpa_page[cnt]); 593 vmbus_msghc_reset(mh, reqsz); 594 595 subreq = vmbus_msghc_dataptr(mh); 596 subreq->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_SUBCONN; 597 subreq->chm_gpadl = gpadl; 598 for (i = 0; i < cnt; ++i) 599 subreq->chm_gpa_page[i] = page_id++; 600 601 vmbus_msghc_exec_noresult(mh); 602 } 603 KASSERT(page_count == 0, ("invalid page count %d", page_count)); 604 605 msg = vmbus_msghc_wait_result(sc, mh); 606 status = ((const struct vmbus_chanmsg_gpadl_connresp *) 607 msg->msg_data)->chm_status; 608 609 vmbus_msghc_put(sc, mh); 610 611 if (status != 0) { 612 vmbus_chan_printf(chan, "gpadl_conn(chan%u) failed: %u\n", 613 chan->ch_id, status); 614 return EIO; 615 } 616 617 /* Done; commit the GPADL id. */ 618 *gpadl0 = gpadl; 619 if (bootverbose) { 620 vmbus_chan_printf(chan, "gpadl_conn(chan%u) succeeded\n", 621 chan->ch_id); 622 } 623 return 0; 624} 625 626static bool 627vmbus_chan_wait_revoke(const struct vmbus_channel *chan) 628{ 629#define WAIT_COUNT 200 /* 200ms */ 630 631 int i; 632 633 for (i = 0; i < WAIT_COUNT; ++i) { 634 if (vmbus_chan_is_revoked(chan)) 635 return (true); 636 /* Not sure about the context; use busy-wait. */ 637 DELAY(1000); 638 } 639 return (false); 640 641#undef WAIT_COUNT 642} 643 644/* 645 * Disconnect the GPA from the target channel 646 */ 647int 648vmbus_chan_gpadl_disconnect(struct vmbus_channel *chan, uint32_t gpadl) 649{ 650 struct vmbus_softc *sc = chan->ch_vmbus; 651 struct vmbus_msghc *mh; 652 struct vmbus_chanmsg_gpadl_disconn *req; 653 int error; 654 655 mh = vmbus_msghc_get(sc, sizeof(*req)); 656 if (mh == NULL) { 657 vmbus_chan_printf(chan, 658 "can not get msg hypercall for gpadl_disconn(chan%u)\n", 659 chan->ch_id); 660 return (EBUSY); 661 } 662 663 req = vmbus_msghc_dataptr(mh); 664 req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_DISCONN; 665 req->chm_chanid = chan->ch_id; 666 req->chm_gpadl = gpadl; 667 668 error = vmbus_msghc_exec(sc, mh); 669 if (error) { 670 vmbus_msghc_put(sc, mh); 671 672 if (vmbus_chan_wait_revoke(chan)) { 673 /* 674 * Error is benign; this channel is revoked, 675 * so this GPADL will not be touched anymore. 676 */ 677 vmbus_chan_printf(chan, 678 "gpadl_disconn(revoked chan%u) msg hypercall " 679 "exec failed: %d\n", chan->ch_id, error); 680 return (0); 681 } 682 vmbus_chan_printf(chan, 683 "gpadl_disconn(chan%u) msg hypercall exec failed: %d\n", 684 chan->ch_id, error); 685 return (error); 686 } 687 688 vmbus_msghc_wait_result(sc, mh); 689 /* Discard result; no useful information */ 690 vmbus_msghc_put(sc, mh); 691 692 return (0); 693} 694 695static void 696vmbus_chan_detach(struct vmbus_channel *chan) 697{ 698 int refs; 699 700 KASSERT(chan->ch_refs > 0, ("chan%u: invalid refcnt %d", 701 chan->ch_id, chan->ch_refs)); 702 refs = atomic_fetchadd_int(&chan->ch_refs, -1); 703#ifdef INVARIANTS 704 if (VMBUS_CHAN_ISPRIMARY(chan)) { 705 KASSERT(refs == 1, ("chan%u: invalid refcnt %d for prichan", 706 chan->ch_id, refs + 1)); 707 } 708#endif 709 if (refs == 1) { 710 /* 711 * Detach the target channel. 712 */ 713 if (bootverbose) { 714 vmbus_chan_printf(chan, "chan%u detached\n", 715 chan->ch_id); 716 } 717 taskqueue_enqueue(chan->ch_mgmt_tq, &chan->ch_detach_task); 718 } 719} 720 721static void 722vmbus_chan_clrchmap_task(void *xchan, int pending __unused) 723{ 724 struct vmbus_channel *chan = xchan; 725 726 critical_enter(); 727 chan->ch_vmbus->vmbus_chmap[chan->ch_id] = NULL; 728 critical_exit(); 729} 730 731static void 732vmbus_chan_clear_chmap(struct vmbus_channel *chan) 733{ 734 struct task chmap_task; 735 736 TASK_INIT(&chmap_task, 0, vmbus_chan_clrchmap_task, chan); 737 taskqueue_enqueue(chan->ch_tq, &chmap_task); 738 taskqueue_drain(chan->ch_tq, &chmap_task); 739} 740 741static void 742vmbus_chan_set_chmap(struct vmbus_channel *chan) 743{ 744 __compiler_membar(); 745 chan->ch_vmbus->vmbus_chmap[chan->ch_id] = chan; 746} 747 748static int 749vmbus_chan_close_internal(struct vmbus_channel *chan) 750{ 751 struct vmbus_softc *sc = chan->ch_vmbus; 752 struct vmbus_msghc *mh; 753 struct vmbus_chanmsg_chclose *req; 754 uint32_t old_stflags; 755 int error; 756 757 /* 758 * NOTE: 759 * Sub-channels are closed upon their primary channel closing, 760 * so they can be closed even before they are opened. 761 */ 762 for (;;) { 763 old_stflags = chan->ch_stflags; 764 if (atomic_cmpset_int(&chan->ch_stflags, old_stflags, 765 old_stflags & ~VMBUS_CHAN_ST_OPENED)) 766 break; 767 } 768 if ((old_stflags & VMBUS_CHAN_ST_OPENED) == 0) { 769 /* Not opened yet; done */ 770 if (bootverbose) { 771 vmbus_chan_printf(chan, "chan%u not opened\n", 772 chan->ch_id); 773 } 774 return (0); 775 } 776 777 /* 778 * Free this channel's sysctl tree attached to its device's 779 * sysctl tree. 780 */ 781 sysctl_ctx_free(&chan->ch_sysctl_ctx); 782 783 /* 784 * NOTE: 785 * Order is critical. This channel _must_ be uninstalled first, 786 * else the channel task may be enqueued by the IDT after it has 787 * been drained. 788 */ 789 vmbus_chan_clear_chmap(chan); 790 taskqueue_drain(chan->ch_tq, &chan->ch_task); 791 chan->ch_tq = NULL; 792 793 /* 794 * Close this channel. 795 */ 796 mh = vmbus_msghc_get(sc, sizeof(*req)); 797 if (mh == NULL) { 798 vmbus_chan_printf(chan, 799 "can not get msg hypercall for chclose(chan%u)\n", 800 chan->ch_id); 801 error = ENXIO; 802 goto disconnect; 803 } 804 805 req = vmbus_msghc_dataptr(mh); 806 req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHCLOSE; 807 req->chm_chanid = chan->ch_id; 808 809 error = vmbus_msghc_exec_noresult(mh); 810 vmbus_msghc_put(sc, mh); 811 812 if (error) { 813 vmbus_chan_printf(chan, 814 "chclose(chan%u) msg hypercall exec failed: %d\n", 815 chan->ch_id, error); 816 goto disconnect; 817 } 818 819 if (bootverbose) 820 vmbus_chan_printf(chan, "chan%u closed\n", chan->ch_id); 821 822disconnect: 823 /* 824 * Disconnect the TX+RX bufrings from this channel. 825 */ 826 if (chan->ch_bufring_gpadl != 0) { 827 int error1; 828 829 error1 = vmbus_chan_gpadl_disconnect(chan, 830 chan->ch_bufring_gpadl); 831 if (error1) { 832 /* 833 * XXX 834 * The bufring GPADL is still connected; abandon 835 * this bufring, instead of having mysterious 836 * crash or trashed data later on. 837 */ 838 vmbus_chan_printf(chan, "chan%u bufring GPADL " 839 "is still connected after close\n", chan->ch_id); 840 chan->ch_bufring = NULL; 841 /* 842 * Give caller a hint that the bufring GPADL is 843 * still connected. 844 */ 845 error = EISCONN; 846 } 847 chan->ch_bufring_gpadl = 0; 848 } 849 850 /* 851 * Destroy the TX+RX bufrings. 852 */ 853 if (chan->ch_bufring != NULL) { 854 hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring); 855 chan->ch_bufring = NULL; 856 } 857 return (error); 858} 859 860int 861vmbus_chan_close_direct(struct vmbus_channel *chan) 862{ 863 int error; 864 865#ifdef INVARIANTS 866 if (VMBUS_CHAN_ISPRIMARY(chan)) { 867 struct vmbus_channel *subchan; 868 869 /* 870 * All sub-channels _must_ have been closed, or are _not_ 871 * opened at all. 872 */ 873 mtx_lock(&chan->ch_subchan_lock); 874 TAILQ_FOREACH(subchan, &chan->ch_subchans, ch_sublink) { 875 KASSERT( 876 (subchan->ch_stflags & VMBUS_CHAN_ST_OPENED) == 0, 877 ("chan%u: subchan%u is still opened", 878 chan->ch_id, subchan->ch_subidx)); 879 } 880 mtx_unlock(&chan->ch_subchan_lock); 881 } 882#endif 883 884 error = vmbus_chan_close_internal(chan); 885 if (!VMBUS_CHAN_ISPRIMARY(chan)) { 886 /* 887 * This sub-channel is referenced, when it is linked to 888 * the primary channel; drop that reference now. 889 */ 890 vmbus_chan_detach(chan); 891 } 892 return (error); 893} 894 895/* 896 * Caller should make sure that all sub-channels have 897 * been added to 'chan' and all to-be-closed channels 898 * are not being opened. 899 */ 900void 901vmbus_chan_close(struct vmbus_channel *chan) 902{ 903 int subchan_cnt; 904 905 if (!VMBUS_CHAN_ISPRIMARY(chan)) { 906 /* 907 * Sub-channel is closed when its primary channel 908 * is closed; done. 909 */ 910 return; 911 } 912 913 /* 914 * Close all sub-channels, if any. 915 */ 916 subchan_cnt = chan->ch_subchan_cnt; 917 if (subchan_cnt > 0) { 918 struct vmbus_channel **subchan; 919 int i; 920 921 subchan = vmbus_subchan_get(chan, subchan_cnt); 922 for (i = 0; i < subchan_cnt; ++i) { 923 vmbus_chan_close_internal(subchan[i]); 924 /* 925 * This sub-channel is referenced, when it is 926 * linked to the primary channel; drop that 927 * reference now. 928 */ 929 vmbus_chan_detach(subchan[i]); 930 } 931 vmbus_subchan_rel(subchan, subchan_cnt); 932 } 933 934 /* Then close the primary channel. */ 935 vmbus_chan_close_internal(chan); 936} 937 938void 939vmbus_chan_intr_drain(struct vmbus_channel *chan) 940{ 941 942 taskqueue_drain(chan->ch_tq, &chan->ch_task); 943} 944 945int 946vmbus_chan_send(struct vmbus_channel *chan, uint16_t type, uint16_t flags, 947 void *data, int dlen, uint64_t xactid) 948{ 949 struct vmbus_chanpkt pkt; 950 int pktlen, pad_pktlen, hlen, error; 951 uint64_t pad = 0; 952 struct iovec iov[3]; 953 boolean_t send_evt; 954 955 hlen = sizeof(pkt); 956 pktlen = hlen + dlen; 957 pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen); 958 KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr), 959 ("invalid packet size %d", pad_pktlen)); 960 961 pkt.cp_hdr.cph_type = type; 962 pkt.cp_hdr.cph_flags = flags; 963 VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_hlen, hlen); 964 VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_tlen, pad_pktlen); 965 pkt.cp_hdr.cph_xactid = xactid; 966 967 iov[0].iov_base = &pkt; 968 iov[0].iov_len = hlen; 969 iov[1].iov_base = data; 970 iov[1].iov_len = dlen; 971 iov[2].iov_base = &pad; 972 iov[2].iov_len = pad_pktlen - pktlen; 973 974 error = vmbus_txbr_write(&chan->ch_txbr, iov, 3, &send_evt); 975 if (!error && send_evt) 976 vmbus_chan_signal_tx(chan); 977 return error; 978} 979 980int 981vmbus_chan_send_sglist(struct vmbus_channel *chan, 982 struct vmbus_gpa sg[], int sglen, void *data, int dlen, uint64_t xactid) 983{ 984 struct vmbus_chanpkt_sglist pkt; 985 int pktlen, pad_pktlen, hlen, error; 986 struct iovec iov[4]; 987 boolean_t send_evt; 988 uint64_t pad = 0; 989 990 hlen = __offsetof(struct vmbus_chanpkt_sglist, cp_gpa[sglen]); 991 pktlen = hlen + dlen; 992 pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen); 993 KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr), 994 ("invalid packet size %d", pad_pktlen)); 995 996 pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA; 997 pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC; 998 VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_hlen, hlen); 999 VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_tlen, pad_pktlen); 1000 pkt.cp_hdr.cph_xactid = xactid; 1001 pkt.cp_rsvd = 0; 1002 pkt.cp_gpa_cnt = sglen; 1003 1004 iov[0].iov_base = &pkt; 1005 iov[0].iov_len = sizeof(pkt); 1006 iov[1].iov_base = sg; 1007 iov[1].iov_len = sizeof(struct vmbus_gpa) * sglen; 1008 iov[2].iov_base = data; 1009 iov[2].iov_len = dlen; 1010 iov[3].iov_base = &pad; 1011 iov[3].iov_len = pad_pktlen - pktlen; 1012 1013 error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt); 1014 if (!error && send_evt) 1015 vmbus_chan_signal_tx(chan); 1016 return error; 1017} 1018 1019int 1020vmbus_chan_send_prplist(struct vmbus_channel *chan, 1021 struct vmbus_gpa_range *prp, int prp_cnt, void *data, int dlen, 1022 uint64_t xactid) 1023{ 1024 struct vmbus_chanpkt_prplist pkt; 1025 int pktlen, pad_pktlen, hlen, error; 1026 struct iovec iov[4]; 1027 boolean_t send_evt; 1028 uint64_t pad = 0; 1029 1030 hlen = __offsetof(struct vmbus_chanpkt_prplist, 1031 cp_range[0].gpa_page[prp_cnt]); 1032 pktlen = hlen + dlen; 1033 pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen); 1034 KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr), 1035 ("invalid packet size %d", pad_pktlen)); 1036 1037 pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA; 1038 pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC; 1039 VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_hlen, hlen); 1040 VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_tlen, pad_pktlen); 1041 pkt.cp_hdr.cph_xactid = xactid; 1042 pkt.cp_rsvd = 0; 1043 pkt.cp_range_cnt = 1; 1044 1045 iov[0].iov_base = &pkt; 1046 iov[0].iov_len = sizeof(pkt); 1047 iov[1].iov_base = prp; 1048 iov[1].iov_len = __offsetof(struct vmbus_gpa_range, gpa_page[prp_cnt]); 1049 iov[2].iov_base = data; 1050 iov[2].iov_len = dlen; 1051 iov[3].iov_base = &pad; 1052 iov[3].iov_len = pad_pktlen - pktlen; 1053 1054 error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt); 1055 if (!error && send_evt) 1056 vmbus_chan_signal_tx(chan); 1057 return error; 1058} 1059 1060int 1061vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0, 1062 uint64_t *xactid) 1063{ 1064 struct vmbus_chanpkt_hdr pkt; 1065 int error, dlen, hlen; 1066 1067 error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); 1068 if (error) 1069 return (error); 1070 1071 if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) { 1072 vmbus_chan_printf(chan, "invalid hlen %u\n", pkt.cph_hlen); 1073 /* XXX this channel is dead actually. */ 1074 return (EIO); 1075 } 1076 if (__predict_false(pkt.cph_hlen > pkt.cph_tlen)) { 1077 vmbus_chan_printf(chan, "invalid hlen %u and tlen %u\n", 1078 pkt.cph_hlen, pkt.cph_tlen); 1079 /* XXX this channel is dead actually. */ 1080 return (EIO); 1081 } 1082 1083 hlen = VMBUS_CHANPKT_GETLEN(pkt.cph_hlen); 1084 dlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen) - hlen; 1085 1086 if (*dlen0 < dlen) { 1087 /* Return the size of this packet's data. */ 1088 *dlen0 = dlen; 1089 return (ENOBUFS); 1090 } 1091 1092 *xactid = pkt.cph_xactid; 1093 *dlen0 = dlen; 1094 1095 /* Skip packet header */ 1096 error = vmbus_rxbr_read(&chan->ch_rxbr, data, dlen, hlen); 1097 KASSERT(!error, ("vmbus_rxbr_read failed")); 1098 1099 return (0); 1100} 1101 1102int 1103vmbus_chan_recv_pkt(struct vmbus_channel *chan, 1104 struct vmbus_chanpkt_hdr *pkt, int *pktlen0) 1105{ 1106 int error, pktlen, pkt_hlen; 1107 1108 pkt_hlen = sizeof(*pkt); 1109 error = vmbus_rxbr_peek(&chan->ch_rxbr, pkt, pkt_hlen); 1110 if (error) 1111 return (error); 1112 1113 if (__predict_false(pkt->cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) { 1114 vmbus_chan_printf(chan, "invalid hlen %u\n", pkt->cph_hlen); 1115 /* XXX this channel is dead actually. */ 1116 return (EIO); 1117 } 1118 if (__predict_false(pkt->cph_hlen > pkt->cph_tlen)) { 1119 vmbus_chan_printf(chan, "invalid hlen %u and tlen %u\n", 1120 pkt->cph_hlen, pkt->cph_tlen); 1121 /* XXX this channel is dead actually. */ 1122 return (EIO); 1123 } 1124 1125 pktlen = VMBUS_CHANPKT_GETLEN(pkt->cph_tlen); 1126 if (*pktlen0 < pktlen) { 1127 /* Return the size of this packet. */ 1128 *pktlen0 = pktlen; 1129 return (ENOBUFS); 1130 } 1131 *pktlen0 = pktlen; 1132 1133 /* 1134 * Skip the fixed-size packet header, which has been filled 1135 * by the above vmbus_rxbr_peek(). 1136 */ 1137 error = vmbus_rxbr_read(&chan->ch_rxbr, pkt + 1, 1138 pktlen - pkt_hlen, pkt_hlen); 1139 KASSERT(!error, ("vmbus_rxbr_read failed")); 1140 1141 return (0); 1142} 1143 1144static void 1145vmbus_chan_task(void *xchan, int pending __unused) 1146{ 1147 struct vmbus_channel *chan = xchan; 1148 vmbus_chan_callback_t cb = chan->ch_cb; 1149 void *cbarg = chan->ch_cbarg; 1150 1151 /* 1152 * Optimize host to guest signaling by ensuring: 1153 * 1. While reading the channel, we disable interrupts from 1154 * host. 1155 * 2. Ensure that we process all posted messages from the host 1156 * before returning from this callback. 1157 * 3. Once we return, enable signaling from the host. Once this 1158 * state is set we check to see if additional packets are 1159 * available to read. In this case we repeat the process. 1160 * 1161 * NOTE: Interrupt has been disabled in the ISR. 1162 */ 1163 for (;;) { 1164 uint32_t left; 1165 1166 cb(chan, cbarg); 1167 1168 left = vmbus_rxbr_intr_unmask(&chan->ch_rxbr); 1169 if (left == 0) { 1170 /* No more data in RX bufring; done */ 1171 break; 1172 } 1173 vmbus_rxbr_intr_mask(&chan->ch_rxbr); 1174 } 1175} 1176 1177static void 1178vmbus_chan_task_nobatch(void *xchan, int pending __unused) 1179{ 1180 struct vmbus_channel *chan = xchan; 1181 1182 chan->ch_cb(chan, chan->ch_cbarg); 1183} 1184 1185static __inline void 1186vmbus_event_flags_proc(struct vmbus_softc *sc, volatile u_long *event_flags, 1187 int flag_cnt) 1188{ 1189 int f; 1190 1191 for (f = 0; f < flag_cnt; ++f) { 1192 uint32_t chid_base; 1193 u_long flags; 1194 int chid_ofs; 1195 1196 if (event_flags[f] == 0) 1197 continue; 1198 1199 flags = atomic_swap_long(&event_flags[f], 0); 1200 chid_base = f << VMBUS_EVTFLAG_SHIFT; 1201 1202 while ((chid_ofs = ffsl(flags)) != 0) { 1203 struct vmbus_channel *chan; 1204 1205 --chid_ofs; /* NOTE: ffsl is 1-based */ 1206 flags &= ~(1UL << chid_ofs); 1207 1208 chan = sc->vmbus_chmap[chid_base + chid_ofs]; 1209 if (__predict_false(chan == NULL)) { 1210 /* Channel is closed. */ 1211 continue; 1212 } 1213 __compiler_membar(); 1214 1215 if (chan->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD) 1216 vmbus_rxbr_intr_mask(&chan->ch_rxbr); 1217 taskqueue_enqueue(chan->ch_tq, &chan->ch_task); 1218 } 1219 } 1220} 1221 1222void 1223vmbus_event_proc(struct vmbus_softc *sc, int cpu) 1224{ 1225 struct vmbus_evtflags *eventf; 1226 1227 /* 1228 * On Host with Win8 or above, the event page can be checked directly 1229 * to get the id of the channel that has the pending interrupt. 1230 */ 1231 eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE; 1232 vmbus_event_flags_proc(sc, eventf->evt_flags, 1233 VMBUS_PCPU_GET(sc, event_flags_cnt, cpu)); 1234} 1235 1236void 1237vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu) 1238{ 1239 struct vmbus_evtflags *eventf; 1240 1241 eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE; 1242 if (atomic_testandclear_long(&eventf->evt_flags[0], 0)) { 1243 vmbus_event_flags_proc(sc, sc->vmbus_rx_evtflags, 1244 VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT); 1245 } 1246} 1247 1248static void 1249vmbus_chan_update_evtflagcnt(struct vmbus_softc *sc, 1250 const struct vmbus_channel *chan) 1251{ 1252 volatile int *flag_cnt_ptr; 1253 int flag_cnt; 1254 1255 flag_cnt = (chan->ch_id / VMBUS_EVTFLAG_LEN) + 1; 1256 flag_cnt_ptr = VMBUS_PCPU_PTR(sc, event_flags_cnt, chan->ch_cpuid); 1257 1258 for (;;) { 1259 int old_flag_cnt; 1260 1261 old_flag_cnt = *flag_cnt_ptr; 1262 if (old_flag_cnt >= flag_cnt) 1263 break; 1264 if (atomic_cmpset_int(flag_cnt_ptr, old_flag_cnt, flag_cnt)) { 1265 if (bootverbose) { 1266 vmbus_chan_printf(chan, 1267 "chan%u update cpu%d flag_cnt to %d\n", 1268 chan->ch_id, chan->ch_cpuid, flag_cnt); 1269 } 1270 break; 1271 } 1272 } 1273} 1274 1275static struct vmbus_channel * 1276vmbus_chan_alloc(struct vmbus_softc *sc) 1277{ 1278 struct vmbus_channel *chan; 1279 1280 chan = malloc(sizeof(*chan), M_DEVBUF, M_WAITOK | M_ZERO); 1281 1282 chan->ch_monprm = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev), 1283 HYPERCALL_PARAM_ALIGN, 0, sizeof(struct hyperv_mon_param), 1284 &chan->ch_monprm_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO); 1285 if (chan->ch_monprm == NULL) { 1286 device_printf(sc->vmbus_dev, "monprm alloc failed\n"); 1287 free(chan, M_DEVBUF); 1288 return NULL; 1289 } 1290 1291 chan->ch_refs = 1; 1292 chan->ch_vmbus = sc; 1293 mtx_init(&chan->ch_subchan_lock, "vmbus subchan", NULL, MTX_DEF); 1294 sx_init(&chan->ch_orphan_lock, "vmbus chorphan"); 1295 TAILQ_INIT(&chan->ch_subchans); 1296 vmbus_rxbr_init(&chan->ch_rxbr); 1297 vmbus_txbr_init(&chan->ch_txbr); 1298 1299 return chan; 1300} 1301 1302static void 1303vmbus_chan_free(struct vmbus_channel *chan) 1304{ 1305 1306 KASSERT(TAILQ_EMPTY(&chan->ch_subchans) && chan->ch_subchan_cnt == 0, 1307 ("still owns sub-channels")); 1308 KASSERT((chan->ch_stflags & 1309 (VMBUS_CHAN_ST_OPENED | 1310 VMBUS_CHAN_ST_ONPRIL | 1311 VMBUS_CHAN_ST_ONSUBL | 1312 VMBUS_CHAN_ST_ONLIST)) == 0, ("free busy channel")); 1313 KASSERT(chan->ch_orphan_xact == NULL, 1314 ("still has orphan xact installed")); 1315 KASSERT(chan->ch_refs == 0, ("chan%u: invalid refcnt %d", 1316 chan->ch_id, chan->ch_refs)); 1317 1318 hyperv_dmamem_free(&chan->ch_monprm_dma, chan->ch_monprm); 1319 mtx_destroy(&chan->ch_subchan_lock); 1320 sx_destroy(&chan->ch_orphan_lock); 1321 vmbus_rxbr_deinit(&chan->ch_rxbr); 1322 vmbus_txbr_deinit(&chan->ch_txbr); 1323 free(chan, M_DEVBUF); 1324} 1325 1326static int 1327vmbus_chan_add(struct vmbus_channel *newchan) 1328{ 1329 struct vmbus_softc *sc = newchan->ch_vmbus; 1330 struct vmbus_channel *prichan; 1331 1332 if (newchan->ch_id == 0) { 1333 /* 1334 * XXX 1335 * Chan0 will neither be processed nor should be offered; 1336 * skip it. 1337 */ 1338 device_printf(sc->vmbus_dev, "got chan0 offer, discard\n"); 1339 return EINVAL; 1340 } else if (newchan->ch_id >= VMBUS_CHAN_MAX) { 1341 device_printf(sc->vmbus_dev, "invalid chan%u offer\n", 1342 newchan->ch_id); 1343 return EINVAL; 1344 } 1345 1346 mtx_lock(&sc->vmbus_prichan_lock); 1347 TAILQ_FOREACH(prichan, &sc->vmbus_prichans, ch_prilink) { 1348 /* 1349 * Sub-channel will have the same type GUID and instance 1350 * GUID as its primary channel. 1351 */ 1352 if (memcmp(&prichan->ch_guid_type, &newchan->ch_guid_type, 1353 sizeof(struct hyperv_guid)) == 0 && 1354 memcmp(&prichan->ch_guid_inst, &newchan->ch_guid_inst, 1355 sizeof(struct hyperv_guid)) == 0) 1356 break; 1357 } 1358 if (VMBUS_CHAN_ISPRIMARY(newchan)) { 1359 if (prichan == NULL) { 1360 /* Install the new primary channel */ 1361 vmbus_chan_ins_prilist(sc, newchan); 1362 mtx_unlock(&sc->vmbus_prichan_lock); 1363 goto done; 1364 } else { 1365 mtx_unlock(&sc->vmbus_prichan_lock); 1366 device_printf(sc->vmbus_dev, 1367 "duplicated primary chan%u\n", newchan->ch_id); 1368 return EINVAL; 1369 } 1370 } else { /* Sub-channel */ 1371 if (prichan == NULL) { 1372 mtx_unlock(&sc->vmbus_prichan_lock); 1373 device_printf(sc->vmbus_dev, 1374 "no primary chan for chan%u\n", newchan->ch_id); 1375 return EINVAL; 1376 } 1377 /* 1378 * Found the primary channel for this sub-channel and 1379 * move on. 1380 * 1381 * XXX refcnt prichan 1382 */ 1383 } 1384 mtx_unlock(&sc->vmbus_prichan_lock); 1385 1386 /* 1387 * This is a sub-channel; link it with the primary channel. 1388 */ 1389 KASSERT(!VMBUS_CHAN_ISPRIMARY(newchan), 1390 ("new channel is not sub-channel")); 1391 KASSERT(prichan != NULL, ("no primary channel")); 1392 1393 /* 1394 * Reference count this sub-channel; it will be dereferenced 1395 * when this sub-channel is closed. 1396 */ 1397 KASSERT(newchan->ch_refs == 1, ("chan%u: invalid refcnt %d", 1398 newchan->ch_id, newchan->ch_refs)); 1399 atomic_add_int(&newchan->ch_refs, 1); 1400 1401 newchan->ch_prichan = prichan; 1402 newchan->ch_dev = prichan->ch_dev; 1403 1404 mtx_lock(&prichan->ch_subchan_lock); 1405 vmbus_chan_ins_sublist(prichan, newchan); 1406 mtx_unlock(&prichan->ch_subchan_lock); 1407 /* 1408 * Notify anyone that is interested in this sub-channel, 1409 * after this sub-channel is setup. 1410 */ 1411 wakeup(prichan); 1412done: 1413 /* 1414 * Hook this channel up for later revocation. 1415 */ 1416 mtx_lock(&sc->vmbus_chan_lock); 1417 vmbus_chan_ins_list(sc, newchan); 1418 mtx_unlock(&sc->vmbus_chan_lock); 1419 1420 if (bootverbose) { 1421 vmbus_chan_printf(newchan, "chan%u subidx%u offer\n", 1422 newchan->ch_id, newchan->ch_subidx); 1423 } 1424 1425 /* Select default cpu for this channel. */ 1426 vmbus_chan_cpu_default(newchan); 1427 1428 return 0; 1429} 1430 1431void 1432vmbus_chan_cpu_set(struct vmbus_channel *chan, int cpu) 1433{ 1434 KASSERT(cpu >= 0 && cpu < mp_ncpus, ("invalid cpu %d", cpu)); 1435 1436 if (chan->ch_vmbus->vmbus_version == VMBUS_VERSION_WS2008 || 1437 chan->ch_vmbus->vmbus_version == VMBUS_VERSION_WIN7) { 1438 /* Only cpu0 is supported */ 1439 cpu = 0; 1440 } 1441 1442 chan->ch_cpuid = cpu; 1443 chan->ch_vcpuid = VMBUS_PCPU_GET(chan->ch_vmbus, vcpuid, cpu); 1444 1445 if (bootverbose) { 1446 vmbus_chan_printf(chan, 1447 "chan%u assigned to cpu%u [vcpu%u]\n", 1448 chan->ch_id, chan->ch_cpuid, chan->ch_vcpuid); 1449 } 1450} 1451 1452void 1453vmbus_chan_cpu_rr(struct vmbus_channel *chan) 1454{ 1455 static uint32_t vmbus_chan_nextcpu; 1456 int cpu; 1457 1458 cpu = atomic_fetchadd_int(&vmbus_chan_nextcpu, 1) % mp_ncpus; 1459 vmbus_chan_cpu_set(chan, cpu); 1460} 1461 1462static void 1463vmbus_chan_cpu_default(struct vmbus_channel *chan) 1464{ 1465 /* 1466 * By default, pin the channel to cpu0. Devices having 1467 * special channel-cpu mapping requirement should call 1468 * vmbus_chan_cpu_{set,rr}(). 1469 */ 1470 vmbus_chan_cpu_set(chan, 0); 1471} 1472 1473static void 1474vmbus_chan_msgproc_choffer(struct vmbus_softc *sc, 1475 const struct vmbus_message *msg) 1476{ 1477 const struct vmbus_chanmsg_choffer *offer; 1478 struct vmbus_channel *chan; 1479 task_fn_t *detach_fn, *attach_fn; 1480 int error; 1481 1482 offer = (const struct vmbus_chanmsg_choffer *)msg->msg_data; 1483 1484 chan = vmbus_chan_alloc(sc); 1485 if (chan == NULL) { 1486 device_printf(sc->vmbus_dev, "allocate chan%u failed\n", 1487 offer->chm_chanid); 1488 return; 1489 } 1490 1491 chan->ch_id = offer->chm_chanid; 1492 chan->ch_subidx = offer->chm_subidx; 1493 chan->ch_guid_type = offer->chm_chtype; 1494 chan->ch_guid_inst = offer->chm_chinst; 1495 1496 /* Batch reading is on by default */ 1497 chan->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD; 1498 1499 chan->ch_monprm->mp_connid = VMBUS_CONNID_EVENT; 1500 if (sc->vmbus_version != VMBUS_VERSION_WS2008) 1501 chan->ch_monprm->mp_connid = offer->chm_connid; 1502 1503 if (offer->chm_flags1 & VMBUS_CHOFFER_FLAG1_HASMNF) { 1504 int trig_idx; 1505 1506 /* 1507 * Setup MNF stuffs. 1508 */ 1509 chan->ch_txflags |= VMBUS_CHAN_TXF_HASMNF; 1510 1511 trig_idx = offer->chm_montrig / VMBUS_MONTRIG_LEN; 1512 if (trig_idx >= VMBUS_MONTRIGS_MAX) 1513 panic("invalid monitor trigger %u", offer->chm_montrig); 1514 chan->ch_montrig = 1515 &sc->vmbus_mnf2->mnf_trigs[trig_idx].mt_pending; 1516 1517 chan->ch_montrig_mask = 1518 1 << (offer->chm_montrig % VMBUS_MONTRIG_LEN); 1519 } 1520 1521 /* 1522 * Setup event flag. 1523 */ 1524 chan->ch_evtflag = 1525 &sc->vmbus_tx_evtflags[chan->ch_id >> VMBUS_EVTFLAG_SHIFT]; 1526 chan->ch_evtflag_mask = 1UL << (chan->ch_id & VMBUS_EVTFLAG_MASK); 1527 1528 /* 1529 * Setup attach and detach tasks. 1530 */ 1531 if (VMBUS_CHAN_ISPRIMARY(chan)) { 1532 chan->ch_mgmt_tq = sc->vmbus_devtq; 1533 attach_fn = vmbus_prichan_attach_task; 1534 detach_fn = vmbus_prichan_detach_task; 1535 } else { 1536 chan->ch_mgmt_tq = sc->vmbus_subchtq; 1537 attach_fn = vmbus_subchan_attach_task; 1538 detach_fn = vmbus_subchan_detach_task; 1539 } 1540 TASK_INIT(&chan->ch_attach_task, 0, attach_fn, chan); 1541 TASK_INIT(&chan->ch_detach_task, 0, detach_fn, chan); 1542 1543 error = vmbus_chan_add(chan); 1544 if (error) { 1545 device_printf(sc->vmbus_dev, "add chan%u failed: %d\n", 1546 chan->ch_id, error); 1547 atomic_subtract_int(&chan->ch_refs, 1); 1548 vmbus_chan_free(chan); 1549 return; 1550 } 1551 taskqueue_enqueue(chan->ch_mgmt_tq, &chan->ch_attach_task); 1552} 1553 1554static void 1555vmbus_chan_msgproc_chrescind(struct vmbus_softc *sc, 1556 const struct vmbus_message *msg) 1557{ 1558 const struct vmbus_chanmsg_chrescind *note; 1559 struct vmbus_channel *chan; 1560 1561 note = (const struct vmbus_chanmsg_chrescind *)msg->msg_data; 1562 if (note->chm_chanid > VMBUS_CHAN_MAX) { 1563 device_printf(sc->vmbus_dev, "invalid revoked chan%u\n", 1564 note->chm_chanid); 1565 return; 1566 } 1567 1568 /* 1569 * Find and remove the target channel from the channel list. 1570 */ 1571 mtx_lock(&sc->vmbus_chan_lock); 1572 TAILQ_FOREACH(chan, &sc->vmbus_chans, ch_link) { 1573 if (chan->ch_id == note->chm_chanid) 1574 break; 1575 } 1576 if (chan == NULL) { 1577 mtx_unlock(&sc->vmbus_chan_lock); 1578 device_printf(sc->vmbus_dev, "chan%u is not offered\n", 1579 note->chm_chanid); 1580 return; 1581 } 1582 vmbus_chan_rem_list(sc, chan); 1583 mtx_unlock(&sc->vmbus_chan_lock); 1584 1585 if (VMBUS_CHAN_ISPRIMARY(chan)) { 1586 /* 1587 * The target channel is a primary channel; remove the 1588 * target channel from the primary channel list now, 1589 * instead of later, so that it will not be found by 1590 * other sub-channel offers, which are processed in 1591 * this thread. 1592 */ 1593 mtx_lock(&sc->vmbus_prichan_lock); 1594 vmbus_chan_rem_prilist(sc, chan); 1595 mtx_unlock(&sc->vmbus_prichan_lock); 1596 } 1597 1598 /* 1599 * NOTE: 1600 * The following processing order is critical: 1601 * Set the REVOKED state flag before orphaning the installed xact. 1602 */ 1603 1604 if (atomic_testandset_int(&chan->ch_stflags, 1605 VMBUS_CHAN_ST_REVOKED_SHIFT)) 1606 panic("channel has already been revoked"); 1607 1608 sx_xlock(&chan->ch_orphan_lock); 1609 if (chan->ch_orphan_xact != NULL) 1610 vmbus_xact_ctx_orphan(chan->ch_orphan_xact); 1611 sx_xunlock(&chan->ch_orphan_lock); 1612 1613 if (bootverbose) 1614 vmbus_chan_printf(chan, "chan%u revoked\n", note->chm_chanid); 1615 vmbus_chan_detach(chan); 1616} 1617 1618static int 1619vmbus_chan_release(struct vmbus_channel *chan) 1620{ 1621 struct vmbus_softc *sc = chan->ch_vmbus; 1622 struct vmbus_chanmsg_chfree *req; 1623 struct vmbus_msghc *mh; 1624 int error; 1625 1626 mh = vmbus_msghc_get(sc, sizeof(*req)); 1627 if (mh == NULL) { 1628 vmbus_chan_printf(chan, 1629 "can not get msg hypercall for chfree(chan%u)\n", 1630 chan->ch_id); 1631 return (ENXIO); 1632 } 1633 1634 req = vmbus_msghc_dataptr(mh); 1635 req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHFREE; 1636 req->chm_chanid = chan->ch_id; 1637 1638 error = vmbus_msghc_exec_noresult(mh); 1639 vmbus_msghc_put(sc, mh); 1640 1641 if (error) { 1642 vmbus_chan_printf(chan, 1643 "chfree(chan%u) msg hypercall exec failed: %d\n", 1644 chan->ch_id, error); 1645 } else { 1646 if (bootverbose) 1647 vmbus_chan_printf(chan, "chan%u freed\n", chan->ch_id); 1648 } 1649 return (error); 1650} 1651 1652static void 1653vmbus_prichan_detach_task(void *xchan, int pending __unused) 1654{ 1655 struct vmbus_channel *chan = xchan; 1656 1657 KASSERT(VMBUS_CHAN_ISPRIMARY(chan), 1658 ("chan%u is not primary channel", chan->ch_id)); 1659 1660 /* Delete and detach the device associated with this channel. */ 1661 vmbus_delete_child(chan); 1662 1663 /* Release this channel (back to vmbus). */ 1664 vmbus_chan_release(chan); 1665 1666 /* Free this channel's resource. */ 1667 vmbus_chan_free(chan); 1668} 1669 1670static void 1671vmbus_subchan_detach_task(void *xchan, int pending __unused) 1672{ 1673 struct vmbus_channel *chan = xchan; 1674 struct vmbus_channel *pri_chan = chan->ch_prichan; 1675 1676 KASSERT(!VMBUS_CHAN_ISPRIMARY(chan), 1677 ("chan%u is primary channel", chan->ch_id)); 1678 1679 /* Release this channel (back to vmbus). */ 1680 vmbus_chan_release(chan); 1681 1682 /* Unlink from its primary channel's sub-channel list. */ 1683 mtx_lock(&pri_chan->ch_subchan_lock); 1684 vmbus_chan_rem_sublist(pri_chan, chan); 1685 mtx_unlock(&pri_chan->ch_subchan_lock); 1686 /* Notify anyone that is waiting for this sub-channel to vanish. */ 1687 wakeup(pri_chan); 1688 1689 /* Free this channel's resource. */ 1690 vmbus_chan_free(chan); 1691} 1692 1693static void 1694vmbus_prichan_attach_task(void *xchan, int pending __unused) 1695{ 1696 1697 /* 1698 * Add device for this primary channel. 1699 */ 1700 vmbus_add_child(xchan); 1701} 1702 1703static void 1704vmbus_subchan_attach_task(void *xchan __unused, int pending __unused) 1705{ 1706 1707 /* Nothing */ 1708} 1709 1710void 1711vmbus_chan_destroy_all(struct vmbus_softc *sc) 1712{ 1713 1714 /* 1715 * Detach all devices and destroy the corresponding primary 1716 * channels. 1717 */ 1718 for (;;) { 1719 struct vmbus_channel *chan; 1720 1721 mtx_lock(&sc->vmbus_chan_lock); 1722 TAILQ_FOREACH(chan, &sc->vmbus_chans, ch_link) { 1723 if (VMBUS_CHAN_ISPRIMARY(chan)) 1724 break; 1725 } 1726 if (chan == NULL) { 1727 /* No more primary channels; done. */ 1728 mtx_unlock(&sc->vmbus_chan_lock); 1729 break; 1730 } 1731 vmbus_chan_rem_list(sc, chan); 1732 mtx_unlock(&sc->vmbus_chan_lock); 1733 1734 mtx_lock(&sc->vmbus_prichan_lock); 1735 vmbus_chan_rem_prilist(sc, chan); 1736 mtx_unlock(&sc->vmbus_prichan_lock); 1737 1738 taskqueue_enqueue(chan->ch_mgmt_tq, &chan->ch_detach_task); 1739 } 1740} 1741 1742struct vmbus_channel ** 1743vmbus_subchan_get(struct vmbus_channel *pri_chan, int subchan_cnt) 1744{ 1745 struct vmbus_channel **ret, *chan; 1746 int i; 1747 1748 KASSERT(subchan_cnt > 0, ("invalid sub-channel count %d", subchan_cnt)); 1749 1750 ret = malloc(subchan_cnt * sizeof(struct vmbus_channel *), M_TEMP, 1751 M_WAITOK); 1752 1753 mtx_lock(&pri_chan->ch_subchan_lock); 1754 1755 while (pri_chan->ch_subchan_cnt < subchan_cnt) 1756 mtx_sleep(pri_chan, &pri_chan->ch_subchan_lock, 0, "subch", 0); 1757 1758 i = 0; 1759 TAILQ_FOREACH(chan, &pri_chan->ch_subchans, ch_sublink) { 1760 /* TODO: refcnt chan */ 1761 ret[i] = chan; 1762 1763 ++i; 1764 if (i == subchan_cnt) 1765 break; 1766 } 1767 KASSERT(i == subchan_cnt, ("invalid subchan count %d, should be %d", 1768 pri_chan->ch_subchan_cnt, subchan_cnt)); 1769 1770 mtx_unlock(&pri_chan->ch_subchan_lock); 1771 1772 return ret; 1773} 1774 1775void 1776vmbus_subchan_rel(struct vmbus_channel **subchan, int subchan_cnt __unused) 1777{ 1778 1779 free(subchan, M_TEMP); 1780} 1781 1782void 1783vmbus_subchan_drain(struct vmbus_channel *pri_chan) 1784{ 1785 mtx_lock(&pri_chan->ch_subchan_lock); 1786 while (pri_chan->ch_subchan_cnt > 0) 1787 mtx_sleep(pri_chan, &pri_chan->ch_subchan_lock, 0, "dsubch", 0); 1788 mtx_unlock(&pri_chan->ch_subchan_lock); 1789} 1790 1791void 1792vmbus_chan_msgproc(struct vmbus_softc *sc, const struct vmbus_message *msg) 1793{ 1794 vmbus_chanmsg_proc_t msg_proc; 1795 uint32_t msg_type; 1796 1797 msg_type = ((const struct vmbus_chanmsg_hdr *)msg->msg_data)->chm_type; 1798 KASSERT(msg_type < VMBUS_CHANMSG_TYPE_MAX, 1799 ("invalid message type %u", msg_type)); 1800 1801 msg_proc = vmbus_chan_msgprocs[msg_type]; 1802 if (msg_proc != NULL) 1803 msg_proc(sc, msg); 1804} 1805 1806void 1807vmbus_chan_set_readbatch(struct vmbus_channel *chan, bool on) 1808{ 1809 if (!on) 1810 chan->ch_flags &= ~VMBUS_CHAN_FLAG_BATCHREAD; 1811 else 1812 chan->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD; 1813} 1814 1815uint32_t 1816vmbus_chan_id(const struct vmbus_channel *chan) 1817{ 1818 return chan->ch_id; 1819} 1820 1821uint32_t 1822vmbus_chan_subidx(const struct vmbus_channel *chan) 1823{ 1824 return chan->ch_subidx; 1825} 1826 1827bool 1828vmbus_chan_is_primary(const struct vmbus_channel *chan) 1829{ 1830 if (VMBUS_CHAN_ISPRIMARY(chan)) 1831 return true; 1832 else 1833 return false; 1834} 1835 1836const struct hyperv_guid * 1837vmbus_chan_guid_inst(const struct vmbus_channel *chan) 1838{ 1839 return &chan->ch_guid_inst; 1840} 1841 1842int 1843vmbus_chan_prplist_nelem(int br_size, int prpcnt_max, int dlen_max) 1844{ 1845 int elem_size; 1846 1847 elem_size = __offsetof(struct vmbus_chanpkt_prplist, 1848 cp_range[0].gpa_page[prpcnt_max]); 1849 elem_size += dlen_max; 1850 elem_size = VMBUS_CHANPKT_TOTLEN(elem_size); 1851 1852 return (vmbus_br_nelem(br_size, elem_size)); 1853} 1854 1855bool 1856vmbus_chan_tx_empty(const struct vmbus_channel *chan) 1857{ 1858 1859 return (vmbus_txbr_empty(&chan->ch_txbr)); 1860} 1861 1862bool 1863vmbus_chan_rx_empty(const struct vmbus_channel *chan) 1864{ 1865 1866 return (vmbus_rxbr_empty(&chan->ch_rxbr)); 1867} 1868 1869static int 1870vmbus_chan_printf(const struct vmbus_channel *chan, const char *fmt, ...) 1871{ 1872 va_list ap; 1873 device_t dev; 1874 int retval; 1875 1876 if (chan->ch_dev == NULL || !device_is_alive(chan->ch_dev)) 1877 dev = chan->ch_vmbus->vmbus_dev; 1878 else 1879 dev = chan->ch_dev; 1880 1881 retval = device_print_prettyname(dev); 1882 va_start(ap, fmt); 1883 retval += vprintf(fmt, ap); 1884 va_end(ap); 1885 1886 return (retval); 1887} 1888 1889void 1890vmbus_chan_run_task(struct vmbus_channel *chan, struct task *task) 1891{ 1892 1893 taskqueue_enqueue(chan->ch_tq, task); 1894 taskqueue_drain(chan->ch_tq, task); 1895} 1896 1897struct taskqueue * 1898vmbus_chan_mgmt_tq(const struct vmbus_channel *chan) 1899{ 1900 1901 return (chan->ch_mgmt_tq); 1902} 1903 1904bool 1905vmbus_chan_is_revoked(const struct vmbus_channel *chan) 1906{ 1907 1908 if (chan->ch_stflags & VMBUS_CHAN_ST_REVOKED) 1909 return (true); 1910 return (false); 1911} 1912 1913void 1914vmbus_chan_set_orphan(struct vmbus_channel *chan, struct vmbus_xact_ctx *xact) 1915{ 1916 1917 sx_xlock(&chan->ch_orphan_lock); 1918 chan->ch_orphan_xact = xact; 1919 sx_xunlock(&chan->ch_orphan_lock); 1920} 1921 1922void 1923vmbus_chan_unset_orphan(struct vmbus_channel *chan) 1924{ 1925 1926 sx_xlock(&chan->ch_orphan_lock); 1927 chan->ch_orphan_xact = NULL; 1928 sx_xunlock(&chan->ch_orphan_lock); 1929} 1930 1931const void * 1932vmbus_chan_xact_wait(const struct vmbus_channel *chan, 1933 struct vmbus_xact *xact, size_t *resp_len, bool can_sleep) 1934{ 1935 const void *ret; 1936 1937 if (can_sleep) 1938 ret = vmbus_xact_wait(xact, resp_len); 1939 else 1940 ret = vmbus_xact_busywait(xact, resp_len); 1941 if (vmbus_chan_is_revoked(chan)) { 1942 /* 1943 * This xact probably is interrupted, and the 1944 * interruption can race the reply reception, 1945 * so we have to make sure that there are nothing 1946 * left on the RX bufring, i.e. this xact will 1947 * not be touched, once this function returns. 1948 * 1949 * Since the hypervisor will not put more data 1950 * onto the RX bufring once the channel is revoked, 1951 * the following loop will be terminated, once all 1952 * data are drained by the driver's channel 1953 * callback. 1954 */ 1955 while (!vmbus_chan_rx_empty(chan)) { 1956 if (can_sleep) 1957 pause("chxact", 1); 1958 else 1959 DELAY(1000); 1960 } 1961 } 1962 return (ret); 1963} 1964