[BACK]Return to vmbus.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / hyperv

Annotation of src/sys/dev/hyperv/vmbus.c, Revision 1.16

1.16    ! riastrad    1: /*     $NetBSD: vmbus.c,v 1.15 2021/12/23 04:06:51 yamaguchi Exp $     */
1.1       nonaka      2: /*     $OpenBSD: hyperv.c,v 1.43 2017/06/27 13:56:15 mikeb Exp $       */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2009-2012 Microsoft Corp.
                      6:  * Copyright (c) 2012 NetApp Inc.
                      7:  * Copyright (c) 2012 Citrix Inc.
                      8:  * Copyright (c) 2016 Mike Belopuhov <mike@esdenera.com>
                      9:  * All rights reserved.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice unmodified, this list of conditions, and the following
                     16:  *    disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: /*
                     34:  * The OpenBSD port was done under funding by Esdenera Networks GmbH.
                     35:  */
                     36:
                     37: #include <sys/cdefs.h>
1.16    ! riastrad   38: __KERNEL_RCSID(0, "$NetBSD: vmbus.c,v 1.15 2021/12/23 04:06:51 yamaguchi Exp $");
1.1       nonaka     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/device.h>
                     43: #include <sys/atomic.h>
                     44: #include <sys/bitops.h>
                     45: #include <sys/bus.h>
                     46: #include <sys/cpu.h>
                     47: #include <sys/intr.h>
                     48: #include <sys/kmem.h>
1.8       nonaka     49: #include <sys/kthread.h>
1.1       nonaka     50: #include <sys/module.h>
                     51: #include <sys/mutex.h>
                     52: #include <sys/xcall.h>
                     53:
                     54: #include <uvm/uvm_extern.h>
                     55:
                     56: #include <dev/hyperv/vmbusvar.h>
                     57:
                     58: #define VMBUS_GPADL_START              0xffff /* 0x10000 effectively */
                     59:
                     60: /* Command submission flags */
                     61: #define HCF_SLEEPOK    0x0000
                     62: #define HCF_NOSLEEP    0x0002  /* M_NOWAIT */
                     63: #define HCF_NOREPLY    0x0004
                     64:
                     65: static void    vmbus_attach_deferred(device_t);
1.8       nonaka     66: static int     vmbus_attach_print(void *, const char *);
1.1       nonaka     67: static int     vmbus_alloc_dma(struct vmbus_softc *);
                     68: static void    vmbus_free_dma(struct vmbus_softc *);
                     69: static int     vmbus_init_interrupts(struct vmbus_softc *);
                     70: static void    vmbus_deinit_interrupts(struct vmbus_softc *);
1.15      yamaguch   71: static void    vmbus_init_interrupts_pcpu(void *, void *);
                     72: static void    vmbus_deinit_interrupts_pcpu(void *, void *);
1.1       nonaka     73:
                     74: static int     vmbus_connect(struct vmbus_softc *);
                     75: static int     vmbus_cmd(struct vmbus_softc *, void *, size_t, void *, size_t,
                     76:                    int);
                     77: static int     vmbus_start(struct vmbus_softc *, struct vmbus_msg *, paddr_t);
                     78: static int     vmbus_reply(struct vmbus_softc *, struct vmbus_msg *);
                     79: static uint16_t vmbus_intr_signal(struct vmbus_softc *, paddr_t);
                     80: static void    vmbus_event_proc(void *, struct cpu_info *);
                     81: static void    vmbus_event_proc_compat(void *, struct cpu_info *);
                     82: static void    vmbus_message_proc(void *, struct cpu_info *);
                     83: static void    vmbus_message_softintr(void *);
                     84: static void    vmbus_channel_response(struct vmbus_softc *,
                     85:                    struct vmbus_chanmsg_hdr *);
                     86: static void    vmbus_channel_offer(struct vmbus_softc *,
                     87:                    struct vmbus_chanmsg_hdr *);
                     88: static void    vmbus_channel_rescind(struct vmbus_softc *,
                     89:                    struct vmbus_chanmsg_hdr *);
                     90: static void    vmbus_channel_delivered(struct vmbus_softc *,
                     91:                    struct vmbus_chanmsg_hdr *);
                     92: static int     vmbus_channel_scan(struct vmbus_softc *);
                     93: static void    vmbus_channel_cpu_default(struct vmbus_channel *);
1.8       nonaka     94: static void    vmbus_process_offer(struct vmbus_softc *,
                     95:                    struct vmbus_chanmsg_choffer *);
                     96: static void    vmbus_process_rescind(struct vmbus_softc *,
                     97:                    struct vmbus_chanmsg_chrescind *);
1.1       nonaka     98: static struct vmbus_channel *
                     99:                vmbus_channel_lookup(struct vmbus_softc *, uint32_t);
                    100: static int     vmbus_channel_ring_create(struct vmbus_channel *, uint32_t);
                    101: static void    vmbus_channel_ring_destroy(struct vmbus_channel *);
1.8       nonaka    102: static void    vmbus_channel_detach(struct vmbus_channel *);
1.1       nonaka    103: static void    vmbus_channel_pause(struct vmbus_channel *);
                    104: static uint32_t        vmbus_channel_unpause(struct vmbus_channel *);
                    105: static uint32_t        vmbus_channel_ready(struct vmbus_channel *);
1.11      nonaka    106: static void    vmbus_chevq_enqueue(struct vmbus_softc *, int, void *);
                    107: static void    vmbus_process_chevq(void *);
                    108: static void    vmbus_chevq_thread(void *);
1.8       nonaka    109: static void    vmbus_devq_enqueue(struct vmbus_softc *, int,
                    110:                    struct vmbus_channel *);
                    111: static void    vmbus_process_devq(void *);
                    112: static void    vmbus_devq_thread(void *);
1.11      nonaka    113: static void    vmbus_subchannel_devq_thread(void *);
1.1       nonaka    114:
                    115: static struct vmbus_softc *vmbus_sc;
                    116:
                    117: static const struct {
                    118:        int     hmd_response;
                    119:        int     hmd_request;
                    120:        void    (*hmd_handler)(struct vmbus_softc *,
                    121:                    struct vmbus_chanmsg_hdr *);
                    122: } vmbus_msg_dispatch[] = {
                    123:        { 0,                                    0, NULL },
                    124:        { VMBUS_CHANMSG_CHOFFER,                0, vmbus_channel_offer },
                    125:        { VMBUS_CHANMSG_CHRESCIND,              0, vmbus_channel_rescind },
                    126:        { VMBUS_CHANMSG_CHREQUEST,              VMBUS_CHANMSG_CHOFFER, NULL },
                    127:        { VMBUS_CHANMSG_CHOFFER_DONE,           0, vmbus_channel_delivered },
                    128:        { VMBUS_CHANMSG_CHOPEN,                 0, NULL },
                    129:        { VMBUS_CHANMSG_CHOPEN_RESP,            VMBUS_CHANMSG_CHOPEN,
                    130:          vmbus_channel_response },
                    131:        { VMBUS_CHANMSG_CHCLOSE,                0, NULL },
                    132:        { VMBUS_CHANMSG_GPADL_CONN,             0, NULL },
                    133:        { VMBUS_CHANMSG_GPADL_SUBCONN,          0, NULL },
                    134:        { VMBUS_CHANMSG_GPADL_CONNRESP,         VMBUS_CHANMSG_GPADL_CONN,
                    135:          vmbus_channel_response },
                    136:        { VMBUS_CHANMSG_GPADL_DISCONN,          0, NULL },
                    137:        { VMBUS_CHANMSG_GPADL_DISCONNRESP,      VMBUS_CHANMSG_GPADL_DISCONN,
                    138:          vmbus_channel_response },
                    139:        { VMBUS_CHANMSG_CHFREE,                 0, NULL },
                    140:        { VMBUS_CHANMSG_CONNECT,                0, NULL },
                    141:        { VMBUS_CHANMSG_CONNECT_RESP,           VMBUS_CHANMSG_CONNECT,
                    142:          vmbus_channel_response },
                    143:        { VMBUS_CHANMSG_DISCONNECT,             0, NULL },
                    144: };
                    145:
                    146: const struct hyperv_guid hyperv_guid_network = {
                    147:        { 0x63, 0x51, 0x61, 0xf8, 0x3e, 0xdf, 0xc5, 0x46,
                    148:          0x91, 0x3f, 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e }
                    149: };
                    150:
                    151: const struct hyperv_guid hyperv_guid_ide = {
                    152:        { 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
                    153:          0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 }
                    154: };
                    155:
                    156: const struct hyperv_guid hyperv_guid_scsi = {
                    157:        { 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
                    158:          0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f }
                    159: };
                    160:
                    161: const struct hyperv_guid hyperv_guid_shutdown = {
                    162:        { 0x31, 0x60, 0x0b, 0x0e, 0x13, 0x52, 0x34, 0x49,
                    163:          0x81, 0x8b, 0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb }
                    164: };
                    165:
                    166: const struct hyperv_guid hyperv_guid_timesync = {
                    167:        { 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
                    168:          0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf }
                    169: };
                    170:
                    171: const struct hyperv_guid hyperv_guid_heartbeat = {
                    172:        { 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
                    173:          0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d }
                    174: };
                    175:
                    176: const struct hyperv_guid hyperv_guid_kvp = {
                    177:        { 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
                    178:          0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x03, 0xe6 }
                    179: };
                    180:
                    181: const struct hyperv_guid hyperv_guid_vss = {
                    182:        { 0x29, 0x2e, 0xfa, 0x35, 0x23, 0xea, 0x36, 0x42,
                    183:          0x96, 0xae, 0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40 }
                    184: };
                    185:
                    186: const struct hyperv_guid hyperv_guid_dynmem = {
                    187:        { 0xdc, 0x74, 0x50, 0x52, 0x85, 0x89, 0xe2, 0x46,
                    188:          0x80, 0x57, 0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02 }
                    189: };
                    190:
                    191: const struct hyperv_guid hyperv_guid_mouse = {
                    192:        { 0x9e, 0xb6, 0xa8, 0xcf, 0x4a, 0x5b, 0xc0, 0x4c,
                    193:          0xb9, 0x8b, 0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a }
                    194: };
                    195:
                    196: const struct hyperv_guid hyperv_guid_kbd = {
                    197:        { 0x6d, 0xad, 0x12, 0xf9, 0x17, 0x2b, 0xea, 0x48,
                    198:          0xbd, 0x65, 0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84 }
                    199: };
                    200:
                    201: const struct hyperv_guid hyperv_guid_video = {
                    202:        { 0x02, 0x78, 0x0a, 0xda, 0x77, 0xe3, 0xac, 0x4a,
                    203:          0x8e, 0x77, 0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8 }
                    204: };
                    205:
                    206: const struct hyperv_guid hyperv_guid_fc = {
                    207:        { 0x4a, 0xcc, 0x9b, 0x2f, 0x69, 0x00, 0xf3, 0x4a,
                    208:          0xb7, 0x6b, 0x6f, 0xd0, 0xbe, 0x52, 0x8c, 0xda }
                    209: };
                    210:
                    211: const struct hyperv_guid hyperv_guid_fcopy = {
                    212:        { 0xe3, 0x4b, 0xd1, 0x34, 0xe4, 0xde, 0xc8, 0x41,
                    213:          0x9a, 0xe7, 0x6b, 0x17, 0x49, 0x77, 0xc1, 0x92 }
                    214: };
                    215:
                    216: const struct hyperv_guid hyperv_guid_pcie = {
                    217:        { 0x1d, 0xf6, 0xc4, 0x44, 0x44, 0x44, 0x00, 0x44,
                    218:          0x9d, 0x52, 0x80, 0x2e, 0x27, 0xed, 0xe1, 0x9f }
                    219: };
                    220:
                    221: const struct hyperv_guid hyperv_guid_netdir = {
                    222:        { 0x3d, 0xaf, 0x2e, 0x8c, 0xa7, 0x32, 0x09, 0x4b,
                    223:          0xab, 0x99, 0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01 }
                    224: };
                    225:
                    226: const struct hyperv_guid hyperv_guid_rdesktop = {
                    227:        { 0xf4, 0xac, 0x6a, 0x27, 0x15, 0xac, 0x6c, 0x42,
                    228:          0x98, 0xdd, 0x75, 0x21, 0xad, 0x3f, 0x01, 0xfe }
                    229: };
                    230:
                    231: /* Automatic Virtual Machine Activation (AVMA) Services */
                    232: const struct hyperv_guid hyperv_guid_avma1 = {
                    233:        { 0x55, 0xb2, 0x87, 0x44, 0x8c, 0xb8, 0x3f, 0x40,
                    234:          0xbb, 0x51, 0xd1, 0xf6, 0x9c, 0xf1, 0x7f, 0x87 }
                    235: };
                    236:
                    237: const struct hyperv_guid hyperv_guid_avma2 = {
                    238:        { 0xf4, 0xba, 0x75, 0x33, 0x15, 0x9e, 0x30, 0x4b,
                    239:          0xb7, 0x65, 0x67, 0xac, 0xb1, 0x0d, 0x60, 0x7b }
                    240: };
                    241:
                    242: const struct hyperv_guid hyperv_guid_avma3 = {
                    243:        { 0xa0, 0x1f, 0x22, 0x99, 0xad, 0x24, 0xe2, 0x11,
                    244:          0xbe, 0x98, 0x00, 0x1a, 0xa0, 0x1b, 0xbf, 0x6e }
                    245: };
                    246:
                    247: const struct hyperv_guid hyperv_guid_avma4 = {
                    248:        { 0x16, 0x57, 0xe6, 0xf8, 0xb3, 0x3c, 0x06, 0x4a,
                    249:          0x9a, 0x60, 0x18, 0x89, 0xc5, 0xcc, 0xca, 0xb5 }
                    250: };
                    251:
                    252: int
                    253: vmbus_match(device_t parent, cfdata_t cf, void *aux)
                    254: {
                    255:
                    256:        if (cf->cf_unit != 0 ||
                    257:            !hyperv_hypercall_enabled() ||
                    258:            !hyperv_synic_supported())
                    259:                return 0;
                    260:
                    261:        return 1;
                    262: }
                    263:
                    264: int
                    265: vmbus_attach(struct vmbus_softc *sc)
                    266: {
                    267:
                    268:        aprint_naive("\n");
                    269:        aprint_normal(": Hyper-V VMBus\n");
                    270:
                    271:        vmbus_sc = sc;
                    272:
                    273:        sc->sc_msgpool = pool_cache_init(sizeof(struct vmbus_msg), 8, 0, 0,
                    274:            "hvmsg", NULL, IPL_NET, NULL, NULL, NULL);
                    275:        hyperv_set_message_proc(vmbus_message_proc, sc);
                    276:
                    277:        if (vmbus_alloc_dma(sc))
                    278:                goto cleanup;
                    279:
                    280:        if (vmbus_init_interrupts(sc))
                    281:                goto cleanup;
                    282:
                    283:        if (vmbus_connect(sc))
                    284:                goto cleanup;
                    285:
                    286:        aprint_normal_dev(sc->sc_dev, "protocol %d.%d\n",
                    287:            VMBUS_VERSION_MAJOR(sc->sc_proto),
                    288:            VMBUS_VERSION_MINOR(sc->sc_proto));
                    289:
                    290:        if (sc->sc_proto == VMBUS_VERSION_WS2008 ||
                    291:            sc->sc_proto == VMBUS_VERSION_WIN7) {
                    292:                hyperv_set_event_proc(vmbus_event_proc_compat, sc);
                    293:                sc->sc_channel_max = VMBUS_CHAN_MAX_COMPAT;
                    294:        } else {
                    295:                hyperv_set_event_proc(vmbus_event_proc, sc);
                    296:                sc->sc_channel_max = VMBUS_CHAN_MAX;
                    297:        }
                    298:
                    299:        if (vmbus_channel_scan(sc))
                    300:                goto cleanup;
                    301:
                    302:        config_interrupts(sc->sc_dev, vmbus_attach_deferred);
                    303:
                    304:        return 0;
                    305:
                    306: cleanup:
                    307:        vmbus_deinit_interrupts(sc);
                    308:        vmbus_free_dma(sc);
                    309:        return -1;
                    310: }
                    311:
                    312: static void
                    313: vmbus_attach_deferred(device_t self)
                    314: {
                    315:        struct vmbus_softc *sc = device_private(self);
1.15      yamaguch  316:        uint64_t xc;
1.1       nonaka    317:
1.15      yamaguch  318:        xc = xc_broadcast(0, vmbus_init_interrupts_pcpu,
                    319:            sc, NULL);
                    320:        xc_wait(xc);
1.1       nonaka    321: }
                    322:
                    323: int
                    324: vmbus_detach(struct vmbus_softc *sc, int flags)
                    325: {
                    326:
                    327:        vmbus_deinit_interrupts(sc);
                    328:        vmbus_free_dma(sc);
                    329:
                    330:        return 0;
                    331: }
                    332:
                    333: static int
                    334: vmbus_alloc_dma(struct vmbus_softc *sc)
                    335: {
                    336:        CPU_INFO_ITERATOR cii;
                    337:        struct cpu_info *ci;
                    338:        struct vmbus_percpu_data *pd;
                    339:        int i;
                    340:
                    341:        /*
                    342:         * Per-CPU messages and event flags.
                    343:         */
                    344:        for (CPU_INFO_FOREACH(cii, ci)) {
                    345:                pd = &sc->sc_percpu[cpu_index(ci)];
                    346:
                    347:                pd->simp = hyperv_dma_alloc(sc->sc_dmat, &pd->simp_dma,
1.8       nonaka    348:                    PAGE_SIZE, PAGE_SIZE, 0, 1, HYPERV_DMA_SLEEPOK);
1.1       nonaka    349:                if (pd->simp == NULL)
                    350:                        return ENOMEM;
                    351:
                    352:                pd->siep = hyperv_dma_alloc(sc->sc_dmat, &pd->siep_dma,
1.8       nonaka    353:                    PAGE_SIZE, PAGE_SIZE, 0, 1, HYPERV_DMA_SLEEPOK);
1.1       nonaka    354:                if (pd->siep == NULL)
                    355:                        return ENOMEM;
                    356:        }
                    357:
                    358:        sc->sc_events = hyperv_dma_alloc(sc->sc_dmat, &sc->sc_events_dma,
1.8       nonaka    359:            PAGE_SIZE, PAGE_SIZE, 0, 1, HYPERV_DMA_SLEEPOK);
1.1       nonaka    360:        if (sc->sc_events == NULL)
                    361:                return ENOMEM;
                    362:        sc->sc_wevents = (u_long *)sc->sc_events;
                    363:        sc->sc_revents = (u_long *)((uint8_t *)sc->sc_events + (PAGE_SIZE / 2));
                    364:
                    365:        for (i = 0; i < __arraycount(sc->sc_monitor); i++) {
                    366:                sc->sc_monitor[i] = hyperv_dma_alloc(sc->sc_dmat,
1.8       nonaka    367:                    &sc->sc_monitor_dma[i], PAGE_SIZE, PAGE_SIZE, 0, 1,
                    368:                    HYPERV_DMA_SLEEPOK);
1.1       nonaka    369:                if (sc->sc_monitor[i] == NULL)
                    370:                        return ENOMEM;
                    371:        }
                    372:
                    373:        return 0;
                    374: }
                    375:
                    376: static void
                    377: vmbus_free_dma(struct vmbus_softc *sc)
                    378: {
                    379:        CPU_INFO_ITERATOR cii;
                    380:        struct cpu_info *ci;
                    381:        int i;
                    382:
                    383:        if (sc->sc_events != NULL) {
                    384:                sc->sc_events = sc->sc_wevents = sc->sc_revents = NULL;
                    385:                hyperv_dma_free(sc->sc_dmat, &sc->sc_events_dma);
                    386:        }
                    387:
                    388:        for (i = 0; i < __arraycount(sc->sc_monitor); i++) {
                    389:                sc->sc_monitor[i] = NULL;
                    390:                hyperv_dma_free(sc->sc_dmat, &sc->sc_monitor_dma[i]);
                    391:        }
                    392:
                    393:        for (CPU_INFO_FOREACH(cii, ci)) {
                    394:                struct vmbus_percpu_data *pd = &sc->sc_percpu[cpu_index(ci)];
                    395:
                    396:                if (pd->simp != NULL) {
                    397:                        pd->simp = NULL;
                    398:                        hyperv_dma_free(sc->sc_dmat, &pd->simp_dma);
                    399:                }
                    400:                if (pd->siep != NULL) {
                    401:                        pd->siep = NULL;
                    402:                        hyperv_dma_free(sc->sc_dmat, &pd->siep_dma);
                    403:                }
                    404:        }
                    405: }
                    406:
                    407: static int
                    408: vmbus_init_interrupts(struct vmbus_softc *sc)
                    409: {
1.15      yamaguch  410:        uint64_t xc;
1.1       nonaka    411:
                    412:        TAILQ_INIT(&sc->sc_reqs);
                    413:        mutex_init(&sc->sc_req_lock, MUTEX_DEFAULT, IPL_NET);
                    414:
                    415:        TAILQ_INIT(&sc->sc_rsps);
                    416:        mutex_init(&sc->sc_rsp_lock, MUTEX_DEFAULT, IPL_NET);
                    417:
                    418:        sc->sc_proto = VMBUS_VERSION_WS2008;
                    419:
                    420:        /* XXX event_tq */
                    421:
                    422:        sc->sc_msg_sih = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE,
                    423:            vmbus_message_softintr, sc);
                    424:        if (sc->sc_msg_sih == NULL)
                    425:                return -1;
                    426:
                    427:        kcpuset_create(&sc->sc_intr_cpuset, true);
                    428:        if (cold) {
                    429:                /* Initialize other CPUs later. */
1.15      yamaguch  430:                vmbus_init_interrupts_pcpu(sc, NULL);
                    431:        } else {
                    432:                xc = xc_broadcast(0, vmbus_init_interrupts_pcpu,
                    433:                    sc, NULL);
                    434:                xc_wait(xc);
                    435:        }
