Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/vmbus/hv_channel.c
Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <dev/hyperv/vmbus/hv_vmbus_priv.h> | #include <dev/hyperv/vmbus/hv_vmbus_priv.h> | ||||
#include <dev/hyperv/vmbus/hyperv_var.h> | #include <dev/hyperv/vmbus/hyperv_var.h> | ||||
#include <dev/hyperv/vmbus/vmbus_reg.h> | #include <dev/hyperv/vmbus/vmbus_reg.h> | ||||
#include <dev/hyperv/vmbus/vmbus_var.h> | #include <dev/hyperv/vmbus/vmbus_var.h> | ||||
static void vmbus_channel_set_event(hv_vmbus_channel* channel); | static void vmbus_channel_set_event(hv_vmbus_channel* channel); | ||||
static void VmbusProcessChannelEvent(void* channel, int pending); | |||||
static void vmbus_chan_update_evtflagcnt(struct vmbus_softc *, | static void vmbus_chan_update_evtflagcnt(struct vmbus_softc *, | ||||
const struct hv_vmbus_channel *); | const struct hv_vmbus_channel *); | ||||
static void vmbus_chan_task(void *, int); | |||||
static void vmbus_chan_task_nobatch(void *, int); | |||||
/** | /** | ||||
* @brief Trigger an event notification on the specified channel | * @brief Trigger an event notification on the specified channel | ||||
*/ | */ | ||||
static void | static void | ||||
vmbus_channel_set_event(hv_vmbus_channel *channel) | vmbus_channel_set_event(hv_vmbus_channel *channel) | ||||
{ | { | ||||
struct vmbus_softc *sc = channel->vmbus_sc; | struct vmbus_softc *sc = channel->vmbus_sc; | ||||
▲ Show 20 Lines • Show All 143 Lines • ▼ Show 20 Lines | hv_vmbus_channel_open( | ||||
new_channel->on_channel_callback = pfn_on_channel_callback; | new_channel->on_channel_callback = pfn_on_channel_callback; | ||||
new_channel->channel_callback_context = context; | new_channel->channel_callback_context = context; | ||||
vmbus_chan_update_evtflagcnt(sc, new_channel); | vmbus_chan_update_evtflagcnt(sc, new_channel); | ||||
new_channel->rxq = VMBUS_PCPU_GET(new_channel->vmbus_sc, event_tq, | new_channel->rxq = VMBUS_PCPU_GET(new_channel->vmbus_sc, event_tq, | ||||
new_channel->target_cpu); | new_channel->target_cpu); | ||||
TASK_INIT(&new_channel->channel_task, 0, VmbusProcessChannelEvent, new_channel); | if (new_channel->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD) { | ||||
TASK_INIT(&new_channel->channel_task, 0, | |||||
vmbus_chan_task, new_channel); | |||||
} else { | |||||
TASK_INIT(&new_channel->channel_task, 0, | |||||
vmbus_chan_task_nobatch, new_channel); | |||||
} | |||||
/* Allocate the ring buffer */ | /* Allocate the ring buffer */ | ||||
out = contigmalloc((send_ring_buffer_size + recv_ring_buffer_size), | out = contigmalloc((send_ring_buffer_size + recv_ring_buffer_size), | ||||
M_DEVBUF, M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); | M_DEVBUF, M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); | ||||
KASSERT(out != NULL, | KASSERT(out != NULL, | ||||
("Error VMBUS: contigmalloc failed to allocate Ring Buffer!")); | ("Error VMBUS: contigmalloc failed to allocate Ring Buffer!")); | ||||
if (out == NULL) | if (out == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
▲ Show 20 Lines • Show All 616 Lines • ▼ Show 20 Lines | hv_vmbus_channel_recv_packet_raw( | ||||
*request_id = desc.transaction_id; | *request_id = desc.transaction_id; | ||||
/* Copy over the entire packet to the user buffer */ | /* Copy over the entire packet to the user buffer */ | ||||
ret = hv_ring_buffer_read(&channel->inbound, buffer, packetLen, 0); | ret = hv_ring_buffer_read(&channel->inbound, buffer, packetLen, 0); | ||||
return (0); | return (0); | ||||
} | } | ||||
/** | |||||
* Process a channel event notification | |||||
*/ | |||||
static void | static void | ||||
VmbusProcessChannelEvent(void* context, int pending) | vmbus_chan_task(void *xchan, int pending __unused) | ||||
{ | { | ||||
struct hv_vmbus_channel *chan = xchan; | |||||
void (*callback)(void *); | |||||
void* arg; | void *arg; | ||||
uint32_t bytes_to_read; | |||||
hv_vmbus_channel* channel = (hv_vmbus_channel*)context; | |||||
bool is_batched_reading = false; | |||||
if (channel->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD) | arg = chan->channel_callback_context; | ||||
is_batched_reading = true; | callback = chan->on_channel_callback; | ||||
arg = channel->channel_callback_context; | |||||
/* | /* | ||||
* Optimize host to guest signaling by ensuring: | * Optimize host to guest signaling by ensuring: | ||||
* 1. While reading the channel, we disable interrupts from | * 1. While reading the channel, we disable interrupts from | ||||
* host. | * host. | ||||
* 2. Ensure that we process all posted messages from the host | * 2. Ensure that we process all posted messages from the host | ||||
* before returning from this callback. | * before returning from this callback. | ||||
* 3. Once we return, enable signaling from the host. Once this | * 3. Once we return, enable signaling from the host. Once this | ||||
* state is set we check to see if additional packets are | * state is set we check to see if additional packets are | ||||
* available to read. In this case we repeat the process. | * available to read. In this case we repeat the process. | ||||
* | |||||
* NOTE: Interrupt has been disabled in the ISR. | |||||
*/ | */ | ||||
do { | for (;;) { | ||||
if (is_batched_reading) | uint32_t left; | ||||
hv_ring_buffer_read_begin(&channel->inbound); | |||||
channel->on_channel_callback(arg); | callback(arg); | ||||
if (is_batched_reading) | left = hv_ring_buffer_read_end(&chan->inbound); | ||||
bytes_to_read = | if (left == 0) { | ||||
hv_ring_buffer_read_end(&channel->inbound); | /* No more data in RX bufring; done */ | ||||
else | break; | ||||
bytes_to_read = 0; | } | ||||
} while (is_batched_reading && (bytes_to_read != 0)); | hv_ring_buffer_read_begin(&chan->inbound); | ||||
} | |||||
} | |||||
static void | |||||
vmbus_chan_task_nobatch(void *xchan, int pending __unused) | |||||
{ | |||||
struct hv_vmbus_channel *chan = xchan; | |||||
chan->on_channel_callback(chan->channel_callback_context); | |||||
} | } | ||||
static __inline void | static __inline void | ||||
vmbus_event_flags_proc(struct vmbus_softc *sc, volatile u_long *event_flags, | vmbus_event_flags_proc(struct vmbus_softc *sc, volatile u_long *event_flags, | ||||
int flag_cnt) | int flag_cnt) | ||||
{ | { | ||||
int f; | int f; | ||||
▲ Show 20 Lines • Show All 85 Lines • Show Last 20 Lines |