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

Commit 0a4dfa5d authored by Daniel De Graaf's avatar Daniel De Graaf Committed by Dmitry Torokhov
Browse files

Input: xen-kbdfront - add grant reference for shared page



Without a grant reference, full access to the domain's memory is
required to use the shared page. Add an additional parameter in
xenstore to allow grant mapping to be used.

Signed-off-by: default avatarDaniel De Graaf <dgdegra@tycho.nsa.gov>
Signed-off-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: default avatarIan Campbell <Ian.Campbell@eu.citrix.com>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 8c3c283e
Loading
Loading
Loading
Loading
+28 −11
Original line number Diff line number Diff line
@@ -11,12 +11,6 @@
 *  more details.
 */

/*
 * TODO:
 *
 * Switch to grant tables together with xen-fbfront.c.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
@@ -30,6 +24,8 @@
#include <xen/xen.h>
#include <xen/events.h>
#include <xen/page.h>
#include <xen/grant_table.h>
#include <xen/interface/grant_table.h>
#include <xen/interface/io/fbif.h>
#include <xen/interface/io/kbdif.h>
#include <xen/xenbus.h>
@@ -38,6 +34,7 @@ struct xenkbd_info {
	struct input_dev *kbd;
	struct input_dev *ptr;
	struct xenkbd_page *page;
	int gref;
	int irq;
	struct xenbus_device *xbdev;
	char phys[32];
@@ -122,6 +119,7 @@ static int __devinit xenkbd_probe(struct xenbus_device *dev,
	dev_set_drvdata(&dev->dev, info);
	info->xbdev = dev;
	info->irq = -1;
	info->gref = -1;
	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);

	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
@@ -232,15 +230,20 @@ static int xenkbd_connect_backend(struct xenbus_device *dev,
	int ret, evtchn;
	struct xenbus_transaction xbt;

	ret = gnttab_grant_foreign_access(dev->otherend_id,
	                                  virt_to_mfn(info->page), 0);
	if (ret < 0)
		return ret;
	info->gref = ret;

	ret = xenbus_alloc_evtchn(dev, &evtchn);
	if (ret)
		return ret;
		goto error_grant;
	ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
					0, dev->devicetype, info);
	if (ret < 0) {
		xenbus_free_evtchn(dev, evtchn);
		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
		return ret;
		goto error_evtchan;
	}
	info->irq = ret;

@@ -248,10 +251,13 @@ static int xenkbd_connect_backend(struct xenbus_device *dev,
	ret = xenbus_transaction_start(&xbt);
	if (ret) {
		xenbus_dev_fatal(dev, ret, "starting transaction");
		return ret;
		goto error_irqh;
	}
	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
			    virt_to_mfn(info->page));
	if (ret)
		goto error_xenbus;
	ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref);
	if (ret)
		goto error_xenbus;
	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
@@ -263,7 +269,7 @@ static int xenkbd_connect_backend(struct xenbus_device *dev,
		if (ret == -EAGAIN)
			goto again;
		xenbus_dev_fatal(dev, ret, "completing transaction");
		return ret;
		goto error_irqh;
	}

	xenbus_switch_state(dev, XenbusStateInitialised);
@@ -272,6 +278,14 @@ static int xenkbd_connect_backend(struct xenbus_device *dev,
 error_xenbus:
	xenbus_transaction_end(xbt, 1);
	xenbus_dev_fatal(dev, ret, "writing xenstore");
 error_irqh:
	unbind_from_irqhandler(info->irq, info);
	info->irq = -1;
 error_evtchan:
	xenbus_free_evtchn(dev, evtchn);
 error_grant:
	gnttab_end_foreign_access_ref(info->gref, 0);
	info->gref = -1;
	return ret;
}

@@ -280,6 +294,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *info)
	if (info->irq >= 0)
		unbind_from_irqhandler(info->irq, info);
	info->irq = -1;
	if (info->gref >= 0)
		gnttab_end_foreign_access_ref(info->gref, 0);
	info->gref = -1;
}

static void xenkbd_backend_changed(struct xenbus_device *dev,