1.1       nonaka    436:        atomic_or_32(&sc->sc_flags, VMBUS_SCFLAG_SYNIC);
                    437:
                    438:        return 0;
                    439: }
                    440:
                    441: static void
                    442: vmbus_deinit_interrupts(struct vmbus_softc *sc)
                    443: {
1.15      yamaguch  444:        uint64_t xc;
1.1       nonaka    445:
1.15      yamaguch  446:        if (cold) {
                    447:                vmbus_deinit_interrupts_pcpu(sc, NULL);
                    448:        } else {
                    449:                xc = xc_broadcast(0, vmbus_deinit_interrupts_pcpu,
                    450:                    sc, NULL);
                    451:                xc_wait(xc);
1.1       nonaka    452:        }
1.15      yamaguch  453:        atomic_and_32(&sc->sc_flags, (uint32_t)~VMBUS_SCFLAG_SYNIC);
1.1       nonaka    454:
                    455:        /* XXX event_tq */
                    456:
                    457:        if (sc->sc_msg_sih != NULL) {
                    458:                softint_disestablish(sc->sc_msg_sih);
                    459:                sc->sc_msg_sih = NULL;
                    460:        }
                    461: }
                    462:
                    463: static void
1.15      yamaguch  464: vmbus_init_interrupts_pcpu(void *arg1, void *arg2 __unused)
1.1       nonaka    465: {
                    466:        struct vmbus_softc *sc = arg1;
                    467:        cpuid_t cpu;
                    468:        int s;
                    469:
                    470:        s = splhigh();
                    471:
                    472:        cpu = cpu_index(curcpu());
                    473:        if (!kcpuset_isset(sc->sc_intr_cpuset, cpu)) {
                    474:                kcpuset_atomic_set(sc->sc_intr_cpuset, cpu);
1.15      yamaguch  475:                vmbus_init_interrupts_md(sc, cpu);
1.1       nonaka    476:                vmbus_init_synic_md(sc, cpu);
                    477:        }
                    478:
                    479:        splx(s);
                    480: }
                    481:
                    482: static void
