staticvoid set_event(struct vmbus_channel *channel, s32 irq_state)
{
channel->inbound.ring_buffer->interrupt_mask = !irq_state; if (!channel->offermsg.monitor_allocated && irq_state) { /* MB is needed for host to see the interrupt mask first */
virt_mb();
vmbus_set_event(channel);
}
}
/* Function used for mmap of ring buffer sysfs interface. *Theringbufferisallocatedascontiguousmemorybyvmbus_open
*/ staticint
hv_uio_ring_mmap(struct vmbus_channel *channel, struct vm_area_struct *vma)
{ void *ring_buffer = page_address(channel->ringbuffer_page);
if (channel->state != CHANNEL_OPENED_STATE) return -ENODEV;
/* Callback from VMBUS subsystem when new channel created. */ staticvoid
hv_uio_new_channel(struct vmbus_channel *new_sc)
{ struct hv_device *hv_dev = new_sc->primary_channel->device_obj; struct device *device = &hv_dev->device; const size_t ring_bytes = SZ_2M; int ret;
/* Create host communication ring */
ret = vmbus_open(new_sc, ring_bytes, ring_bytes, NULL, 0,
hv_uio_channel_cb, new_sc); if (ret) {
dev_err(device, "vmbus_open subchannel failed: %d\n", ret); return;
}
set_channel_read_mode(new_sc, HV_CALL_ISR);
ret = hv_create_ring_sysfs(new_sc, hv_uio_ring_mmap); if (ret) {
dev_err(device, "sysfs create ring bin file failed; %d\n", ret);
vmbus_close(new_sc);
}
}
/* free the reserved buffers for send and receive */ staticvoid
hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)
{ if (pdata->send_gpadl.gpadl_handle) {
vmbus_teardown_gpadl(dev->channel, &pdata->send_gpadl); if (!pdata->send_gpadl.decrypted)
vfree(pdata->send_buf);
}
if (pdata->recv_gpadl.gpadl_handle) {
vmbus_teardown_gpadl(dev->channel, &pdata->recv_gpadl); if (!pdata->recv_gpadl.decrypted)
vfree(pdata->recv_buf);
}
}
/* VMBus primary channel is opened on first use */ staticint
hv_uio_open(struct uio_info *info, struct inode *inode)
{ struct hv_uio_private_data *pdata
= container_of(info, struct hv_uio_private_data, info); struct hv_device *dev = pdata->device; int ret;
if (atomic_inc_return(&pdata->refcnt) != 1) return0;
if (channel->device_id == HV_NIC) {
pdata->recv_buf = vzalloc(RECV_BUFFER_SIZE); if (!pdata->recv_buf) {
ret = -ENOMEM; goto fail_free_ring;
}
ret = vmbus_establish_gpadl(channel, pdata->recv_buf,
RECV_BUFFER_SIZE, &pdata->recv_gpadl); if (ret) { if (!pdata->recv_gpadl.decrypted)
vfree(pdata->recv_buf); goto fail_close;
}
/* put Global Physical Address Label in name */
snprintf(pdata->recv_name, sizeof(pdata->recv_name), "recv:%u", pdata->recv_gpadl.gpadl_handle);
pdata->info.mem[RECV_BUF_MAP].name = pdata->recv_name;
pdata->info.mem[RECV_BUF_MAP].addr = (uintptr_t)pdata->recv_buf;
pdata->info.mem[RECV_BUF_MAP].size = RECV_BUFFER_SIZE;
pdata->info.mem[RECV_BUF_MAP].memtype = UIO_MEM_VIRTUAL;
pdata->send_buf = vzalloc(SEND_BUFFER_SIZE); if (!pdata->send_buf) {
ret = -ENOMEM; goto fail_close;
}
ret = vmbus_establish_gpadl(channel, pdata->send_buf,
SEND_BUFFER_SIZE, &pdata->send_gpadl); if (ret) { if (!pdata->send_gpadl.decrypted)
vfree(pdata->send_buf); goto fail_close;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.