|
@@ -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,
|