1.15      yamaguch  483: vmbus_deinit_interrupts_pcpu(void *arg1, void *arg2 __unused)
1.1       nonaka    484: {
                    485:        struct vmbus_softc *sc = arg1;
                    486:        cpuid_t cpu;
                    487:        int s;
                    488:
                    489:        s = splhigh();
                    490:
                    491:        cpu = cpu_index(curcpu());
                    492:        if (kcpuset_isset(sc->sc_intr_cpuset, cpu)) {
1.15      yamaguch  493:                if (ISSET(sc->sc_flags, VMBUS_SCFLAG_SYNIC))
                    494:                        vmbus_deinit_synic_md(sc, cpu);
                    495:                vmbus_deinit_interrupts_md(sc, cpu);
1.1       nonaka    496:                kcpuset_atomic_clear(sc->sc_intr_cpuset, cpu);
                    497:        }
                    498:
                    499:        splx(s);
                    500: }
                    501:
                    502: static int
                    503: vmbus_connect(struct vmbus_softc *sc)
                    504: {
                    505:        static const uint32_t versions[] = {
                    506:                VMBUS_VERSION_WIN8_1,
                    507:                VMBUS_VERSION_WIN8,
                    508:                VMBUS_VERSION_WIN7,
                    509:                VMBUS_VERSION_WS2008
                    510:        };
                    511:        struct vmbus_chanmsg_connect cmd;
                    512:        struct vmbus_chanmsg_connect_resp rsp;
                    513:        int i, rv;
                    514:
                    515:        memset(&cmd, 0, sizeof(cmd));
                    516:        cmd.chm_hdr.chm_type = VMBUS_CHANMSG_CONNECT;
                    517:        cmd.chm_evtflags = hyperv_dma_get_paddr(&sc->sc_events_dma);
                    518:        cmd.chm_mnf1 = hyperv_dma_get_paddr(&sc->sc_monitor_dma[0]);
                    519:        cmd.chm_mnf2 = hyperv_dma_get_paddr(&sc->sc_monitor_dma[1]);
                    520:
                    521:        memset(&rsp, 0, sizeof(rsp));
                    522:
                    523:        for (i = 0; i < __arraycount(versions); i++) {
                    524:                cmd.chm_ver = versions[i];
                    525:                rv = vmbus_cmd(sc, &cmd, sizeof(cmd), &rsp, sizeof(rsp),
                    526:                    cold ? HCF_NOSLEEP : HCF_SLEEPOK);
                    527:                if (rv) {
                    528:                        DPRINTF("%s: CONNECT failed\n",
                    529:                            device_xname(sc->sc_dev));
                    530:                        return rv;
                    531:                }
                    532:                if (rsp.chm_done) {
                    533:                        atomic_or_32(&sc->sc_flags, VMBUS_SCFLAG_CONNECTED);
                    534:                        sc->sc_proto = versions[i];
                    535:                        sc->sc_handle = VMBUS_GPADL_START;
                    536:                        break;
                    537:                }
                    538:        }
                    539:        if (i == __arraycount(versions)) {
                    540:                device_printf(sc->sc_dev,
                    541:                    "failed to negotiate protocol version\n");
                    542:                return ENXIO;
                    543:        }
                    544:
                    545:        return 0;
                    546: }
                    547:
                    548: static int
                    549: vmbus_cmd(struct vmbus_softc *sc, void *cmd, size_t cmdlen, void *rsp,
                    550:     size_t rsplen, int flags)
                    551: {
                    552:        const int prflags = cold ? PR_NOWAIT : PR_WAITOK;
                    553:        struct vmbus_msg *msg;
                    554:        paddr_t pa;
                    555:        int rv;
                    556:
                    557:        if (cmdlen > VMBUS_MSG_DSIZE_MAX) {
                    558:                device_printf(sc->sc_dev, "payload too large (%zu)\n",
                    559:                    cmdlen);
                    560:                return EMSGSIZE;
                    561:        }
                    562:
                    563:        msg = pool_cache_get_paddr(sc->sc_msgpool, prflags, &pa);
                    564:        if (msg == NULL) {
                    565:                device_printf(sc->sc_dev, "couldn't get msgpool\n");
                    566:                return ENOMEM;
                    567:        }
                    568:        memset(msg, 0, sizeof(*msg));
                    569:        msg->msg_req.hc_dsize = cmdlen;
                    570:        memcpy(msg->msg_req.hc_data, cmd, cmdlen);
                    571:
                    572:        if (!(flags & HCF_NOREPLY)) {
                    573:                msg->msg_rsp = rsp;
                    574:                msg->msg_rsplen = rsplen;
                    575:        } else
                    576:                msg->msg_flags |= MSGF_NOQUEUE;
                    577:
                    578:        if (flags & HCF_NOSLEEP)
                    579:                msg->msg_flags |= MSGF_NOSLEEP;
                    580:
                    581:        rv = vmbus_start(sc, msg, pa);
                    582:        if (rv == 0)
                    583:                rv = vmbus_reply(sc, msg);
                    584:        pool_cache_put_paddr(sc->sc_msgpool, msg, pa);
                    585:        return rv;
                    586: }
                    587:
                    588: static int
                    589: vmbus_start(struct vmbus_softc *sc, struct vmbus_msg *msg, paddr_t msg_pa)
                    590: {
                    591:        static const int delays[] = {
                    592:                100, 100, 100, 500, 500, 5000, 5000, 5000
                    593:        };
                    594:        const char *wchan = "hvstart";
                    595:        uint16_t status;
                    596:        int i, s;
                    597:
                    598:        msg->msg_req.hc_connid = VMBUS_CONNID_MESSAGE;
                    599:        msg->msg_req.hc_msgtype = 1;
                    600:
                    601:        if (!(msg->msg_flags & MSGF_NOQUEUE)) {
                    602:                mutex_enter(&sc->sc_req_lock);
                    603:                TAILQ_INSERT_TAIL(&sc->sc_reqs, msg, msg_entry);
                    604:                mutex_exit(&sc->sc_req_lock);
                    605:        }
                    606:
                    607:        for (i = 0; i < __arraycount(delays); i++) {
                    608:                status = hyperv_hypercall_post_message(
                    609:                    msg_pa + offsetof(struct vmbus_msg, msg_req));
                    610:                if (status == HYPERCALL_STATUS_SUCCESS)
                    611:                        break;
                    612:
                    613:                if (msg->msg_flags & MSGF_NOSLEEP) {
                    614:                        delay(delays[i]);
                    615:                        s = splnet();
                    616:                        hyperv_intr();
                    617:                        splx(s);
                    618:                } else
1.12      nonaka    619:                        tsleep(wchan, PRIBIO, wchan,
                    620:                            uimax(1, mstohz(delays[i] / 1000)));
1.1       nonaka    621:        }
                    622:        if (status != HYPERCALL_STATUS_SUCCESS) {
                    623:                device_printf(sc->sc_dev,
                    624:                    "posting vmbus message failed with %d\n", status);
                    625:                if (!(msg->msg_flags & MSGF_NOQUEUE)) {
                    626:                        mutex_enter(&sc->sc_req_lock);
                    627:                        TAILQ_REMOVE(&sc->sc_reqs, msg, msg_entry);
                    628:                        mutex_exit(&sc->sc_req_lock);
                    629:                }
                    630:                return EIO;
                    631:        }
                    632:
                    633:        return 0;
                    634: }
                    635:
                    636: static int
                    637: vmbus_reply_done(struct vmbus_softc *sc, struct vmbus_msg *msg)
                    638: {
                    639:        struct vmbus_msg *m;
                    640:
                    641:        mutex_enter(&sc->sc_rsp_lock);
                    642:        TAILQ_FOREACH(m, &sc->sc_rsps, msg_entry) {
                    643:                if (m == msg) {
                    644:                        mutex_exit(&sc->sc_rsp_lock);
                    645:                        return 1;
                    646:                }
                    647:        }
                    648:        mutex_exit(&sc->sc_rsp_lock);
                    649:        return 0;
                    650: }
                    651:
                    652: static int
                    653: vmbus_reply(struct vmbus_softc *sc, struct vmbus_msg *msg)
                    654: {
1.10      nonaka    655:        int s;
1.1       nonaka    656:
                    657:        if (msg->msg_flags & MSGF_NOQUEUE)
                    658:                return 0;
                    659:
1.10      nonaka    660:        while (!vmbus_reply_done(sc, msg)) {
1.1       nonaka    661:                if (msg->msg_flags & MSGF_NOSLEEP) {
                    662:                        delay(1000);
                    663:                        s = splnet();
                    664:                        hyperv_intr();
                    665:                        splx(s);
                    666:                } else
1.10      nonaka    667:                        tsleep(msg, PRIBIO, "hvreply", 1);
1.1       nonaka    668:        }
1.10      nonaka    669:
                    670:        mutex_enter(&sc->sc_rsp_lock);
                    671:        TAILQ_REMOVE(&sc->sc_rsps, msg, msg_entry);
                    672:        mutex_exit(&sc->sc_rsp_lock);
                    673:
                    674:        return 0;
1.1       nonaka    675: }
                    676:
                    677: static uint16_t
                    678: vmbus_intr_signal(struct vmbus_softc *sc, paddr_t con_pa)
                    679: {
                    680:        uint64_t status;
                    681:
                    682:        status = hyperv_hypercall_signal_event(con_pa);
                    683:        return (uint16_t)status;
                    684: }
                    685:
                    686: #if LONG_BIT == 64
                    687: #define ffsl(v)        ffs64(v)
                    688: #elif LONG_BIT == 32
                    689: #define ffsl(v)        ffs32(v)
                    690: #else
                    691: #error unsupport LONG_BIT
                    692: #endif /* LONG_BIT */
                    693:
                    694: static void
                    695: vmbus_event_flags_proc(struct vmbus_softc *sc, volatile u_long *revents,
                    696:     int maxrow)
                    697: {
                    698:        struct vmbus_channel *ch;
                    699:        u_long pending;
                    700:        uint32_t chanid, chanid_base;
                    701:        int row, chanid_ofs;
                    702:
                    703:        for (row = 0; row < maxrow; row++) {
                    704:                if (revents[row] == 0)
                    705:                        continue;
                    706:
                    707:                pending = atomic_swap_ulong(&revents[row], 0);
                    708:                chanid_base = row * LONG_BIT;
                    709:
                    710:                while ((chanid_ofs = ffsl(pending)) != 0) {
                    711:                        chanid_ofs--;   /* NOTE: ffs is 1-based */
                    712:                        pending &= ~(1UL << chanid_ofs);
                    713:
                    714:                        chanid = chanid_base + chanid_ofs;
                    715:                        /* vmbus channel protocol message */
                    716:                        if (chanid == 0)
                    717:                                continue;
                    718:
                    719:                        ch = vmbus_channel_lookup(sc, chanid);
                    720:                        if (ch == NULL) {
                    721:                                device_printf(sc->sc_dev,
                    722:                                    "unhandled event on %d\n", chanid);
                    723:                                continue;
                    724:                        }
                    725:                        if (ch->ch_state != VMBUS_CHANSTATE_OPENED) {
                    726:                                device_printf(sc->sc_dev,
                    727:                                    "channel %d is not active\n", chanid);
                    728:                                continue;
                    729:                        }
                    730:                        ch->ch_evcnt.ev_count++;
                    731:                        vmbus_channel_schedule(ch);
                    732:                }
                    733:        }
                    734: }
                    735:
                    736: static void
                    737: vmbus_event_proc(void *arg, struct cpu_info *ci)
                    738: {
                    739:        struct vmbus_softc *sc = arg;
                    740:        struct vmbus_evtflags *evt;
                    741:
                    742:        /*
                    743:         * On Host with Win8 or above, the event page can be
                    744:         * checked directly to get the id of the channel
                    745:         * that has the pending interrupt.
                    746:         */
                    747:        evt = (struct vmbus_evtflags *)sc->sc_percpu[cpu_index(ci)].siep +
                    748:            VMBUS_SINT_MESSAGE;
                    749:
                    750:        vmbus_event_flags_proc(sc, evt->evt_flags,
                    751:            __arraycount(evt->evt_flags));
                    752: }
                    753:
                    754: static void
                    755: vmbus_event_proc_compat(void *arg, struct cpu_info *ci)
                    756: {
                    757:        struct vmbus_softc *sc = arg;
                    758:        struct vmbus_evtflags *evt;
                    759:
                    760:        evt = (struct vmbus_evtflags *)sc->sc_percpu[cpu_index(ci)].siep +
                    761:            VMBUS_SINT_MESSAGE;
                    762:
                    763:        if (test_bit(0, &evt->evt_flags[0])) {
                    764:                clear_bit(0, &evt->evt_flags[0]);
                    765:                /*
                    766:                 * receive size is 1/2 page and divide that by 4 bytes
                    767:                 */
                    768:                vmbus_event_flags_proc(sc, sc->sc_revents,
                    769:                    VMBUS_CHAN_MAX_COMPAT / VMBUS_EVTFLAG_LEN);
                    770:        }
                    771: }
                    772:
                    773: static void
                    774: vmbus_message_proc(void *arg, struct cpu_info *ci)
                    775: {
                    776:        struct vmbus_softc *sc = arg;
                    777:        struct vmbus_message *msg;
                    778:
                    779:        msg = (struct vmbus_message *)sc->sc_percpu[cpu_index(ci)].simp +
                    780:            VMBUS_SINT_MESSAGE;
                    781:        if (__predict_false(msg->msg_type != HYPERV_MSGTYPE_NONE)) {
                    782:                if (__predict_true(!cold))
                    783:                        softint_schedule_cpu(sc->sc_msg_sih, ci);
                    784:                else
                    785:                        vmbus_message_softintr(sc);
                    786:        }
                    787: }
                    788:
                    789: static void
                    790: vmbus_message_softintr(void *arg)
                    791: {
                    792:        struct vmbus_softc *sc = arg;
                    793:        struct vmbus_message *msg;
                    794:        struct vmbus_chanmsg_hdr *hdr;
                    795:        uint32_t type;
                    796:        cpuid_t cpu;
                    797:
                    798:        cpu = cpu_index(curcpu());
                    799:
                    800:        for (;;) {
                    801:                msg = (struct vmbus_message *)sc->sc_percpu[cpu].simp +
                    802:                    VMBUS_SINT_MESSAGE;
                    803:                if (msg->msg_type == HYPERV_MSGTYPE_NONE)
                    804:                        break;
                    805:
                    806:                hdr = (struct vmbus_chanmsg_hdr *)msg->msg_data;
                    807:                type = hdr->chm_type;
                    808:                if (type >= VMBUS_CHANMSG_COUNT) {
                    809:                        device_printf(sc->sc_dev,
                    810:                            "unhandled message type %u flags %#x\n", type,
                    811:                            msg->msg_flags);
                    812:                } else {
                    813:                        if (vmbus_msg_dispatch[type].hmd_handler) {
                    814:                                vmbus_msg_dispatch[type].hmd_handler(sc, hdr);
                    815:                        } else {
                    816:                                device_printf(sc->sc_dev,
                    817:                                    "unhandled message type %u\n", type);
                    818:                        }
                    819:                }
                    820:
                    821:                msg->msg_type = HYPERV_MSGTYPE_NONE;
                    822:                membar_sync();
                    823:                if (msg->msg_flags & VMBUS_MSGFLAG_PENDING)
                    824:                        hyperv_send_eom();
                    825:        }
                    826: }
                    827:
                    828: static void
                    829: vmbus_channel_response(struct vmbus_softc *sc, struct vmbus_chanmsg_hdr *rsphdr)
                    830: {
                    831:        struct vmbus_msg *msg;
                    832:        struct vmbus_chanmsg_hdr *reqhdr;
                    833:        int req;
                    834:
                    835:        req = vmbus_msg_dispatch[rsphdr->chm_type].hmd_request;
                    836:        mutex_enter(&sc->sc_req_lock);
                    837:        TAILQ_FOREACH(msg, &sc->sc_reqs, msg_entry) {
                    838:                reqhdr = (struct vmbus_chanmsg_hdr *)&msg->msg_req.hc_data;
                    839:                if (reqhdr->chm_type == req) {
                    840:                        TAILQ_REMOVE(&sc->sc_reqs, msg, msg_entry);
                    841:                        break;
                    842:                }
                    843:        }
                    844:        mutex_exit(&sc->sc_req_lock);
                    845:        if (msg != NULL) {
                    846:                memcpy(msg->msg_rsp, rsphdr, msg->msg_rsplen);
                    847:                mutex_enter(&sc->sc_rsp_lock);
                    848:                TAILQ_INSERT_TAIL(&sc->sc_rsps, msg, msg_entry);
                    849:                mutex_exit(&sc->sc_rsp_lock);
                    850:                wakeup(msg);
                    851:        }
                    852: }
                    853:
                    854: static void
                    855: vmbus_channel_offer(struct vmbus_softc *sc, struct vmbus_chanmsg_hdr *hdr)
                    856: {
1.11      nonaka    857:        struct vmbus_chanmsg_choffer *co;
1.1       nonaka    858:
1.11      nonaka    859:        co = kmem_intr_alloc(sizeof(*co), KM_NOSLEEP);
                    860:        if (co == NULL) {
                    861:                device_printf(sc->sc_dev,
                    862:                    "failed to allocate an offer object\n");
                    863:                return;
                    864:        }
                    865:
                    866:        memcpy(co, hdr, sizeof(*co));
                    867:        vmbus_chevq_enqueue(sc, VMBUS_CHEV_TYPE_OFFER, co);
1.1       nonaka    868: }
                    869:
                    870: static void
                    871: vmbus_channel_rescind(struct vmbus_softc *sc, struct vmbus_chanmsg_hdr *hdr)
                    872: {
1.11      nonaka    873:        struct vmbus_chanmsg_chrescind *cr;
                    874:
                    875:        cr = kmem_intr_alloc(sizeof(*cr), KM_NOSLEEP);
                    876:        if (cr == NULL) {
                    877:                device_printf(sc->sc_dev,
                    878:                    "failed to allocate an rescind object\n");
                    879:                return;
                    880:        }
1.1       nonaka    881:
1.11      nonaka    882:        memcpy(cr, hdr, sizeof(*cr));
                    883:        vmbus_chevq_enqueue(sc, VMBUS_CHEV_TYPE_RESCIND, cr);
1.1       nonaka    884: }
                    885:
                    886: static void
                    887: vmbus_channel_delivered(struct vmbus_softc *sc, struct vmbus_chanmsg_hdr *hdr)
                    888: {
                    889:
                    890:        atomic_or_32(&sc->sc_flags, VMBUS_SCFLAG_OFFERS_DELIVERED);
1.8       nonaka    891:        wakeup(&sc->sc_devq);
1.1       nonaka    892: }
                    893:
                    894: static void
                    895: hyperv_guid_sprint(struct hyperv_guid *guid, char *str, size_t size)
                    896: {
                    897:        static const struct {
                    898:                const struct hyperv_guid *guid;
                    899:                const char *ident;
                    900:        } map[] = {
                    901:                { &hyperv_guid_network,         "network" },
                    902:                { &hyperv_guid_ide,             "ide" },
                    903:                { &hyperv_guid_scsi,            "scsi" },
                    904:                { &hyperv_guid_shutdown,        "shutdown" },
                    905:                { &hyperv_guid_timesync,        "timesync" },
                    906:                { &hyperv_guid_heartbeat,       "heartbeat" },
                    907:                { &hyperv_guid_kvp,             "kvp" },
                    908:                { &hyperv_guid_vss,             "vss" },
                    909:                { &hyperv_guid_dynmem,          "dynamic-memory" },
                    910:                { &hyperv_guid_mouse,           "mouse" },
                    911:                { &hyperv_guid_kbd,             "keyboard" },
                    912:                { &hyperv_guid_video,           "video" },
                    913:                { &hyperv_guid_fc,              "fiber-channel" },
                    914:                { &hyperv_guid_fcopy,           "file-copy" },
                    915:                { &hyperv_guid_pcie,            "pcie-passthrough" },
                    916:                { &hyperv_guid_netdir,          "network-direct" },
                    917:                { &hyperv_guid_rdesktop,        "remote-desktop" },
                    918:                { &hyperv_guid_avma1,           "avma-1" },
                    919:                { &hyperv_guid_avma2,           "avma-2" },
                    920:                { &hyperv_guid_avma3,           "avma-3" },
                    921:                { &hyperv_guid_avma4,           "avma-4" },
                    922:        };
                    923:        int i;
                    924:
                    925:        for (i = 0; i < __arraycount(map); i++) {
                    926:                if (memcmp(guid, map[i].guid, sizeof(*guid)) == 0) {
                    927:                        strlcpy(str, map[i].ident, size);
                    928:                        return;
                    929:                }
                    930:        }
                    931:        hyperv_guid2str(guid, str, size);
                    932: }
                    933:
                    934: static int
                    935: vmbus_channel_scan(struct vmbus_softc *sc)
                    936: {
                    937:        struct vmbus_chanmsg_hdr hdr;
                    938:        struct vmbus_chanmsg_choffer rsp;
                    939:
1.11      nonaka    940:        TAILQ_INIT(&sc->sc_prichans);
                    941:        mutex_init(&sc->sc_prichan_lock, MUTEX_DEFAULT, IPL_NET);
1.8       nonaka    942:        TAILQ_INIT(&sc->sc_channels);
                    943:        mutex_init(&sc->sc_channel_lock, MUTEX_DEFAULT, IPL_NET);
                    944:
1.11      nonaka    945:        /*
                    946:         * This queue serializes vmbus channel offer and rescind messages.
                    947:         */
                    948:        SIMPLEQ_INIT(&sc->sc_chevq);
                    949:        mutex_init(&sc->sc_chevq_lock, MUTEX_DEFAULT, IPL_NET);
                    950:        cv_init(&sc->sc_chevq_cv, "hvchevcv");
                    951:        if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
                    952:            vmbus_chevq_thread, sc, NULL, "hvchevq") != 0) {
                    953:                DPRINTF("%s: failed to create prich chevq thread\n",
                    954:                    device_xname(sc->sc_dev));
                    955:                return -1;
                    956:        }
                    957:
                    958:        /*
                    959:         * This queue serializes vmbus devices' attach and detach
                    960:         * for channel offer and rescind messages.
                    961:         */
