2 * Copyright (c) 2009-2012,2016 Microsoft Corp.
3 * Copyright (c) 2012 NetApp Inc.
4 * Copyright (c) 2012 Citrix Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice unmodified, this list of conditions, and the following
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/param.h>
30 #include <sys/kernel.h>
31 #include <sys/malloc.h>
32 #include <sys/systm.h>
34 #include <sys/mutex.h>
35 #include <machine/bus.h>
36 #include <machine/atomic.h>
38 #include <vm/vm_param.h>
41 #include <dev/hyperv/vmbus/hv_vmbus_priv.h>
42 #include <dev/hyperv/vmbus/hyperv_reg.h>
43 #include <dev/hyperv/vmbus/vmbus_reg.h>
44 #include <dev/hyperv/vmbus/vmbus_var.h>
47 vmbus_event_flags_proc(struct vmbus_softc *sc, volatile u_long *event_flags,
52 for (f = 0; f < flag_cnt; ++f) {
57 if (event_flags[f] == 0)
60 flags = atomic_swap_long(&event_flags[f], 0);
61 rel_id_base = f << VMBUS_EVTFLAG_SHIFT;
63 while ((bit = ffsl(flags)) != 0) {
64 struct hv_vmbus_channel *channel;
67 --bit; /* NOTE: ffsl is 1-based */
68 flags &= ~(1UL << bit);
70 rel_id = rel_id_base + bit;
71 channel = sc->vmbus_chmap[rel_id];
73 /* if channel is closed or closing */
74 if (channel == NULL || channel->rxq == NULL)
77 if (channel->batched_reading)
78 hv_ring_buffer_read_begin(&channel->inbound);
79 taskqueue_enqueue(channel->rxq, &channel->channel_task);
85 vmbus_event_proc(struct vmbus_softc *sc, int cpu)
87 struct vmbus_evtflags *eventf;
90 * On Host with Win8 or above, the event page can be checked directly
91 * to get the id of the channel that has the pending interrupt.
93 eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE;
94 vmbus_event_flags_proc(sc, eventf->evt_flags,
95 VMBUS_PCPU_GET(sc, event_flags_cnt, cpu));
99 vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu)
101 struct vmbus_evtflags *eventf;
103 eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE;
104 if (atomic_testandclear_long(&eventf->evt_flags[0], 0)) {
105 vmbus_event_flags_proc(sc, sc->vmbus_rx_evtflags,
106 VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT);
111 vmbus_on_channel_open(const struct hv_vmbus_channel *chan)
113 volatile int *flag_cnt_ptr;
116 flag_cnt = (chan->offer_msg.child_rel_id / VMBUS_EVTFLAG_LEN) + 1;
117 flag_cnt_ptr = VMBUS_PCPU_PTR(chan->vmbus_sc, event_flags_cnt,
123 old_flag_cnt = *flag_cnt_ptr;
124 if (old_flag_cnt >= flag_cnt)
126 if (atomic_cmpset_int(flag_cnt_ptr, old_flag_cnt, flag_cnt)) {
128 printf("VMBUS: channel%u update "
129 "cpu%d flag_cnt to %d\n",
130 chan->offer_msg.child_rel_id,
131 chan->target_cpu, flag_cnt);