Fri Dec 6 12:46:06 2019 UTC ()
Clear the allocated memory in hyperv_dma_alloc().


(nonaka)
diff -r1.2 -r1.3 src/sys/dev/hyperv/hyperv_common.c
diff -r1.5 -r1.6 src/sys/dev/hyperv/vmbus.c

cvs diff -r1.2 -r1.3 src/sys/dev/hyperv/hyperv_common.c (switch to unified diff)

--- src/sys/dev/hyperv/hyperv_common.c 2019/05/31 04:23:19 1.2
+++ src/sys/dev/hyperv/hyperv_common.c 2019/12/06 12:46:06 1.3
@@ -1,184 +1,188 @@ @@ -1,184 +1,188 @@
1/* $NetBSD: hyperv_common.c,v 1.2 2019/05/31 04:23:19 nonaka Exp $ */ 1/* $NetBSD: hyperv_common.c,v 1.3 2019/12/06 12:46:06 nonaka Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2009-2012,2016-2017 Microsoft Corp. 4 * Copyright (c) 2009-2012,2016-2017 Microsoft Corp.
5 * Copyright (c) 2012 NetApp Inc. 5 * Copyright (c) 2012 NetApp Inc.
6 * Copyright (c) 2012 Citrix Inc. 6 * Copyright (c) 2012 Citrix Inc.
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice unmodified, this list of conditions, and the following 13 * notice unmodified, this list of conditions, and the following
14 * disclaimer. 14 * disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: hyperv_common.c,v 1.2 2019/05/31 04:23:19 nonaka Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: hyperv_common.c,v 1.3 2019/12/06 12:46:06 nonaka Exp $");
33 33
34#include "hyperv.h" 34#include "hyperv.h"
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/systm.h> 37#include <sys/systm.h>
38#include <sys/kernel.h> 38#include <sys/kernel.h>
39#include <sys/bus.h> 39#include <sys/bus.h>
40#include <sys/kmem.h> 40#include <sys/kmem.h>
41 41
42#include <dev/hyperv/hypervreg.h> 42#include <dev/hyperv/hypervreg.h>
43#include <dev/hyperv/hypervvar.h> 43#include <dev/hyperv/hypervvar.h>
44 44
45hyperv_tc64_t hyperv_tc64; 45hyperv_tc64_t hyperv_tc64;
46 46
47int hyperv_nullop(void); 47int hyperv_nullop(void);
48void hyperv_voidop(void); 48void hyperv_voidop(void);
49uint64_t hyperv_hypercall_error(uint64_t, paddr_t, paddr_t); 49uint64_t hyperv_hypercall_error(uint64_t, paddr_t, paddr_t);
50 50
51__weak_alias(hyperv_hypercall, hyperv_hypercall_error); 51__weak_alias(hyperv_hypercall, hyperv_hypercall_error);
52__weak_alias(hyperv_hypercall_enabled, hyperv_nullop); 52__weak_alias(hyperv_hypercall_enabled, hyperv_nullop);
53__weak_alias(hyperv_synic_supported, hyperv_nullop); 53__weak_alias(hyperv_synic_supported, hyperv_nullop);
54__weak_alias(hyperv_is_gen1, hyperv_nullop); 54__weak_alias(hyperv_is_gen1, hyperv_nullop);
55__weak_alias(hyperv_set_event_proc, hyperv_voidop); 55__weak_alias(hyperv_set_event_proc, hyperv_voidop);
56__weak_alias(hyperv_set_message_proc, hyperv_voidop); 56__weak_alias(hyperv_set_message_proc, hyperv_voidop);
57__weak_alias(hyperv_send_eom, hyperv_voidop); 57__weak_alias(hyperv_send_eom, hyperv_voidop);
58__weak_alias(hyperv_intr, hyperv_voidop); 58__weak_alias(hyperv_intr, hyperv_voidop);
59__weak_alias(vmbus_init_interrupts_md, hyperv_voidop); 59__weak_alias(vmbus_init_interrupts_md, hyperv_voidop);
60__weak_alias(vmbus_deinit_interrupts_md, hyperv_voidop); 60__weak_alias(vmbus_deinit_interrupts_md, hyperv_voidop);
61__weak_alias(vmbus_init_synic_md, hyperv_voidop); 61__weak_alias(vmbus_init_synic_md, hyperv_voidop);
62__weak_alias(vmbus_deinit_synic_md, hyperv_voidop); 62__weak_alias(vmbus_deinit_synic_md, hyperv_voidop);
63 63
64int 64int
65hyperv_nullop(void) 65hyperv_nullop(void)
66{ 66{
67 return 0; 67 return 0;
68} 68}
69 69
70void 70void
71hyperv_voidop(void) 71hyperv_voidop(void)
72{ 72{
73} 73}
74 74
75uint64_t 75uint64_t
76hyperv_hypercall_error(uint64_t control, paddr_t in_paddr, paddr_t out_paddr) 76hyperv_hypercall_error(uint64_t control, paddr_t in_paddr, paddr_t out_paddr)
77{ 77{
78 return ~HYPERCALL_STATUS_SUCCESS; 78 return ~HYPERCALL_STATUS_SUCCESS;
79} 79}
80 80
81uint64_t 81uint64_t
82hyperv_hypercall_post_message(paddr_t msg) 82hyperv_hypercall_post_message(paddr_t msg)
83{ 83{
84 84
85 return hyperv_hypercall(HYPERCALL_POST_MESSAGE, msg, 0); 85 return hyperv_hypercall(HYPERCALL_POST_MESSAGE, msg, 0);
86} 86}
87 87
88uint64_t 88uint64_t
89hyperv_hypercall_signal_event(paddr_t monprm) 89hyperv_hypercall_signal_event(paddr_t monprm)
90{ 90{
91 91
92 return hyperv_hypercall(HYPERCALL_SIGNAL_EVENT, monprm, 0); 92 return hyperv_hypercall(HYPERCALL_SIGNAL_EVENT, monprm, 0);
93} 93}
94 94
95int 95int
96hyperv_guid2str(const struct hyperv_guid *guid, char *buf, size_t sz) 96hyperv_guid2str(const struct hyperv_guid *guid, char *buf, size_t sz)
97{ 97{
98 const uint8_t *d = guid->hv_guid; 98 const uint8_t *d = guid->hv_guid;
99 99
100 return snprintf(buf, sz, "%02x%02x%02x%02x-" 100 return snprintf(buf, sz, "%02x%02x%02x%02x-"
101 "%02x%02x-%02x%02x-%02x%02x-" 101 "%02x%02x-%02x%02x-%02x%02x-"
102 "%02x%02x%02x%02x%02x%02x", 102 "%02x%02x%02x%02x%02x%02x",
103 d[3], d[2], d[1], d[0], 103 d[3], d[2], d[1], d[0],
104 d[5], d[4], d[7], d[6], d[8], d[9], 104 d[5], d[4], d[7], d[6], d[8], d[9],
105 d[10], d[11], d[12], d[13], d[14], d[15]); 105 d[10], d[11], d[12], d[13], d[14], d[15]);
106} 106}
107 107
108/* 108/*
109 * Hyper-V bus_dma utilities. 109 * Hyper-V bus_dma utilities.
110 */ 110 */
111void * 111void *
112hyperv_dma_alloc(bus_dma_tag_t dmat, struct hyperv_dma *dma, bus_size_t size, 112hyperv_dma_alloc(bus_dma_tag_t dmat, struct hyperv_dma *dma, bus_size_t size,
113 bus_size_t alignment, bus_size_t boundary, int nsegs) 113 bus_size_t alignment, bus_size_t boundary, int nsegs)
114{ 114{
115 const int kmemflags = cold ? KM_NOSLEEP : KM_SLEEP; 115 const int kmemflags = cold ? KM_NOSLEEP : KM_SLEEP;
116 const int dmaflags = cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK; 116 const int dmaflags = cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
117 int rseg, error; 117 int rseg, error;
118 118
119 KASSERT(dma != NULL); 119 KASSERT(dma != NULL);
120 KASSERT(dma->segs == NULL); 120 KASSERT(dma->segs == NULL);
121 KASSERT(nsegs > 0); 121 KASSERT(nsegs > 0);
122 122
123 dma->segs = kmem_zalloc(sizeof(*dma->segs) * nsegs, kmemflags); 123 dma->segs = kmem_zalloc(sizeof(*dma->segs) * nsegs, kmemflags);
124 if (dma->segs == NULL) 124 if (dma->segs == NULL)
125 return NULL; 125 return NULL;
126 126
127 dma->nsegs = nsegs; 127 dma->nsegs = nsegs;
128 128
129 error = bus_dmamem_alloc(dmat, size, alignment, boundary, dma->segs, 129 error = bus_dmamem_alloc(dmat, size, alignment, boundary, dma->segs,
130 nsegs, &rseg, dmaflags); 130 nsegs, &rseg, dmaflags);
131 if (error) { 131 if (error) {
132 printf("%s: bus_dmamem_alloc failed: error=%d\n", 132 printf("%s: bus_dmamem_alloc failed: error=%d\n",
133 __func__, error); 133 __func__, error);
134 goto fail1; 134 goto fail1;
135 } 135 }
136 error = bus_dmamem_map(dmat, dma->segs, rseg, size, &dma->addr, 136 error = bus_dmamem_map(dmat, dma->segs, rseg, size, &dma->addr,
137 dmaflags); 137 dmaflags);
138 if (error) { 138 if (error) {
139 printf("%s: bus_dmamem_map failed: error=%d\n", 139 printf("%s: bus_dmamem_map failed: error=%d\n",
140 __func__, error); 140 __func__, error);
141 goto fail2; 141 goto fail2;
142 } 142 }
143 error = bus_dmamap_create(dmat, size, rseg, size, boundary, dmaflags, 143 error = bus_dmamap_create(dmat, size, rseg, size, boundary, dmaflags,
144 &dma->map); 144 &dma->map);
145 if (error) { 145 if (error) {
146 printf("%s: bus_dmamap_create failed: error=%d\n", 146 printf("%s: bus_dmamap_create failed: error=%d\n",
147 __func__, error); 147 __func__, error);
148 goto fail3; 148 goto fail3;
149 } 149 }
150 error = bus_dmamap_load(dmat, dma->map, dma->addr, size, NULL, 150 error = bus_dmamap_load(dmat, dma->map, dma->addr, size, NULL,
151 BUS_DMA_READ | BUS_DMA_WRITE | dmaflags); 151 BUS_DMA_READ | BUS_DMA_WRITE | dmaflags);
152 if (error) { 152 if (error) {
153 printf("%s: bus_dmamap_load failed: error=%d\n", 153 printf("%s: bus_dmamap_load failed: error=%d\n",
154 __func__, error); 154 __func__, error);
155 goto fail4; 155 goto fail4;
156 } 156 }
157 157
 158 memset(dma->addr, 0, dma->map->dm_mapsize);
 159 bus_dmamap_sync(dmat, dma->map, 0, dma->map->dm_mapsize,
 160 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 161
158 return dma->addr; 162 return dma->addr;
159 163
160fail4: bus_dmamap_destroy(dmat, dma->map); 164fail4: bus_dmamap_destroy(dmat, dma->map);
161fail3: bus_dmamem_unmap(dmat, dma->addr, size); 165fail3: bus_dmamem_unmap(dmat, dma->addr, size);
162 dma->addr = NULL; 166 dma->addr = NULL;
163fail2: bus_dmamem_free(dmat, dma->segs, rseg); 167fail2: bus_dmamem_free(dmat, dma->segs, rseg);
164fail1: kmem_free(dma->segs, sizeof(*dma->segs) * nsegs); 168fail1: kmem_free(dma->segs, sizeof(*dma->segs) * nsegs);
165 dma->segs = NULL; 169 dma->segs = NULL;
166 dma->nsegs = 0; 170 dma->nsegs = 0;
167 return NULL; 171 return NULL;
168} 172}
169 173
170void 174void
171hyperv_dma_free(bus_dma_tag_t dmat, struct hyperv_dma *dma) 175hyperv_dma_free(bus_dma_tag_t dmat, struct hyperv_dma *dma)
172{ 176{
173 bus_size_t size = dma->map->dm_mapsize; 177 bus_size_t size = dma->map->dm_mapsize;
174 int rsegs = dma->map->dm_nsegs; 178 int rsegs = dma->map->dm_nsegs;
175 179
176 bus_dmamap_unload(dmat, dma->map); 180 bus_dmamap_unload(dmat, dma->map);
177 bus_dmamap_destroy(dmat, dma->map); 181 bus_dmamap_destroy(dmat, dma->map);
178 bus_dmamem_unmap(dmat, dma->addr, size); 182 bus_dmamem_unmap(dmat, dma->addr, size);
179 dma->addr = NULL; 183 dma->addr = NULL;
180 bus_dmamem_free(dmat, dma->segs, rsegs); 184 bus_dmamem_free(dmat, dma->segs, rsegs);
181 kmem_free(dma->segs, sizeof(*dma->segs) * dma->nsegs); 185 kmem_free(dma->segs, sizeof(*dma->segs) * dma->nsegs);
182 dma->segs = NULL; 186 dma->segs = NULL;
183 dma->nsegs = 0; 187 dma->nsegs = 0;
184} 188}

cvs diff -r1.5 -r1.6 src/sys/dev/hyperv/vmbus.c (switch to unified diff)

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