1.8       nonaka    962:        SIMPLEQ_INIT(&sc->sc_devq);
                    963:        mutex_init(&sc->sc_devq_lock, MUTEX_DEFAULT, IPL_NET);
                    964:        cv_init(&sc->sc_devq_cv, "hvdevqcv");
1.11      nonaka    965:        if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
                    966:            vmbus_devq_thread, sc, NULL, "hvdevq") != 0) {
                    967:                DPRINTF("%s: failed to create prich devq thread\n",
                    968:                    device_xname(sc->sc_dev));
                    969:                return -1;
                    970:        }
1.8       nonaka    971:
1.11      nonaka    972:        /*
                    973:         * This queue handles sub-channel detach, so that vmbus
                    974:         * device's detach running in sc_devq can drain its sub-channels.
                    975:         */
                    976:        SIMPLEQ_INIT(&sc->sc_subch_devq);
                    977:        mutex_init(&sc->sc_subch_devq_lock, MUTEX_DEFAULT, IPL_NET);
                    978:        cv_init(&sc->sc_subch_devq_cv, "hvsdvqcv");
1.8       nonaka    979:        if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
1.11      nonaka    980:            vmbus_subchannel_devq_thread, sc, NULL, "hvsdevq") != 0) {
                    981:                DPRINTF("%s: failed to create subch devq thread\n",
1.8       nonaka    982:                    device_xname(sc->sc_dev));
                    983:                return -1;
                    984:        }
1.1       nonaka    985:
                    986:        memset(&hdr, 0, sizeof(hdr));
                    987:        hdr.chm_type = VMBUS_CHANMSG_CHREQUEST;
                    988:
                    989:        if (vmbus_cmd(sc, &hdr, sizeof(hdr), &rsp, sizeof(rsp),
                    990:            HCF_NOREPLY | (cold ? HCF_NOSLEEP : HCF_SLEEPOK))) {
                    991:                DPRINTF("%s: CHREQUEST failed\n", device_xname(sc->sc_dev));
                    992:                return -1;
                    993:        }
                    994:
1.10      nonaka    995:        while (!ISSET(sc->sc_flags, VMBUS_SCFLAG_OFFERS_DELIVERED))
                    996:                tsleep(&sc->sc_devq, PRIBIO, "hvscan", 1);
1.1       nonaka    997:
1.11      nonaka    998:        mutex_enter(&sc->sc_chevq_lock);
                    999:        vmbus_process_chevq(sc);
                   1000:        mutex_exit(&sc->sc_chevq_lock);
1.8       nonaka   1001:        mutex_enter(&sc->sc_devq_lock);
                   1002:        vmbus_process_devq(sc);
                   1003:        mutex_exit(&sc->sc_devq_lock);
1.1       nonaka   1004:
                   1005:        return 0;
                   1006: }
                   1007:
                   1008: static struct vmbus_channel *
                   1009: vmbus_channel_alloc(struct vmbus_softc *sc)
                   1010: {
                   1011:        struct vmbus_channel *ch;
                   1012:
1.11      nonaka   1013:        ch = kmem_zalloc(sizeof(*ch), KM_SLEEP);
1.1       nonaka   1014:
                   1015:        ch->ch_monprm = hyperv_dma_alloc(sc->sc_dmat, &ch->ch_monprm_dma,
1.11      nonaka   1016:            sizeof(*ch->ch_monprm), 8, 0, 1, HYPERV_DMA_SLEEPOK);
1.1       nonaka   1017:        if (ch->ch_monprm == NULL) {
                   1018:                device_printf(sc->sc_dev, "monprm alloc failed\n");
                   1019:                kmem_free(ch, sizeof(*ch));
                   1020:                return NULL;
                   1021:        }
                   1022:
                   1023:        ch->ch_refs = 1;
                   1024:        ch->ch_sc = sc;
                   1025:        mutex_init(&ch->ch_subchannel_lock, MUTEX_DEFAULT, IPL_NET);
                   1026:        TAILQ_INIT(&ch->ch_subchannels);
                   1027:
                   1028:        ch->ch_state = VMBUS_CHANSTATE_CLOSED;
                   1029:
                   1030:        return ch;
                   1031: }
                   1032:
                   1033: static void
                   1034: vmbus_channel_free(struct vmbus_channel *ch)
                   1035: {
                   1036:        struct vmbus_softc *sc = ch->ch_sc;
                   1037:
                   1038:        KASSERTMSG(TAILQ_EMPTY(&ch->ch_subchannels) &&
                   1039:            ch->ch_subchannel_count == 0, "still owns sub-channels");
                   1040:        KASSERTMSG(ch->ch_state == 0 || ch->ch_state == VMBUS_CHANSTATE_CLOSED,
                   1041:            "free busy channel");
                   1042:        KASSERTMSG(ch->ch_refs == 0, "channel %u: invalid refcnt %d",
                   1043:            ch->ch_id, ch->ch_refs);
                   1044:
                   1045:        hyperv_dma_free(sc->sc_dmat, &ch->ch_monprm_dma);
                   1046:        mutex_destroy(&ch->ch_subchannel_lock);
                   1047:        /* XXX ch_evcnt */
1.8       nonaka   1048:        if (ch->ch_taskq != NULL)
                   1049:                softint_disestablish(ch->ch_taskq);
1.1       nonaka   1050:        kmem_free(ch, sizeof(*ch));
                   1051: }
                   1052:
                   1053: static int
                   1054: vmbus_channel_add(struct vmbus_channel *nch)
                   1055: {
                   1056:        struct vmbus_softc *sc = nch->ch_sc;
                   1057:        struct vmbus_channel *ch;
1.2       hannken  1058:        u_int refs __diagused;
1.1       nonaka   1059:
                   1060:        if (nch->ch_id == 0) {
                   1061:                device_printf(sc->sc_dev, "got channel 0 offer, discard\n");
                   1062:                return EINVAL;
                   1063:        } else if (nch->ch_id >= sc->sc_channel_max) {
                   1064:                device_printf(sc->sc_dev, "invalid channel %u offer\n",
                   1065:                    nch->ch_id);
                   1066:                return EINVAL;
                   1067:        }
                   1068:
1.11      nonaka   1069:        mutex_enter(&sc->sc_prichan_lock);
                   1070:        TAILQ_FOREACH(ch, &sc->sc_prichans, ch_prientry) {
1.1       nonaka   1071:                if (!memcmp(&ch->ch_type, &nch->ch_type, sizeof(ch->ch_type)) &&
                   1072:                    !memcmp(&ch->ch_inst, &nch->ch_inst, sizeof(ch->ch_inst)))
                   1073:                        break;
                   1074:        }
                   1075:        if (VMBUS_CHAN_ISPRIMARY(nch)) {
                   1076:                if (ch == NULL) {
1.11      nonaka   1077:                        TAILQ_INSERT_TAIL(&sc->sc_prichans, nch, ch_prientry);
                   1078:                        mutex_exit(&sc->sc_prichan_lock);
1.1       nonaka   1079:                        goto done;
                   1080:                } else {
1.11      nonaka   1081:                        mutex_exit(&sc->sc_prichan_lock);
1.1       nonaka   1082:                        device_printf(sc->sc_dev,
                   1083:                            "duplicated primary channel%u\n", nch->ch_id);
                   1084:                        return EINVAL;
                   1085:                }
                   1086:        } else {
                   1087:                if (ch == NULL) {
1.11      nonaka   1088:                        mutex_exit(&sc->sc_prichan_lock);
1.1       nonaka   1089:                        device_printf(sc->sc_dev, "no primary channel%u\n",
                   1090:                            nch->ch_id);
                   1091:                        return EINVAL;
                   1092:                }
                   1093:        }
1.11      nonaka   1094:        mutex_exit(&sc->sc_prichan_lock);
1.1       nonaka   1095:
                   1096:        KASSERT(!VMBUS_CHAN_ISPRIMARY(nch));
                   1097:        KASSERT(ch != NULL);
                   1098:
1.8       nonaka   1099:        refs = atomic_inc_uint_nv(&nch->ch_refs);
                   1100:        KASSERT(refs == 2);
1.1       nonaka   1101:
                   1102:        nch->ch_primary_channel = ch;
                   1103:        nch->ch_dev = ch->ch_dev;
                   1104:
                   1105:        mutex_enter(&ch->ch_subchannel_lock);
                   1106:        TAILQ_INSERT_TAIL(&ch->ch_subchannels, nch, ch_subentry);
                   1107:        ch->ch_subchannel_count++;
                   1108:        mutex_exit(&ch->ch_subchannel_lock);
                   1109:        wakeup(ch);
                   1110:
                   1111: done:
1.11      nonaka   1112:        mutex_enter(&sc->sc_channel_lock);
                   1113:        TAILQ_INSERT_TAIL(&sc->sc_channels, nch, ch_entry);
                   1114:        mutex_exit(&sc->sc_channel_lock);
                   1115:
1.1       nonaka   1116:        vmbus_channel_cpu_default(nch);
                   1117:
                   1118:        return 0;
                   1119: }
                   1120:
                   1121: void
                   1122: vmbus_channel_cpu_set(struct vmbus_channel *ch, int cpu)
                   1123: {
                   1124:        struct vmbus_softc *sc = ch->ch_sc;
                   1125:
                   1126:        KASSERTMSG(cpu >= 0 && cpu < ncpu, "invalid cpu %d", cpu);
                   1127:
                   1128:        if (sc->sc_proto == VMBUS_VERSION_WS2008 ||
                   1129:            sc->sc_proto == VMBUS_VERSION_WIN7) {
                   1130:                /* Only cpu0 is supported */
                   1131:                cpu = 0;
                   1132:        }
                   1133:
                   1134:        ch->ch_cpuid = cpu;
1.7       nonaka   1135:        ch->ch_vcpu = hyperv_get_vcpuid(cpu);
1.1       nonaka   1136: }
                   1137:
                   1138: void
                   1139: vmbus_channel_cpu_rr(struct vmbus_channel *ch)
                   1140: {
                   1141:        static uint32_t vmbus_channel_nextcpu;
                   1142:        int cpu;
                   1143:
1.8       nonaka   1144:        cpu = atomic_inc_32_nv(&vmbus_channel_nextcpu) % ncpu;
1.1       nonaka   1145:        vmbus_channel_cpu_set(ch, cpu);
                   1146: }
                   1147:
                   1148: static void
                   1149: vmbus_channel_cpu_default(struct vmbus_channel *ch)
                   1150: {
                   1151:
                   1152:         /*
                   1153:         * By default, pin the channel to cpu0.  Devices having
                   1154:         * special channel-cpu mapping requirement should call
                   1155:         * vmbus_channel_cpu_{set,rr}().
                   1156:         */
                   1157:        vmbus_channel_cpu_set(ch, 0);
                   1158: }
                   1159:
1.8       nonaka   1160: bool
                   1161: vmbus_channel_is_revoked(struct vmbus_channel *ch)
                   1162: {
                   1163:
                   1164:        return (ch->ch_flags & CHF_REVOKED) ? true : false;
                   1165: }
                   1166:
