rotary: rewrite driver implementation
authorSeokYeon Hwang <syeon.hwang@samsung.com>
Thu, 23 Jun 2016 04:16:46 +0000 (13:16 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Tue, 28 Jun 2016 02:02:43 +0000 (11:02 +0900)
Change-Id: I734e833ac3b4af76ddb4f9d6a9e06fdbc95049a9
Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
drivers/maru/maru_virtio_rotary.c
drivers/maru/maru_virtio_touchscreen.c

index 73056d0316e3ebb857e5b7d8340f48512fadb94a..6e193e198294ed1b1a3e15e69d88bc05f932a956 100644 (file)
@@ -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");
 }
 
index 1e5650eb69a4b2437ebbbe8b25e0c4ade83e01b9..83b83c05b52cbc29d26f8e18efe5203d498e72e2 100644 (file)
@@ -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 */