diff options
author | SeokYeon Hwang <syeon.hwang@samsung.com> | 2016-06-23 13:16:46 +0900 |
---|---|---|
committer | SeokYeon Hwang <syeon.hwang@samsung.com> | 2016-06-28 11:04:14 +0900 |
commit | 0039a6ec682bb855b8e4ff01a55bc74a73c14fd2 (patch) | |
tree | 41768027a0d963f55c544965a225172a854f7f6f | |
parent | 37bd14836f536df795a70fb8dab279d8da437d93 (diff) | |
download | emulator-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.c | 139 | ||||
-rw-r--r-- | drivers/maru/maru_virtio_touchscreen.c | 1 |
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 */ |