1.1       nonaka   1167: static void
1.8       nonaka   1168: vmbus_process_offer(struct vmbus_softc *sc, struct vmbus_chanmsg_choffer *co)
1.1       nonaka   1169: {
                   1170:        struct vmbus_channel *ch;
                   1171:
                   1172:        ch = vmbus_channel_alloc(sc);
                   1173:        if (ch == NULL) {
                   1174:                device_printf(sc->sc_dev, "allocate channel %u failed\n",
1.8       nonaka   1175:                    co->chm_chanid);
1.1       nonaka   1176:                return;
                   1177:        }
                   1178:
                   1179:        /*
                   1180:         * By default we setup state to enable batched reading.
                   1181:         * A specific service can choose to disable this prior
                   1182:         * to opening the channel.
                   1183:         */
                   1184:        ch->ch_flags |= CHF_BATCHED;
                   1185:
1.8       nonaka   1186:        hyperv_guid_sprint(&co->chm_chtype, ch->ch_ident,
1.1       nonaka   1187:            sizeof(ch->ch_ident));
                   1188:
                   1189:        ch->ch_monprm->mp_connid = VMBUS_CONNID_EVENT;
                   1190:        if (sc->sc_proto > VMBUS_VERSION_WS2008)
1.8       nonaka   1191:                ch->ch_monprm->mp_connid = co->chm_connid;
1.1       nonaka   1192:
1.8       nonaka   1193:        if (co->chm_flags1 & VMBUS_CHOFFER_FLAG1_HASMNF) {
                   1194:                ch->ch_mgroup = co->chm_montrig / VMBUS_MONTRIG_LEN;
                   1195:                ch->ch_mindex = co->chm_montrig % VMBUS_MONTRIG_LEN;
1.1       nonaka   1196:                ch->ch_flags |= CHF_MONITOR;
                   1197:        }
                   1198:
1.8       nonaka   1199:        ch->ch_id = co->chm_chanid;
                   1200:        ch->ch_subidx = co->chm_subidx;
1.1       nonaka   1201:
1.8       nonaka   1202:        memcpy(&ch->ch_type, &co->chm_chtype, sizeof(ch->ch_type));
                   1203:        memcpy(&ch->ch_inst, &co->chm_chinst, sizeof(ch->ch_inst));
1.1       nonaka   1204:
                   1205:        if (vmbus_channel_add(ch) != 0) {
1.8       nonaka   1206:                atomic_dec_uint(&ch->ch_refs);
1.1       nonaka   1207:                vmbus_channel_free(ch);
                   1208:                return;
                   1209:        }
                   1210:
                   1211:        ch->ch_state = VMBUS_CHANSTATE_OFFERED;
                   1212:
1.8       nonaka   1213:        vmbus_devq_enqueue(sc, VMBUS_DEV_TYPE_ATTACH, ch);
                   1214:
1.1       nonaka   1215: #ifdef HYPERV_DEBUG
                   1216:        printf("%s: channel %u: \"%s\"", device_xname(sc->sc_dev), ch->ch_id,
                   1217:            ch->ch_ident);
                   1218:        if (ch->ch_flags & CHF_MONITOR)
1.8       nonaka   1219:                printf(", monitor %u\n", co->chm_montrig);
1.1       nonaka   1220:        else
                   1221:                printf("\n");
                   1222: #endif
                   1223: }
                   1224:
1.8       nonaka   1225: static void
                   1226: vmbus_process_rescind(struct vmbus_softc *sc,
                   1227:     struct vmbus_chanmsg_chrescind *cr)
                   1228: {
                   1229:        struct vmbus_channel *ch;
                   1230:
                   1231:        if (cr->chm_chanid > VMBUS_CHAN_MAX) {
                   1232:                device_printf(sc->sc_dev, "invalid revoked channel%u\n",
                   1233:                    cr->chm_chanid);
                   1234:                return;
                   1235:        }
                   1236:
                   1237:        mutex_enter(&sc->sc_channel_lock);
                   1238:        ch = vmbus_channel_lookup(sc, cr->chm_chanid);
                   1239:        if (ch == NULL) {
                   1240:                mutex_exit(&sc->sc_channel_lock);
                   1241:                device_printf(sc->sc_dev, "channel%u is not offered\n",
                   1242:                    cr->chm_chanid);
                   1243:                return;
                   1244:        }
                   1245:        TAILQ_REMOVE(&sc->sc_channels, ch, ch_entry);
                   1246:        mutex_exit(&sc->sc_channel_lock);
                   1247:
1.11      nonaka   1248:        if (VMBUS_CHAN_ISPRIMARY(ch)) {
                   1249:                mutex_enter(&sc->sc_prichan_lock);
                   1250:                TAILQ_REMOVE(&sc->sc_prichans, ch, ch_prientry);
                   1251:                mutex_exit(&sc->sc_prichan_lock);
                   1252:        }
                   1253:
1.8       nonaka   1254:        KASSERTMSG(!(ch->ch_flags & CHF_REVOKED),
                   1255:            "channel%u has already been revoked", ch->ch_id);
                   1256:        atomic_or_uint(&ch->ch_flags, CHF_REVOKED);
                   1257:
                   1258:        vmbus_channel_detach(ch);
                   1259: }
                   1260:
