Commit ce3d1536 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by Greg Kroah-Hartman

uio_hv_generic: fix subchannel ring mmap

The fault method of handling subchannel ring, did not work correctly
(it only worked for the first page).

Since ring buffer is physically contiguous, using the vm helper
function is simpler and handles more cases.

Fixes: 37b96a49 ("uio_hv_generic: support sub-channels")
Signed-off-by: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 135db384
......@@ -19,7 +19,7 @@
* # echo -n "ed963694-e847-4b2a-85af-bc9cfc11d6f3" \
* > /sys/bus/vmbus/drivers/uio_hv_generic/bind
*/
#define DEBUG 1
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/device.h>
......@@ -122,54 +122,23 @@ static void hv_uio_rescind(struct vmbus_channel *channel)
uio_event_notify(&pdata->info);
}
/*
* Handle fault when looking for sub channel ring buffer
* Subchannel ring buffer is same as resource 0 which is main ring buffer
* This is derived from uio_vma_fault
/* Sysfs API to allow mmap of the ring buffers
* The ring buffer is allocated as contiguous memory by vmbus_open
*/
static int hv_uio_vma_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
void *ring_buffer = vma->vm_private_data;
struct page *page;
void *addr;
addr = ring_buffer + (vmf->pgoff << PAGE_SHIFT);
page = virt_to_page(addr);
get_page(page);
vmf->page = page;
return 0;
}
static const struct vm_operations_struct hv_uio_vm_ops = {
.fault = hv_uio_vma_fault,
};
/* Sysfs API to allow mmap of the ring buffers */
static int hv_uio_ring_mmap(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct vmbus_channel *channel
= container_of(kobj, struct vmbus_channel, kobj);
unsigned long requested_pages, actual_pages;
if (vma->vm_end < vma->vm_start)
return -EINVAL;
struct hv_device *dev = channel->primary_channel->device_obj;
u16 q_idx = channel->offermsg.offer.sub_channel_index;
/* only allow 0 for now */
if (vma->vm_pgoff > 0)
return -EINVAL;
dev_dbg(&dev->device, "mmap channel %u pages %#lx at %#lx\n",
q_idx, vma_pages(vma), vma->vm_pgoff);
requested_pages = vma_pages(vma);
actual_pages = 2 * HV_RING_SIZE;
if (requested_pages > actual_pages)
return -EINVAL;
vma->vm_private_data = channel->ringbuffer_pages;
vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_ops = &hv_uio_vm_ops;
return 0;
return vm_iomap_memory(vma, virt_to_phys(channel->ringbuffer_pages),
channel->ringbuffer_pagecount << PAGE_SHIFT);
}
static const struct bin_attribute ring_buffer_bin_attr = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment