summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeokYeon Hwang <syeon.hwang@samsung.com>2016-06-23 13:16:46 +0900
committerSeokYeon Hwang <syeon.hwang@samsung.com>2016-06-28 11:04:14 +0900
commit0039a6ec682bb855b8e4ff01a55bc74a73c14fd2 (patch)
tree41768027a0d963f55c544965a225172a854f7f6f
parent37bd14836f536df795a70fb8dab279d8da437d93 (diff)
downloademulator-kernel-0039a6ec682bb855b8e4ff01a55bc74a73c14fd2.tar.gz
emulator-kernel-0039a6ec682bb855b8e4ff01a55bc74a73c14fd2.tar.bz2
emulator-kernel-0039a6ec682bb855b8e4ff01a55bc74a73c14fd2.zip
rotary: rewrite driver implementation
Change-Id: I734e833ac3b4af76ddb4f9d6a9e06fdbc95049a9 Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
-rw-r--r--drivers/maru/maru_virtio_rotary.c139
-rw-r--r--drivers/maru/maru_virtio_touchscreen.c1
2 files changed, 62 insertions, 78 deletions
diff --git a/drivers/maru/maru_virtio_rotary.c b/drivers/maru/maru_virtio_rotary.c
index 73056d0316e3..6e193e198294 100644
--- a/drivers/maru/maru_virtio_rotary.c
+++ b/drivers/maru/maru_virtio_rotary.c
@@ -4,8 +4,8 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
*
* Contact:
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
* Jinhyung Jo <jinhyung.jo@samsung.com>
- * Sangho Park <sangho1206.park@samsung.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -39,6 +39,8 @@
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
+#include "maru_virtio_device.h"
+
MODULE_LICENSE("GPL2");
MODULE_AUTHOR("Jinhyung Jo <jinhyung.jo@samsung.com>");
MODULE_DESCRIPTION("Emulator Virtio Rotary Driver");
@@ -47,26 +49,18 @@ MODULE_DESCRIPTION("Emulator Virtio Rotary Driver");
#define VR_LOG(log_level, fmt, ...) \
printk(log_level "%s: " fmt, DRIVER_NAME, ##__VA_ARGS__)
-#define ROTARY_EVENT_MAX 32
struct rotary_event {
int32_t delta;
int32_t type;
};
-#define ROTARY_EVENT_BUF_SIZE \
- (ROTARY_EVENT_MAX * sizeof(struct rotary_event))
-
struct virtio_rotary {
- struct virtio_device *vdev;
- struct virtqueue *vq;
- struct input_dev *idev;
- struct mutex mutex;
+ struct maru_virtio_device *mdev;
- struct rotary_event event[ROTARY_EVENT_MAX];
+ struct input_dev *idev;
+ struct rotary_event evtbuf[MAX_BUF_COUNT];
};
-struct virtio_rotary *vrtr;
-
static int last_pos; /* 0 ~ 360 */
static int last_detent;
@@ -84,6 +78,7 @@ typeof(n) _n = (n) % (div); \
_n; \
})
+/*
static int add_inbuf(struct virtqueue *vq, struct rotary_event *event)
{
struct scatterlist sg[1];
@@ -97,55 +92,47 @@ static int add_inbuf(struct virtqueue *vq, struct rotary_event *event)
return ret;
}
+*/
static int get_rotary_pos(int value)
{
return REMAINDER(value, 360);
}
-static void vq_rotary_handler(struct virtqueue *vq)
+static void vq_rotary_callback(struct virtqueue *vq)
{
int err = 0;
- struct rotary_event *data;
+ struct rotary_event *event;
unsigned int len = 0;
- size_t j, num_event;
-
- data = (struct rotary_event *)virtqueue_get_buf(vq, &len);
- if (!data) {
- VR_LOG(KERN_ERR, "there is no available buffer\n");
- return;
- }
+ struct virtio_rotary *vrtr = vq->vdev->priv;
+ struct maru_virtio_device *mdev = vrtr->mdev;
+ unsigned long flags;
- num_event = (size_t)len / sizeof(struct rotary_event);
- VR_LOG(KERN_DEBUG, "len(%u), num_event(%zu)\n", len, num_event);
-
- for (j = 0; j < num_event; j++) {
+ spin_lock_irqsave(&mdev->lock, flags);
+ while ((event = virtqueue_get_buf(mdev->vq, &len)) != NULL) {
int i = 0;
int pos = 0;
int value = 0;
- struct rotary_event event;
- memcpy(&event, &data[j],
- sizeof(struct rotary_event));
+ spin_unlock_irqrestore(&mdev->lock, flags);
- event.delta %= 360;
- if (event.delta == 0)
+ event->delta %= 360;
+ if (event->delta == 0)
continue;
- pos = get_rotary_pos(last_pos + event.delta);
+ pos = get_rotary_pos(last_pos + event->delta);
VR_LOG(KERN_DEBUG,
- "rotary event: idx(%zu), event.delta(%d), pos(%d)\n",
- j, event.delta, pos);
+ "rotary event: event.delta(%d), pos(%d)\n", event->delta, pos);
- for (i = 1; i <= abs(event.delta); i++) {
- value = (event.delta > 0) ? last_pos + i : last_pos - i;
+ for (i = 1; i <= abs(event->delta); i++) {
+ value = (event->delta > 0) ? last_pos + i : last_pos - i;
if ((value % DETENT_UNIT) == 0) {
input_report_rel(vrtr->idev, REL_WHEEL, 1);
input_sync(vrtr->idev);
if (get_rotary_pos(value) != last_detent) {
last_detent = get_rotary_pos(value);
- if (event.delta > 0) { /* CW */
+ if (event->delta > 0) { /* CW */
input_report_rel(vrtr->idev,
REL_WHEEL, 2);
} else { /* CCW */
@@ -160,18 +147,21 @@ static void vq_rotary_handler(struct virtqueue *vq)
VR_LOG(KERN_INFO,
"rotary event: delta(%d), detent(%d)\n",
- event.delta, last_detent);
+ event->delta, last_detent);
}
}
last_pos = pos;
- }
- err = add_inbuf(vrtr->vq, vrtr->event);
- if (err < 0) {
- VR_LOG(KERN_ERR, "failed to add buffer to virtqueue\n");
- return;
+ // add new buffer
+ spin_lock_irqsave(&mdev->lock, flags);
+ err = add_new_buf(mdev, event, sizeof(*event));
+ if (err < 0) {
+ printk(KERN_ERR "failed to add buffer\n");
+ }
}
- virtqueue_kick(vrtr->vq);
+
+ virtqueue_kick(mdev->vq);
+ spin_unlock_irqrestore(&mdev->lock, flags);
}
static int input_rotary_open(struct input_dev *dev)
@@ -188,6 +178,7 @@ static void input_rotary_close(struct input_dev *dev)
static int virtio_rotary_probe(struct virtio_device *vdev)
{
int ret = 0;
+ struct virtio_rotary *vrtr = vdev->priv;
if (vrtr) {
VR_LOG(KERN_ERR, "driver is already exist\n");
@@ -195,29 +186,21 @@ static int virtio_rotary_probe(struct virtio_device *vdev)
}
vdev->priv = vrtr = kzalloc(sizeof(struct virtio_rotary), GFP_KERNEL);
- if (!vrtr)
+ if (!vrtr) {
return -ENOMEM;
-
- vrtr->vdev = vdev;
- mutex_init(&vrtr->mutex);
-
- vrtr->vq = virtio_find_single_vq(vrtr->vdev,
- vq_rotary_handler,
- "maru-rotary-vq");
- if (IS_ERR(vrtr->vq)) {
- ret = PTR_ERR(vrtr->vq);
- kfree(vrtr);
- vdev->priv = NULL;
- return ret;
+ }
+ vrtr->mdev = kzalloc(sizeof(*vrtr->mdev), GFP_KERNEL);
+ if (!vrtr->mdev) {
+ ret = -ENOMEM;
+ goto err3;
}
/* register for input device */
vrtr->idev = input_allocate_device();
if (!vrtr->idev) {
VR_LOG(KERN_ERR, "failed to allocate a input device\n");
- kfree(vrtr);
- vdev->priv = NULL;
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err2;
}
vrtr->idev->name = DRIVER_NAME;
@@ -238,43 +221,45 @@ static int virtio_rotary_probe(struct virtio_device *vdev)
ret = input_register_device(vrtr->idev);
if (ret) {
VR_LOG(KERN_ERR, "failed to register a input device\n");
- input_free_device(vrtr->idev);
- kfree(vrtr);
- vdev->priv = NULL;
- return ret;
+ ret = -1;
+ goto err;
}
- ret = add_inbuf(vrtr->vq, vrtr->event);
- if (ret < 0) {
- VR_LOG(KERN_ERR, "failed to add buffer to virtqueue\n");
- input_unregister_device(vrtr->idev);
- input_free_device(vrtr->idev);
- kfree(vrtr);
- vdev->priv = NULL;
- return ret;
+ ret = init_virtio_device(vdev, vrtr->mdev, vq_rotary_callback,
+ vrtr->evtbuf, sizeof(struct rotary_event));
+ if (ret) {
+ goto err;
}
- VR_LOG(KERN_INFO, "driver probe done\n");
+ printk(KERN_INFO "virtio rotary driver is probed\n");
return 0;
+
+err:
+ input_free_device(vrtr->idev);
+err2:
+ kfree(vrtr->mdev);
+err3:
+ kfree(vrtr);
+ vdev->priv = NULL;
+ return ret;
}
static void virtio_rotary_remove(struct virtio_device *vdev)
{
+ struct virtio_rotary *vrtr = vdev->priv;
+
if (!vrtr) {
VR_LOG(KERN_ERR, "rotary instance is NULL\n");
return;
}
- vdev->config->reset(vdev);
- vdev->config->del_vqs(vdev);
-
input_unregister_device(vrtr->idev);
input_free_device(vrtr->idev);
+ deinit_virtio_device(vdev);
kfree(vrtr);
- vrtr = NULL;
- vdev->priv = NULL;
+
VR_LOG(KERN_INFO, "driver is removed\n");
}
diff --git a/drivers/maru/maru_virtio_touchscreen.c b/drivers/maru/maru_virtio_touchscreen.c
index 1e5650eb69a4..83b83c05b52c 100644
--- a/drivers/maru/maru_virtio_touchscreen.c
+++ b/drivers/maru/maru_virtio_touchscreen.c
@@ -190,7 +190,6 @@ static int virtio_touchscreen_probe(struct virtio_device *vdev)
unsigned long width = 0;
unsigned long height = 0;
int ret = 0;
-
struct virtio_touchscreen *vt;
/* init virtio */