1.1       nonaka   1261: static int
                   1262: vmbus_channel_release(struct vmbus_channel *ch)
                   1263: {
                   1264:        struct vmbus_softc *sc = ch->ch_sc;
                   1265:        struct vmbus_chanmsg_chfree cmd;
                   1266:        int rv;
                   1267:
                   1268:        memset(&cmd, 0, sizeof(cmd));
                   1269:        cmd.chm_hdr.chm_type = VMBUS_CHANMSG_CHFREE;
                   1270:        cmd.chm_chanid = ch->ch_id;
                   1271:
                   1272:        rv = vmbus_cmd(sc, &cmd, sizeof(cmd), NULL, 0,
                   1273:            HCF_NOREPLY | (cold ? HCF_NOSLEEP : HCF_SLEEPOK));
                   1274:        if (rv) {
                   1275:                DPRINTF("%s: CHFREE failed with %d\n", device_xname(sc->sc_dev),
                   1276:                    rv);
                   1277:        }
                   1278:        return rv;
                   1279: }
                   1280:
                   1281: struct vmbus_channel **
                   1282: vmbus_subchannel_get(struct vmbus_channel *prich, int cnt)
                   1283: {
1.11      nonaka   1284:        struct vmbus_softc *sc = prich->ch_sc;
1.1       nonaka   1285:        struct vmbus_channel **ret, *ch;
1.11      nonaka   1286:        int i, s;
1.1       nonaka   1287:
1.11      nonaka   1288:        KASSERTMSG(cnt > 0, "invalid sub-channel count %d", cnt);
1.1       nonaka   1289:
1.11      nonaka   1290:        ret = kmem_zalloc(sizeof(struct vmbus_channel *) * cnt, KM_SLEEP);
1.1       nonaka   1291:
                   1292:        mutex_enter(&prich->ch_subchannel_lock);
                   1293:
1.11      nonaka   1294:        while (prich->ch_subchannel_count < cnt) {
                   1295:                if (cold) {
                   1296:                        mutex_exit(&prich->ch_subchannel_lock);
                   1297:                        delay(1000);
                   1298:                        s = splnet();
                   1299:                        hyperv_intr();
                   1300:                        splx(s);
                   1301:                        mutex_enter(&sc->sc_chevq_lock);
                   1302:                        vmbus_process_chevq(sc);
                   1303:                        mutex_exit(&sc->sc_chevq_lock);
                   1304:                        mutex_enter(&prich->ch_subchannel_lock);
                   1305:                } else {
                   1306:                        mtsleep(prich, PRIBIO, "hvsubch", 1,
                   1307:                            &prich->ch_subchannel_lock);
                   1308:                }
                   1309:        }
1.1       nonaka   1310:
                   1311:        i = 0;
                   1312:        TAILQ_FOREACH(ch, &prich->ch_subchannels, ch_subentry) {
                   1313:                ret[i] = ch;    /* XXX inc refs */
                   1314:
                   1315:                if (++i == cnt)
                   1316:                        break;
                   1317:        }
                   1318:
1.11      nonaka   1319:        KASSERTMSG(i == cnt, "invalid subchan count %d, should be %d",
                   1320:            prich->ch_subchannel_count, cnt);
                   1321:
1.1       nonaka   1322:        mutex_exit(&prich->ch_subchannel_lock);
                   1323:
                   1324:        return ret;
                   1325: }
                   1326:
                   1327: void
                   1328: vmbus_subchannel_put(struct vmbus_channel **subch, int cnt)
                   1329: {
                   1330:
                   1331:        kmem_free(subch, sizeof(struct vmbus_channel *) * cnt);
                   1332: }
                   1333:
                   1334: static struct vmbus_channel *
                   1335: vmbus_channel_lookup(struct vmbus_softc *sc, uint32_t relid)
                   1336: {
                   1337:        struct vmbus_channel *ch;
                   1338:
                   1339:        TAILQ_FOREACH(ch, &sc->sc_channels, ch_entry) {
                   1340:                if (ch->ch_id == relid)
                   1341:                        return ch;
                   1342:        }
                   1343:        return NULL;
                   1344: }
                   1345:
                   1346: static int
                   1347: vmbus_channel_ring_create(struct vmbus_channel *ch, uint32_t buflen)
                   1348: {
                   1349:        struct vmbus_softc *sc = ch->ch_sc;
                   1350:
                   1351:        buflen = roundup(buflen, PAGE_SIZE) + sizeof(struct vmbus_bufring);
                   1352:        ch->ch_ring_size = 2 * buflen;
1.8       nonaka   1353:        /* page aligned memory */
1.1       nonaka   1354:        ch->ch_ring = hyperv_dma_alloc(sc->sc_dmat, &ch->ch_ring_dma,
1.8       nonaka   1355:            ch->ch_ring_size, PAGE_SIZE, 0, 1, HYPERV_DMA_SLEEPOK);
1.1       nonaka   1356:        if (ch->ch_ring == NULL) {
                   1357:                device_printf(sc->sc_dev,
                   1358:                    "failed to allocate channel ring\n");
                   1359:                return ENOMEM;
                   1360:        }
                   1361:
                   1362:        memset(&ch->ch_wrd, 0, sizeof(ch->ch_wrd));
                   1363:        ch->ch_wrd.rd_ring = (struct vmbus_bufring *)ch->ch_ring;
                   1364:        ch->ch_wrd.rd_size = buflen;
                   1365:        ch->ch_wrd.rd_dsize = buflen - sizeof(struct vmbus_bufring);
                   1366:        mutex_init(&ch->ch_wrd.rd_lock, MUTEX_DEFAULT, IPL_NET);
                   1367:
                   1368:        memset(&ch->ch_rrd, 0, sizeof(ch->ch_rrd));
                   1369:        ch->ch_rrd.rd_ring = (struct vmbus_bufring *)((uint8_t *)ch->ch_ring +
                   1370:            buflen);
                   1371:        ch->ch_rrd.rd_size = buflen;
                   1372:        ch->ch_rrd.rd_dsize = buflen - sizeof(struct vmbus_bufring);
                   1373:        mutex_init(&ch->ch_rrd.rd_lock, MUTEX_DEFAULT, IPL_NET);
                   1374:
                   1375:        if (vmbus_handle_alloc(ch, &ch->ch_ring_dma, ch->ch_ring_size,
                   1376:            &ch->ch_ring_gpadl)) {
                   1377:                device_printf(sc->sc_dev,
                   1378:                    "failed to obtain a PA handle for the ring\n");
                   1379:                vmbus_channel_ring_destroy(ch);
                   1380:                return ENOMEM;
                   1381:        }
                   1382:
                   1383:        return 0;
                   1384: }
                   1385:
                   1386: static void
                   1387: vmbus_channel_ring_destroy(struct vmbus_channel *ch)
                   1388: {
                   1389:        struct vmbus_softc *sc = ch->ch_sc;
                   1390:
                   1391:        hyperv_dma_free(sc->sc_dmat, &ch->ch_ring_dma);
                   1392:        ch->ch_ring = NULL;
                   1393:        vmbus_handle_free(ch, ch->ch_ring_gpadl);
                   1394:
                   1395:        mutex_destroy(&ch->ch_wrd.rd_lock);
                   1396:        memset(&ch->ch_wrd, 0, sizeof(ch->ch_wrd));
                   1397:        mutex_destroy(&ch->ch_rrd.rd_lock);
                   1398:        memset(&ch->ch_rrd, 0, sizeof(ch->ch_rrd));
                   1399: }
                   1400:
                   1401: int
                   1402: vmbus_channel_open(struct vmbus_channel *ch, size_t buflen, void *udata,
                   1403:     size_t udatalen, void (*handler)(void *), void *arg)
                   1404: {
                   1405:        struct vmbus_softc *sc = ch->ch_sc;
                   1406:        struct vmbus_chanmsg_chopen cmd;
                   1407:        struct vmbus_chanmsg_chopen_resp rsp;
                   1408:        int rv = EINVAL;
                   1409:
                   1410:        if (ch->ch_ring == NULL &&
                   1411:            (rv = vmbus_channel_ring_create(ch, buflen))) {
                   1412:                DPRINTF("%s: failed to create channel ring\n",
                   1413:                    device_xname(sc->sc_dev));
                   1414:                return rv;
                   1415:        }
                   1416:
                   1417:        memset(&cmd, 0, sizeof(cmd));
                   1418:        cmd.chm_hdr.chm_type = VMBUS_CHANMSG_CHOPEN;
                   1419:        cmd.chm_openid = ch->ch_id;
                   1420:        cmd.chm_chanid = ch->ch_id;
                   1421:        cmd.chm_gpadl = ch->ch_ring_gpadl;
                   1422:        cmd.chm_txbr_pgcnt = atop(ch->ch_wrd.rd_size);
                   1423:        cmd.chm_vcpuid = ch->ch_vcpu;
                   1424:        if (udata && udatalen > 0)
                   1425:                memcpy(cmd.chm_udata, udata, udatalen);
                   1426:
                   1427:        memset(&rsp, 0, sizeof(rsp));
                   1428:
                   1429:        ch->ch_handler = handler;
                   1430:        ch->ch_ctx = arg;
                   1431:        ch->ch_state = VMBUS_CHANSTATE_OPENED;
                   1432:
                   1433:        rv = vmbus_cmd(sc, &cmd, sizeof(cmd), &rsp, sizeof(rsp),
                   1434:            cold ? HCF_NOSLEEP : HCF_SLEEPOK);
                   1435:        if (rv) {
                   1436:                vmbus_channel_ring_destroy(ch);
                   1437:                DPRINTF("%s: CHOPEN failed with %d\n", device_xname(sc->sc_dev),
                   1438:                    rv);
                   1439:                ch->ch_handler = NULL;
                   1440:                ch->ch_ctx = NULL;
                   1441:                ch->ch_state = VMBUS_CHANSTATE_OFFERED;
                   1442:                return rv;
                   1443:        }
                   1444:        return 0;
                   1445: }
                   1446:
                   1447: static void
                   1448: vmbus_channel_detach(struct vmbus_channel *ch)
                   1449: {
                   1450:        u_int refs;
                   1451:
1.8       nonaka   1452:        KASSERTMSG(ch->ch_refs > 0, "channel%u: invalid refcnt %d",
                   1453:            ch->ch_id, ch->ch_refs);
1.1       nonaka   1454:
1.16    ! riastrad 1455:        membar_exit();
1.8       nonaka   1456:        refs = atomic_dec_uint_nv(&ch->ch_refs);
                   1457:        if (refs == 0) {
1.16    ! riastrad 1458:                membar_enter();
1.8       nonaka   1459:                /* Detach the target channel. */
                   1460:                vmbus_devq_enqueue(ch->ch_sc, VMBUS_DEV_TYPE_DETACH, ch);
1.1       nonaka   1461:        }
                   1462: }
                   1463:
                   1464: static int
                   1465: vmbus_channel_close_internal(struct vmbus_channel *ch)
                   1466: {
                   1467:        struct vmbus_softc *sc = ch->ch_sc;
                   1468:        struct vmbus_chanmsg_chclose cmd;
                   1469:        int rv;
                   1470:
                   1471:        memset(&cmd, 0, sizeof(cmd));
                   1472:        cmd.chm_hdr.chm_type = VMBUS_CHANMSG_CHCLOSE;
                   1473:        cmd.chm_chanid = ch->ch_id;
                   1474:
                   1475:        ch->ch_state = VMBUS_CHANSTATE_CLOSING;
                   1476:        rv = vmbus_cmd(sc, &cmd, sizeof(cmd), NULL, 0,
                   1477:            HCF_NOREPLY | (cold ? HCF_NOSLEEP : HCF_SLEEPOK));
                   1478:        if (rv) {
                   1479:                DPRINTF("%s: CHCLOSE failed with %d\n",
                   1480:                    device_xname(sc->sc_dev), rv);
                   1481:                return rv;
                   1482:        }
                   1483:        ch->ch_state = VMBUS_CHANSTATE_CLOSED;
                   1484:        vmbus_channel_ring_destroy(ch);
                   1485:        return 0;
                   1486: }
                   1487:
                   1488: int
                   1489: vmbus_channel_close_direct(struct vmbus_channel *ch)
                   1490: {
                   1491:        int rv;
                   1492:
                   1493:        rv = vmbus_channel_close_internal(ch);
                   1494:        if (!VMBUS_CHAN_ISPRIMARY(ch))
                   1495:                vmbus_channel_detach(ch);
                   1496:        return rv;
                   1497: }
                   1498:
                   1499: int
                   1500: vmbus_channel_close(struct vmbus_channel *ch)
                   1501: {
                   1502:        struct vmbus_channel **subch;
                   1503:        int i, cnt, rv;
                   1504:
                   1505:        if (!VMBUS_CHAN_ISPRIMARY(ch))
                   1506:                return 0;
                   1507:
                   1508:        cnt = ch->ch_subchannel_count;
                   1509:        if (cnt > 0) {
                   1510:                subch = vmbus_subchannel_get(ch, cnt);
                   1511:                for (i = 0; i < ch->ch_subchannel_count; i++) {
                   1512:                        rv = vmbus_channel_close_internal(subch[i]);
                   1513:                        (void) rv;      /* XXX */
                   1514:                        vmbus_channel_detach(ch);
                   1515:                }
                   1516:                vmbus_subchannel_put(subch, cnt);
                   1517:        }
                   1518:
                   1519:        return vmbus_channel_close_internal(ch);
                   1520: }
                   1521:
                   1522: static inline void
                   1523: vmbus_channel_setevent(struct vmbus_softc *sc, struct vmbus_channel *ch)
                   1524: {
                   1525:        struct vmbus_mon_trig *mtg;
                   1526:
                   1527:        /* Each uint32_t represents 32 channels */
                   1528:        set_bit(ch->ch_id, sc->sc_wevents);
                   1529:        if (ch->ch_flags & CHF_MONITOR) {
                   1530:                mtg = &sc->sc_monitor[1]->mnf_trigs[ch->ch_mgroup];
                   1531:                set_bit(ch->ch_mindex, &mtg->mt_pending);
                   1532:        } else
                   1533:                vmbus_intr_signal(sc, hyperv_dma_get_paddr(&ch->ch_monprm_dma));
                   1534: }
                   1535:
                   1536: static void
                   1537: vmbus_channel_intr(void *arg)
                   1538: {
                   1539:        struct vmbus_channel *ch = arg;
                   1540:
                   1541:        if (vmbus_channel_ready(ch))
                   1542:                ch->ch_handler(ch->ch_ctx);
                   1543:
                   1544:        if (vmbus_channel_unpause(ch) == 0)
                   1545:                return;
                   1546:
                   1547:        vmbus_channel_pause(ch);
                   1548:        vmbus_channel_schedule(ch);
                   1549: }
                   1550:
                   1551: int
                   1552: vmbus_channel_setdeferred(struct vmbus_channel *ch, const char *name)
                   1553: {
                   1554:
                   1555:        ch->ch_taskq = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE,
                   1556:            vmbus_channel_intr, ch);
                   1557:        if (ch->ch_taskq == NULL)
                   1558:                return -1;
                   1559:        return 0;
                   1560: }
                   1561:
                   1562: void
                   1563: vmbus_channel_schedule(struct vmbus_channel *ch)
                   1564: {
                   1565:
                   1566:        if (ch->ch_handler) {
                   1567:                if (!cold && (ch->ch_flags & CHF_BATCHED)) {
                   1568:                        vmbus_channel_pause(ch);
                   1569:                        softint_schedule(ch->ch_taskq);
                   1570:                } else
                   1571:                        ch->ch_handler(ch->ch_ctx);
                   1572:        }
                   1573: }
                   1574:
                   1575: static __inline void
                   1576: vmbus_ring_put(struct vmbus_ring_data *wrd, uint8_t *data, uint32_t datalen)
                   1577: {
                   1578:        int left = MIN(datalen, wrd->rd_dsize - wrd->rd_prod);
                   1579:
                   1580:        memcpy(&wrd->rd_ring->br_data[wrd->rd_prod], data, left);
                   1581:        memcpy(&wrd->rd_ring->br_data[0], data + left, datalen - left);
                   1582:        wrd->rd_prod += datalen;
                   1583:        if (wrd->rd_prod >= wrd->rd_dsize)
                   1584:                wrd->rd_prod -= wrd->rd_dsize;
                   1585: }
                   1586:
                   1587: static inline void
                   1588: vmbus_ring_get(struct vmbus_ring_data *rrd, uint8_t *data, uint32_t datalen,
                   1589:     int peek)
                   1590: {
                   1591:        int left = MIN(datalen, rrd->rd_dsize - rrd->rd_cons);
                   1592:
                   1593:        memcpy(data, &rrd->rd_ring->br_data[rrd->rd_cons], left);
                   1594:        memcpy(data + left, &rrd->rd_ring->br_data[0], datalen - left);
                   1595:        if (!peek) {
                   1596:                rrd->rd_cons += datalen;
                   1597:                if (rrd->rd_cons >= rrd->rd_dsize)
                   1598:                        rrd->rd_cons -= rrd->rd_dsize;
                   1599:        }
                   1600: }
                   1601:
                   1602: static __inline void
                   1603: vmbus_ring_avail(struct vmbus_ring_data *rd, uint32_t *towrite,
                   1604:     uint32_t *toread)
                   1605: {
                   1606:        uint32_t ridx = rd->rd_ring->br_rindex;
                   1607:        uint32_t widx = rd->rd_ring->br_windex;
                   1608:        uint32_t r, w;
                   1609:
                   1610:        if (widx >= ridx)
                   1611:                w = rd->rd_dsize - (widx - ridx);
                   1612:        else
                   1613:                w = ridx - widx;
                   1614:        r = rd->rd_dsize - w;
                   1615:        if (towrite)
                   1616:                *towrite = w;
                   1617:        if (toread)
                   1618:                *toread = r;
                   1619: }
                   1620:
                   1621: static int
                   1622: vmbus_ring_write(struct vmbus_ring_data *wrd, struct iovec *iov, int iov_cnt,
                   1623:     int *needsig)
                   1624: {
                   1625:        uint64_t indices = 0;
                   1626:        uint32_t avail, oprod, datalen = sizeof(indices);
                   1627:        int i;
                   1628:
                   1629:        for (i = 0; i < iov_cnt; i++)
                   1630:                datalen += iov[i].iov_len;
                   1631:
                   1632:        KASSERT(datalen <= wrd->rd_dsize);
                   1633:
                   1634:        vmbus_ring_avail(wrd, &avail, NULL);
                   1635:        if (avail <= datalen) {
                   1636:                DPRINTF("%s: avail %u datalen %u\n", __func__, avail, datalen);
                   1637:                return EAGAIN;
                   1638:        }
                   1639:
                   1640:        oprod = wrd->rd_prod;
                   1641:
                   1642:        for (i = 0; i < iov_cnt; i++)
                   1643:                vmbus_ring_put(wrd, iov[i].iov_base, iov[i].iov_len);
                   1644:
                   1645:        indices = (uint64_t)oprod << 32;
                   1646:        vmbus_ring_put(wrd, (uint8_t *)&indices, sizeof(indices));
                   1647:
                   1648:        membar_sync();
                   1649:        wrd->rd_ring->br_windex = wrd->rd_prod;
                   1650:        membar_sync();
                   1651:
                   1652:        /* Signal when the ring transitions from being empty to non-empty */
                   1653:        if (wrd->rd_ring->br_imask == 0 &&
                   1654:            wrd->rd_ring->br_rindex == oprod)
                   1655:                *needsig = 1;
                   1656:        else
                   1657:                *needsig = 0;
                   1658:
                   1659:        return 0;
                   1660: }
                   1661:
                   1662: int
                   1663: vmbus_channel_send(struct vmbus_channel *ch, void *data, uint32_t datalen,
                   1664:     uint64_t rid, int type, uint32_t flags)
                   1665: {
                   1666:        struct vmbus_softc *sc = ch->ch_sc;
                   1667:        struct vmbus_chanpkt cp;
                   1668:        struct iovec iov[3];
                   1669:        uint32_t pktlen, pktlen_aligned;
                   1670:        uint64_t zeropad = 0;
                   1671:        int rv, needsig = 0;
                   1672:
                   1673:        pktlen = sizeof(cp) + datalen;
                   1674:        pktlen_aligned = roundup(pktlen, sizeof(uint64_t));
                   1675:
                   1676:        cp.cp_hdr.cph_type = type;
                   1677:        cp.cp_hdr.cph_flags = flags;
                   1678:        VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_hlen, sizeof(cp));
                   1679:        VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_tlen, pktlen_aligned);
                   1680:        cp.cp_hdr.cph_tid = rid;
                   1681:
                   1682:        iov[0].iov_base = &cp;
                   1683:        iov[0].iov_len = sizeof(cp);
                   1684:
                   1685:        iov[1].iov_base = data;
                   1686:        iov[1].iov_len = datalen;
                   1687:
                   1688:        iov[2].iov_base = &zeropad;
                   1689:        iov[2].iov_len = pktlen_aligned - pktlen;
                   1690:
                   1691:        mutex_enter(&ch->ch_wrd.rd_lock);
                   1692:        rv = vmbus_ring_write(&ch->ch_wrd, iov, 3, &needsig);
                   1693:        mutex_exit(&ch->ch_wrd.rd_lock);
                   1694:        if (rv == 0 && needsig)
                   1695:                vmbus_channel_setevent(sc, ch);
                   1696:
                   1697:        return rv;
                   1698: }
                   1699:
                   1700: int
                   1701: vmbus_channel_send_sgl(struct vmbus_channel *ch, struct vmbus_gpa *sgl,
                   1702:     uint32_t nsge, void *data, uint32_t datalen, uint64_t rid)
                   1703: {
                   1704:        struct vmbus_softc *sc = ch->ch_sc;
                   1705:        struct vmbus_chanpkt_sglist cp;
                   1706:        struct iovec iov[4];
                   1707:        uint32_t buflen, pktlen, pktlen_aligned;
                   1708:        uint64_t zeropad = 0;
                   1709:        int rv, needsig = 0;
                   1710:
                   1711:        buflen = sizeof(struct vmbus_gpa) * nsge;
                   1712:        pktlen = sizeof(cp) + datalen + buflen;
                   1713:        pktlen_aligned = roundup(pktlen, sizeof(uint64_t));
                   1714:
                   1715:        cp.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA;
                   1716:        cp.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC;
                   1717:        VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_hlen, sizeof(cp) + buflen);
                   1718:        VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_tlen, pktlen_aligned);
                   1719:        cp.cp_hdr.cph_tid = rid;
                   1720:        cp.cp_gpa_cnt = nsge;
                   1721:        cp.cp_rsvd = 0;
                   1722:
                   1723:        iov[0].iov_base = &cp;
                   1724:        iov[0].iov_len = sizeof(cp);
                   1725:
                   1726:        iov[1].iov_base = sgl;
                   1727:        iov[1].iov_len = buflen;
                   1728:
                   1729:        iov[2].iov_base = data;
                   1730:        iov[2].iov_len = datalen;
                   1731:
                   1732:        iov[3].iov_base = &zeropad;
                   1733:        iov[3].iov_len = pktlen_aligned - pktlen;
                   1734:
                   1735:        mutex_enter(&ch->ch_wrd.rd_lock);
                   1736:        rv = vmbus_ring_write(&ch->ch_wrd, iov, 4, &needsig);
                   1737:        mutex_exit(&ch->ch_wrd.rd_lock);
                   1738:        if (rv == 0 && needsig)
                   1739:                vmbus_channel_setevent(sc, ch);
                   1740:
                   1741:        return rv;
                   1742: }
                   1743:
                   1744: int
                   1745: vmbus_channel_send_prpl(struct vmbus_channel *ch, struct vmbus_gpa_range *prpl,
                   1746:     uint32_t nprp, void *data, uint32_t datalen, uint64_t rid)
                   1747: {
                   1748:        struct vmbus_softc *sc = ch->ch_sc;
                   1749:        struct vmbus_chanpkt_prplist cp;
                   1750:        struct iovec iov[4];
                   1751:        uint32_t buflen, pktlen, pktlen_aligned;
                   1752:        uint64_t zeropad = 0;
                   1753:        int rv, needsig = 0;
                   1754:
                   1755:        buflen = sizeof(struct vmbus_gpa_range) * (nprp + 1);
                   1756:        pktlen = sizeof(cp) + datalen + buflen;
                   1757:        pktlen_aligned = roundup(pktlen, sizeof(uint64_t));
                   1758:
                   1759:        cp.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA;
                   1760:        cp.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC;
                   1761:        VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_hlen, sizeof(cp) + buflen);
                   1762:        VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_tlen, pktlen_aligned);
                   1763:        cp.cp_hdr.cph_tid = rid;
                   1764:        cp.cp_range_cnt = 1;
                   1765:        cp.cp_rsvd = 0;
                   1766:
                   1767:        iov[0].iov_base = &cp;
                   1768:        iov[0].iov_len = sizeof(cp);
                   1769:
                   1770:        iov[1].iov_base = prpl;
                   1771:        iov[1].iov_len = buflen;
                   1772:
                   1773:        iov[2].iov_base = data;
                   1774:        iov[2].iov_len = datalen;
                   1775:
                   1776:        iov[3].iov_base = &zeropad;
                   1777:        iov[3].iov_len = pktlen_aligned - pktlen;
                   1778:
                   1779:        mutex_enter(&ch->ch_wrd.rd_lock);
                   1780:        rv = vmbus_ring_write(&ch->ch_wrd, iov, 4, &needsig);
                   1781:        mutex_exit(&ch->ch_wrd.rd_lock);
                   1782:        if (rv == 0 && needsig)
                   1783:                vmbus_channel_setevent(sc, ch);
                   1784:
                   1785:        return rv;
                   1786: }
                   1787:
                   1788: static int
                   1789: vmbus_ring_peek(struct vmbus_ring_data *rrd, void *data, uint32_t datalen)
                   1790: {
                   1791:        uint32_t avail;
                   1792:
                   1793:        KASSERT(datalen <= rrd->rd_dsize);
                   1794:
                   1795:        vmbus_ring_avail(rrd, NULL, &avail);
                   1796:        if (avail < datalen)
                   1797:                return EAGAIN;
                   1798:
                   1799:        vmbus_ring_get(rrd, (uint8_t *)data, datalen, 1);
                   1800:        return 0;
                   1801: }
                   1802:
                   1803: static int
                   1804: vmbus_ring_read(struct vmbus_ring_data *rrd, void *data, uint32_t datalen,
                   1805:     uint32_t offset)
                   1806: {
                   1807:        uint64_t indices;
                   1808:        uint32_t avail;
                   1809:
                   1810:        KASSERT(datalen <= rrd->rd_dsize);
                   1811:
                   1812:        vmbus_ring_avail(rrd, NULL, &avail);
                   1813:        if (avail < datalen) {
                   1814:                DPRINTF("%s: avail %u datalen %u\n", __func__, avail, datalen);
                   1815:                return EAGAIN;
                   1816:        }
                   1817:
                   1818:        if (offset) {
                   1819:                rrd->rd_cons += offset;
                   1820:                if (rrd->rd_cons >= rrd->rd_dsize)
                   1821:                        rrd->rd_cons -= rrd->rd_dsize;
                   1822:        }
                   1823:
                   1824:        vmbus_ring_get(rrd, (uint8_t *)data, datalen, 0);
                   1825:        vmbus_ring_get(rrd, (uint8_t *)&indices, sizeof(indices), 0);
                   1826:
                   1827:        membar_sync();
                   1828:        rrd->rd_ring->br_rindex = rrd->rd_cons;
                   1829:
                   1830:        return 0;
                   1831: }
                   1832:
                   1833: int
                   1834: vmbus_channel_recv(struct vmbus_channel *ch, void *data, uint32_t datalen,
                   1835:     uint32_t *rlen, uint64_t *rid, int raw)
                   1836: {
                   1837:        struct vmbus_softc *sc = ch->ch_sc;
                   1838:        struct vmbus_chanpkt_hdr cph;
                   1839:        uint32_t offset, pktlen;
                   1840:        int rv;
                   1841:
                   1842:        *rlen = 0;
                   1843:
                   1844:        mutex_enter(&ch->ch_rrd.rd_lock);
                   1845:
                   1846:        if ((rv = vmbus_ring_peek(&ch->ch_rrd, &cph, sizeof(cph))) != 0) {
                   1847:                mutex_exit(&ch->ch_rrd.rd_lock);
                   1848:                return rv;
                   1849:        }
                   1850:
                   1851:        offset = raw ? 0 : VMBUS_CHANPKT_GETLEN(cph.cph_hlen);
                   1852:        pktlen = VMBUS_CHANPKT_GETLEN(cph.cph_tlen) - offset;
                   1853:        if (pktlen > datalen) {
                   1854:                mutex_exit(&ch->ch_rrd.rd_lock);
                   1855:                device_printf(sc->sc_dev, "%s: pktlen %u datalen %u\n",
                   1856:                    __func__, pktlen, datalen);
                   1857:                return EINVAL;
                   1858:        }
                   1859:
                   1860:        rv = vmbus_ring_read(&ch->ch_rrd, data, pktlen, offset);
                   1861:        if (rv == 0) {
                   1862:                *rlen = pktlen;
                   1863:                *rid = cph.cph_tid;
                   1864:        }
                   1865:
                   1866:        mutex_exit(&ch->ch_rrd.rd_lock);
                   1867:
                   1868:        return rv;
                   1869: }
                   1870:
                   1871: static inline void
                   1872: vmbus_ring_mask(struct vmbus_ring_data *rd)
                   1873: {
                   1874:
                   1875:        membar_sync();
                   1876:        rd->rd_ring->br_imask = 1;
                   1877:        membar_sync();
                   1878: }
                   1879:
                   1880: static inline void
                   1881: vmbus_ring_unmask(struct vmbus_ring_data *rd)
                   1882: {
                   1883:
                   1884:        membar_sync();
                   1885:        rd->rd_ring->br_imask = 0;
                   1886:        membar_sync();
                   1887: }
                   1888:
                   1889: static void
                   1890: vmbus_channel_pause(struct vmbus_channel *ch)
                   1891: {
                   1892:
                   1893:        vmbus_ring_mask(&ch->ch_rrd);
                   1894: }
                   1895:
                   1896: static uint32_t
                   1897: vmbus_channel_unpause(struct vmbus_channel *ch)
                   1898: {
                   1899:        uint32_t avail;
                   1900:
                   1901:        vmbus_ring_unmask(&ch->ch_rrd);
                   1902:        vmbus_ring_avail(&ch->ch_rrd, NULL, &avail);
                   1903:
                   1904:        return avail;
                   1905: }
                   1906:
                   1907: static uint32_t
                   1908: vmbus_channel_ready(struct vmbus_channel *ch)
                   1909: {
                   1910:        uint32_t avail;
                   1911:
                   1912:        vmbus_ring_avail(&ch->ch_rrd, NULL, &avail);
                   1913:
                   1914:        return avail;
                   1915: }
                   1916:
                   1917: /* How many PFNs can be referenced by the header */
                   1918: #define VMBUS_NPFNHDR  ((VMBUS_MSG_DSIZE_MAX - \
                   1919:          sizeof(struct vmbus_chanmsg_gpadl_conn)) / sizeof(uint64_t))
                   1920:
                   1921: /* How many PFNs can be referenced by the body */
                   1922: #define VMBUS_NPFNBODY ((VMBUS_MSG_DSIZE_MAX - \
                   1923:          sizeof(struct vmbus_chanmsg_gpadl_subconn)) / sizeof(uint64_t))
                   1924:
                   1925: int
                   1926: vmbus_handle_alloc(struct vmbus_channel *ch, const struct hyperv_dma *dma,
                   1927:     uint32_t buflen, uint32_t *handle)
                   1928: {
                   1929:        const int prflags = cold ? PR_NOWAIT : PR_WAITOK;
                   1930:        const int kmemflags = cold ? KM_NOSLEEP : KM_SLEEP;
                   1931:        const int msgflags = cold ? MSGF_NOSLEEP : 0;
                   1932:        const int hcflags = cold ? HCF_NOSLEEP : HCF_SLEEPOK;
                   1933:        struct vmbus_softc *sc = ch->ch_sc;
                   1934:        struct vmbus_chanmsg_gpadl_conn *hdr;
                   1935:        struct vmbus_chanmsg_gpadl_subconn *cmd;
                   1936:        struct vmbus_chanmsg_gpadl_connresp rsp;
                   1937:        struct vmbus_msg *msg;
                   1938:        int i, j, last, left, rv;
                   1939:        int bodylen = 0, ncmds = 0, pfn = 0;
                   1940:        uint64_t *frames;
                   1941:        paddr_t pa;
                   1942:        uint8_t *body;
                   1943:        /* Total number of pages to reference */
                   1944:        int total = atop(buflen);
                   1945:        /* Number of pages that will fit the header */
                   1946:        int inhdr = MIN(total, VMBUS_NPFNHDR);
                   1947:
                   1948:        KASSERT((buflen & PAGE_MASK) == 0);
                   1949:        KASSERT(buflen == (uint32_t)dma->map->dm_mapsize);
                   1950:
                   1951:        msg = pool_cache_get_paddr(sc->sc_msgpool, prflags, &pa);
                   1952:        if (msg == NULL)
                   1953:                return ENOMEM;
                   1954:
                   1955:        /* Prepare array of frame addresses */
                   1956:        frames = kmem_zalloc(total * sizeof(*frames), kmemflags);
                   1957:        if (frames == NULL) {
                   1958:                pool_cache_put_paddr(sc->sc_msgpool, msg, pa);
                   1959:                return ENOMEM;
                   1960:        }
                   1961:        for (i = 0, j = 0; i < dma->map->dm_nsegs && j < total; i++) {
                   1962:                bus_dma_segment_t *seg = &dma->map->dm_segs[i];
                   1963:                bus_addr_t addr = seg->ds_addr;
                   1964:
                   1965:                KASSERT((addr & PAGE_MASK) == 0);
                   1966:                KASSERT((seg->ds_len & PAGE_MASK) == 0);
                   1967:
                   1968:                while (addr < seg->ds_addr + seg->ds_len && j < total) {
                   1969:                        frames[j++] = atop(addr);
                   1970:                        addr += PAGE_SIZE;
                   1971:                }
                   1972:        }
                   1973:
                   1974:        memset(msg, 0, sizeof(*msg));
                   1975:        msg->msg_req.hc_dsize = sizeof(struct vmbus_chanmsg_gpadl_conn) +
                   1976:            inhdr * sizeof(uint64_t);
                   1977:        hdr = (struct vmbus_chanmsg_gpadl_conn *)msg->msg_req.hc_data;
                   1978:        msg->msg_rsp = &rsp;
                   1979:        msg->msg_rsplen = sizeof(rsp);
                   1980:        msg->msg_flags = msgflags;
                   1981:
                   1982:        left = total - inhdr;
                   1983:
                   1984:        /* Allocate additional gpadl_body structures if required */
                   1985:        if (left > 0) {
1.9       nonaka   1986:                ncmds = howmany(left, VMBUS_NPFNBODY);
1.1       nonaka   1987:                bodylen = ncmds * VMBUS_MSG_DSIZE_MAX;
                   1988:                body = kmem_zalloc(bodylen, kmemflags);
                   1989:                if (body == NULL) {
                   1990:                        kmem_free(frames, total * sizeof(*frames));
                   1991:                        pool_cache_put_paddr(sc->sc_msgpool, msg, pa);
                   1992:                        return ENOMEM;
                   1993:                }
                   1994:        }
                   1995:
1.8       nonaka   1996:        *handle = atomic_inc_32_nv(&sc->sc_handle);
1.1       nonaka   1997:
                   1998:        hdr->chm_hdr.chm_type = VMBUS_CHANMSG_GPADL_CONN;
                   1999:        hdr->chm_chanid = ch->ch_id;
                   2000:        hdr->chm_gpadl = *handle;
                   2001:
                   2002:        /* Single range for a contiguous buffer */
                   2003:        hdr->chm_range_cnt = 1;
                   2004:        hdr->chm_range_len = sizeof(struct vmbus_gpa_range) + total *
                   2005:            sizeof(uint64_t);
                   2006:        hdr->chm_range.gpa_ofs = 0;
                   2007:        hdr->chm_range.gpa_len = buflen;
                   2008:
                   2009:        /* Fit as many pages as possible into the header */
                   2010:        for (i = 0; i < inhdr; i++)
                   2011:                hdr->chm_range.gpa_page[i] = frames[pfn++];
                   2012:
                   2013:        for (i = 0; i < ncmds; i++) {
                   2014:                cmd = (struct vmbus_chanmsg_gpadl_subconn *)(body +
                   2015:                    VMBUS_MSG_DSIZE_MAX * i);
                   2016:                cmd->chm_hdr.chm_type = VMBUS_CHANMSG_GPADL_SUBCONN;
                   2017:                cmd->chm_gpadl = *handle;
                   2018:                last = MIN(left, VMBUS_NPFNBODY);
                   2019:                for (j = 0; j < last; j++)
                   2020:                        cmd->chm_gpa_page[j] = frames[pfn++];
                   2021:                left -= last;
                   2022:        }
                   2023:
                   2024:        rv = vmbus_start(sc, msg, pa);
                   2025:        if (rv != 0) {
                   2026:                DPRINTF("%s: GPADL_CONN failed\n", device_xname(sc->sc_dev));
                   2027:                goto out;
                   2028:        }
                   2029:        for (i = 0; i < ncmds; i++) {
                   2030:                int cmdlen = sizeof(*cmd);
                   2031:                cmd = (struct vmbus_chanmsg_gpadl_subconn *)(body +
                   2032:                    VMBUS_MSG_DSIZE_MAX * i);
                   2033:                /* Last element can be short */
                   2034:                if (i == ncmds - 1)
                   2035:                        cmdlen += last * sizeof(uint64_t);
                   2036:                else
                   2037:                        cmdlen += VMBUS_NPFNBODY * sizeof(uint64_t);
                   2038:                rv = vmbus_cmd(sc, cmd, cmdlen, NULL, 0, HCF_NOREPLY | hcflags);
                   2039:                if (rv != 0) {
                   2040:                        DPRINTF("%s: GPADL_SUBCONN (iteration %d/%d) failed "
                   2041:                            "with %d\n", device_xname(sc->sc_dev), i, ncmds,
                   2042:                            rv);
                   2043:                        goto out;
                   2044:                }
                   2045:        }
                   2046:        rv = vmbus_reply(sc, msg);
                   2047:        if (rv != 0) {
                   2048:                DPRINTF("%s: GPADL allocation failed with %d\n",
                   2049:                    device_xname(sc->sc_dev), rv);
                   2050:        }
                   2051:
                   2052:  out:
                   2053:        if (bodylen > 0)
                   2054:                kmem_free(body, bodylen);
                   2055:        kmem_free(frames, total * sizeof(*frames));
                   2056:        pool_cache_put_paddr(sc->sc_msgpool, msg, pa);
                   2057:        if (rv)
                   2058:                return rv;
                   2059:
                   2060:        KASSERT(*handle == rsp.chm_gpadl);
                   2061:
                   2062:        return 0;
                   2063: }
                   2064:
                   2065: void
                   2066: vmbus_handle_free(struct vmbus_channel *ch, uint32_t handle)
                   2067: {
                   2068:        struct vmbus_softc *sc = ch->ch_sc;
                   2069:        struct vmbus_chanmsg_gpadl_disconn cmd;
                   2070:        struct vmbus_chanmsg_gpadl_disconn rsp;
                   2071:        int rv;
                   2072:
                   2073:        memset(&cmd, 0, sizeof(cmd));
                   2074:        cmd.chm_hdr.chm_type = VMBUS_CHANMSG_GPADL_DISCONN;
                   2075:        cmd.chm_chanid = ch->ch_id;
                   2076:        cmd.chm_gpadl = handle;
                   2077:
                   2078:        rv = vmbus_cmd(sc, &cmd, sizeof(cmd), &rsp, sizeof(rsp),
                   2079:            cold ? HCF_NOSLEEP : HCF_SLEEPOK);
                   2080:        if (rv) {
                   2081:                DPRINTF("%s: GPADL_DISCONN failed with %d\n",
                   2082:                    device_xname(sc->sc_dev), rv);
                   2083:        }
                   2084: }
                   2085:
