Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7d21464 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by Greg Kroah-Hartman
Browse files

uio_hv_generic: create send and receive buffers



Map in receive and send buffers for networking in UIO device.
These buffers are special and need to be setup by kernel
API's; userspace can not do it.

Signed-off-by: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c5702d1b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -702,6 +702,8 @@ The vmbus device regions are mapped into uio device resources:
    0) Channel ring buffers: guest to host and host to guest
    1) Guest to host interrupt signalling pages
    2) Guest to host monitor page
    3) Network receive buffer region
    4) Network send buffer region

Further information
===================
+69 −2
Original line number Diff line number Diff line
@@ -39,6 +39,10 @@
#define DRIVER_AUTHOR	"Stephen Hemminger <sthemmin at microsoft.com>"
#define DRIVER_DESC	"Generic UIO driver for VMBus devices"

#define HV_RING_SIZE	 512	/* pages */
#define SEND_BUFFER_SIZE (15 * 1024 * 1024)
#define RECV_BUFFER_SIZE (15 * 1024 * 1024)

/*
 * List of resources to be mapped to user space
 * can be extended up to MAX_UIO_MAPS(5) items
@@ -47,13 +51,21 @@ enum hv_uio_map {
	TXRX_RING_MAP = 0,
	INT_PAGE_MAP,
	MON_PAGE_MAP,
	RECV_BUF_MAP,
	SEND_BUF_MAP
};

#define HV_RING_SIZE	512

struct hv_uio_private_data {
	struct uio_info info;
	struct hv_device *device;

	void	*recv_buf;
	u32	recv_gpadl;
	char	recv_name[32];	/* "recv_4294967295" */

	void	*send_buf;
	u32	send_gpadl;
	char	send_name[32];
};

/*
@@ -91,6 +103,19 @@ static void hv_uio_channel_cb(void *context)
	uio_event_notify(&pdata->info);
}


static void
hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)
{
	if (pdata->send_gpadl)
		vmbus_teardown_gpadl(dev->channel, pdata->send_gpadl);
	vfree(pdata->send_buf);

	if (pdata->recv_gpadl)
		vmbus_teardown_gpadl(dev->channel, pdata->recv_gpadl);
	vfree(pdata->recv_buf);
}

static int
hv_uio_probe(struct hv_device *dev,
	     const struct hv_vmbus_device_id *dev_id)
@@ -137,6 +162,46 @@ hv_uio_probe(struct hv_device *dev,
	pdata->info.mem[MON_PAGE_MAP].size = PAGE_SIZE;
	pdata->info.mem[MON_PAGE_MAP].memtype = UIO_MEM_LOGICAL;

	pdata->recv_buf = vzalloc(RECV_BUFFER_SIZE);
	if (pdata->recv_buf == NULL) {
		ret = -ENOMEM;
		goto fail_close;
	}

	ret = vmbus_establish_gpadl(dev->channel, pdata->recv_buf,
				    RECV_BUFFER_SIZE, &pdata->recv_gpadl);
	if (ret)
		goto fail_close;

	/* put Global Physical Address Label in name */
	snprintf(pdata->recv_name, sizeof(pdata->recv_name),
		 "recv:%u", pdata->recv_gpadl);
	pdata->info.mem[RECV_BUF_MAP].name = pdata->recv_name;
	pdata->info.mem[RECV_BUF_MAP].addr
		= (phys_addr_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 == NULL) {
		ret = -ENOMEM;
		goto fail_close;
	}

	ret = vmbus_establish_gpadl(dev->channel, pdata->send_buf,
				    SEND_BUFFER_SIZE, &pdata->send_gpadl);
	if (ret)
		goto fail_close;

	snprintf(pdata->send_name, sizeof(pdata->send_name),
		 "send:%u", pdata->send_gpadl);
	pdata->info.mem[SEND_BUF_MAP].name = pdata->send_name;
	pdata->info.mem[SEND_BUF_MAP].addr
		= (phys_addr_t)pdata->send_buf;
	pdata->info.mem[SEND_BUF_MAP].size = SEND_BUFFER_SIZE;
	pdata->info.mem[SEND_BUF_MAP].memtype = UIO_MEM_VIRTUAL;

	pdata->info.priv = pdata;
	pdata->device = dev;

@@ -151,6 +216,7 @@ hv_uio_probe(struct hv_device *dev,
	return 0;

fail_close:
	hv_uio_cleanup(dev, pdata);
	vmbus_close(dev->channel);
fail:
	kfree(pdata);
@@ -167,6 +233,7 @@ hv_uio_remove(struct hv_device *dev)
		return 0;

	uio_unregister_device(&pdata->info);
	hv_uio_cleanup(dev, pdata);
	hv_set_drvdata(dev, NULL);
	vmbus_close(dev->channel);
	kfree(pdata);