1.11      nonaka   2086:  static void
                   2087: vmbus_chevq_enqueue(struct vmbus_softc *sc, int type, void *arg)
                   2088: {
                   2089:        struct vmbus_chev *vce;
                   2090:
                   2091:        vce = kmem_intr_alloc(sizeof(*vce), KM_NOSLEEP);
                   2092:        if (vce == NULL) {
                   2093:                device_printf(sc->sc_dev, "failed to allocate chev\n");
                   2094:                return;
                   2095:        }
                   2096:
                   2097:        vce->vce_type = type;
                   2098:        vce->vce_arg = arg;
                   2099:
                   2100:        mutex_enter(&sc->sc_chevq_lock);
                   2101:        SIMPLEQ_INSERT_TAIL(&sc->sc_chevq, vce, vce_entry);
                   2102:        cv_broadcast(&sc->sc_chevq_cv);
                   2103:        mutex_exit(&sc->sc_chevq_lock);
                   2104: }
                   2105:
                   2106: static void
                   2107: vmbus_process_chevq(void *arg)
                   2108: {
                   2109:        struct vmbus_softc *sc = arg;
                   2110:        struct vmbus_chev *vce;
                   2111:        struct vmbus_chanmsg_choffer *co;
                   2112:        struct vmbus_chanmsg_chrescind *cr;
                   2113:
                   2114:        KASSERT(mutex_owned(&sc->sc_chevq_lock));
                   2115:
                   2116:        while (!SIMPLEQ_EMPTY(&sc->sc_chevq)) {
                   2117:                vce = SIMPLEQ_FIRST(&sc->sc_chevq);
                   2118:                SIMPLEQ_REMOVE_HEAD(&sc->sc_chevq, vce_entry);
                   2119:                mutex_exit(&sc->sc_chevq_lock);
                   2120:
                   2121:                switch (vce->vce_type) {
                   2122:                case VMBUS_CHEV_TYPE_OFFER:
                   2123:                        co = vce->vce_arg;
                   2124:                        vmbus_process_offer(sc, co);
                   2125:                        kmem_free(co, sizeof(*co));
                   2126:                        break;
                   2127:
                   2128:                case VMBUS_CHEV_TYPE_RESCIND:
                   2129:                        cr = vce->vce_arg;
                   2130:                        vmbus_process_rescind(sc, cr);
                   2131:                        kmem_free(cr, sizeof(*cr));
                   2132:                        break;
                   2133:
                   2134:                default:
                   2135:                        DPRINTF("%s: unknown chevq type %d\n",
                   2136:                            device_xname(sc->sc_dev), vce->vce_type);
                   2137:                        break;
                   2138:                }
                   2139:                kmem_free(vce, sizeof(*vce));
                   2140:
                   2141:                mutex_enter(&sc->sc_chevq_lock);
                   2142:        }
                   2143: }
                   2144:
                   2145: static void
                   2146: vmbus_chevq_thread(void *arg)
                   2147: {
                   2148:        struct vmbus_softc *sc = arg;
                   2149:
                   2150:        mutex_enter(&sc->sc_chevq_lock);
                   2151:        for (;;) {
                   2152:                if (SIMPLEQ_EMPTY(&sc->sc_chevq)) {
                   2153:                        cv_wait(&sc->sc_chevq_cv, &sc->sc_chevq_lock);
                   2154:                        continue;
                   2155:                }
                   2156:
                   2157:                vmbus_process_chevq(sc);
                   2158:        }
                   2159:        mutex_exit(&sc->sc_chevq_lock);
                   2160:
                   2161:        kthread_exit(0);
                   2162: }
                   2163:
1.8       nonaka   2164: static void
                   2165: vmbus_devq_enqueue(struct vmbus_softc *sc, int type, struct vmbus_channel *ch)
1.1       nonaka   2166: {
1.8       nonaka   2167:        struct vmbus_dev *vd;
                   2168:
1.11      nonaka   2169:        vd = kmem_zalloc(sizeof(*vd), KM_SLEEP);
1.8       nonaka   2170:        if (vd == NULL) {
                   2171:                device_printf(sc->sc_dev, "failed to allocate devq\n");
                   2172:                return;
                   2173:        }
1.1       nonaka   2174:
1.8       nonaka   2175:        vd->vd_type = type;
                   2176:        vd->vd_chan = ch;
1.1       nonaka   2177:
1.11      nonaka   2178:        if (VMBUS_CHAN_ISPRIMARY(ch)) {
                   2179:                mutex_enter(&sc->sc_devq_lock);
                   2180:                SIMPLEQ_INSERT_TAIL(&sc->sc_devq, vd, vd_entry);
                   2181:                cv_broadcast(&sc->sc_devq_cv);
                   2182:                mutex_exit(&sc->sc_devq_lock);
                   2183:        } else {
                   2184:                mutex_enter(&sc->sc_subch_devq_lock);
                   2185:                SIMPLEQ_INSERT_TAIL(&sc->sc_subch_devq, vd, vd_entry);
                   2186:                cv_broadcast(&sc->sc_subch_devq_cv);
                   2187:                mutex_exit(&sc->sc_subch_devq_lock);
                   2188:        }
1.1       nonaka   2189: }
                   2190:
1.8       nonaka   2191: static void
                   2192: vmbus_process_devq(void *arg)
1.1       nonaka   2193: {
1.8       nonaka   2194:        struct vmbus_softc *sc = arg;
                   2195:        struct vmbus_dev *vd;
1.11      nonaka   2196:        struct vmbus_channel *ch;
                   2197:        struct vmbus_attach_args vaa;
1.8       nonaka   2198:
                   2199:        KASSERT(mutex_owned(&sc->sc_devq_lock));
                   2200:
                   2201:        while (!SIMPLEQ_EMPTY(&sc->sc_devq)) {
                   2202:                vd = SIMPLEQ_FIRST(&sc->sc_devq);
                   2203:                SIMPLEQ_REMOVE_HEAD(&sc->sc_devq, vd_entry);
                   2204:                mutex_exit(&sc->sc_devq_lock);
                   2205:
                   2206:                switch (vd->vd_type) {
                   2207:                case VMBUS_DEV_TYPE_ATTACH:
                   2208:                        ch = vd->vd_chan;
1.11      nonaka   2209:                        vaa.aa_type = &ch->ch_type;
                   2210:                        vaa.aa_inst = &ch->ch_inst;
                   2211:                        vaa.aa_ident = ch->ch_ident;
                   2212:                        vaa.aa_chan = ch;
                   2213:                        vaa.aa_iot = sc->sc_iot;
                   2214:                        vaa.aa_memt = sc->sc_memt;
1.13      thorpej  2215:                        ch->ch_dev = config_found(sc->sc_dev,
1.14      thorpej  2216:                            &vaa, vmbus_attach_print, CFARGS_NONE);
1.8       nonaka   2217:                        break;
                   2218:
                   2219:                case VMBUS_DEV_TYPE_DETACH:
                   2220:                        ch = vd->vd_chan;
1.11      nonaka   2221:                        if (ch->ch_dev != NULL) {
                   2222:                                config_detach(ch->ch_dev, DETACH_FORCE);
                   2223:                                ch->ch_dev = NULL;
1.8       nonaka   2224:                        }
                   2225:                        vmbus_channel_release(ch);
                   2226:                        vmbus_channel_free(ch);
                   2227:                        break;
1.1       nonaka   2228:
1.8       nonaka   2229:                default:
1.11      nonaka   2230:                        DPRINTF("%s: unknown devq type %d\n",
1.8       nonaka   2231:                            device_xname(sc->sc_dev), vd->vd_type);
                   2232:                        break;
1.1       nonaka   2233:                }
1.8       nonaka   2234:                kmem_free(vd, sizeof(*vd));
                   2235:
                   2236:                mutex_enter(&sc->sc_devq_lock);
1.1       nonaka   2237:        }
                   2238: }
                   2239:
1.8       nonaka   2240: static void
                   2241: vmbus_devq_thread(void *arg)
1.1       nonaka   2242: {
1.8       nonaka   2243:        struct vmbus_softc *sc = arg;
1.1       nonaka   2244:
1.8       nonaka   2245:        mutex_enter(&sc->sc_devq_lock);
                   2246:        for (;;) {
                   2247:                if (SIMPLEQ_EMPTY(&sc->sc_devq)) {
                   2248:                        cv_wait(&sc->sc_devq_cv, &sc->sc_devq_lock);
1.1       nonaka   2249:                        continue;
1.8       nonaka   2250:                }
1.1       nonaka   2251:
1.8       nonaka   2252:                vmbus_process_devq(sc);
1.1       nonaka   2253:        }
1.8       nonaka   2254:        mutex_exit(&sc->sc_devq_lock);
                   2255:
                   2256:        kthread_exit(0);
                   2257: }
                   2258:
1.11      nonaka   2259: static void
                   2260: vmbus_subchannel_devq_thread(void *arg)
                   2261: {
                   2262:        struct vmbus_softc *sc = arg;
                   2263:        struct vmbus_dev *vd;
                   2264:        struct vmbus_channel *ch, *prich;
                   2265:
                   2266:        mutex_enter(&sc->sc_subch_devq_lock);
                   2267:        for (;;) {
                   2268:                if (SIMPLEQ_EMPTY(&sc->sc_subch_devq)) {
                   2269:                        cv_wait(&sc->sc_subch_devq_cv, &sc->sc_subch_devq_lock);
                   2270:                        continue;
                   2271:                }
                   2272:
                   2273:                while (!SIMPLEQ_EMPTY(&sc->sc_subch_devq)) {
                   2274:                        vd = SIMPLEQ_FIRST(&sc->sc_subch_devq);
                   2275:                        SIMPLEQ_REMOVE_HEAD(&sc->sc_subch_devq, vd_entry);
                   2276:                        mutex_exit(&sc->sc_subch_devq_lock);
                   2277:
                   2278:                        switch (vd->vd_type) {
                   2279:                        case VMBUS_DEV_TYPE_ATTACH:
                   2280:                                /* Nothing to do */
                   2281:                                break;
                   2282:
                   2283:                        case VMBUS_DEV_TYPE_DETACH:
                   2284:                                ch = vd->vd_chan;
                   2285:
                   2286:                                vmbus_channel_release(ch);
                   2287:
                   2288:                                prich = ch->ch_primary_channel;
                   2289:                                mutex_enter(&prich->ch_subchannel_lock);
                   2290:                                TAILQ_REMOVE(&prich->ch_subchannels, ch,
                   2291:                                    ch_subentry);
                   2292:                                prich->ch_subchannel_count--;
                   2293:                                mutex_exit(&prich->ch_subchannel_lock);
                   2294:                                wakeup(prich);
                   2295:
                   2296:                                vmbus_channel_free(ch);
                   2297:                                break;
                   2298:
                   2299:                        default:
                   2300:                                DPRINTF("%s: unknown devq type %d\n",
                   2301:                                    device_xname(sc->sc_dev), vd->vd_type);
                   2302:                                break;
                   2303:                        }
                   2304:
                   2305:                        kmem_free(vd, sizeof(*vd));
                   2306:
                   2307:                        mutex_enter(&sc->sc_subch_devq_lock);
                   2308:                }
                   2309:        }
                   2310:        mutex_exit(&sc->sc_subch_devq_lock);
                   2311:
                   2312:        kthread_exit(0);
                   2313: }
                   2314:
                   2315:
1.8       nonaka   2316: static int
                   2317: vmbus_attach_print(void *aux, const char *name)
                   2318: {
                   2319:        struct vmbus_attach_args *aa = aux;
                   2320:
                   2321:        if (name)
                   2322:                printf("\"%s\" at %s", aa->aa_ident, name);
                   2323:
                   2324:        return UNCONF;
1.1       nonaka   2325: }
                   2326:
                   2327: MODULE(MODULE_CLASS_DRIVER, vmbus, "hyperv");
                   2328:
                   2329: #ifdef _MODULE
                   2330: #include "ioconf.c"
                   2331: #endif
                   2332:
                   2333: static int
                   2334: vmbus_modcmd(modcmd_t cmd, void *aux)
                   2335: {
                   2336:        int rv = 0;
                   2337:
                   2338:        switch (cmd) {
                   2339:        case MODULE_CMD_INIT:
                   2340: #ifdef _MODULE
                   2341:                rv = config_init_component(cfdriver_ioconf_vmbus,
                   2342:                    cfattach_ioconf_vmbus, cfdata_ioconf_vmbus);
                   2343: #endif
                   2344:                break;
                   2345:
                   2346:        case MODULE_CMD_FINI:
                   2347: #ifdef _MODULE
                   2348:                rv = config_fini_component(cfdriver_ioconf_vmbus,
                   2349:                    cfattach_ioconf_vmbus, cfdata_ioconf_vmbus);
                   2350: #endif
                   2351:                break;
                   2352:
                   2353:        default:
                   2354:                rv = ENOTTY;
                   2355:                break;
                   2356:        }
                   2357:
                   2358:        return rv;
                   2359: }

CVSweb <webmaster@jp.NetBSD.org>