From ccaa08359a390abd0f75a851cc9129047bcfb74c Mon Sep 17 00:00:00 2001 From: "syeon.hwang" Date: Thu, 13 Dec 2012 17:30:55 +0900 Subject: [PATCH] virtio-esm: Add missing source file Signed-off-by: SeokYeon Hwang --- drivers/maru/maru_virtio_esm.c | 261 +++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 drivers/maru/maru_virtio_esm.c diff --git a/drivers/maru/maru_virtio_esm.c b/drivers/maru/maru_virtio_esm.c new file mode 100644 index 000000000000..c776433c1e1f --- /dev/null +++ b/drivers/maru/maru_virtio_esm.c @@ -0,0 +1,261 @@ +/* + * Maru Virtio EmulatorStatusMedium Device Driver + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL2"); +MODULE_AUTHOR("SeokYeon Hwang "); +MODULE_DESCRIPTION("Emulator Virtio EmulatorStatusMedium Driver"); + +#define DRIVER_NAME "VirtIO EmulatorStatusMedium " +#define VESM_LOG(log_level, fmt, ...) \ + printk(log_level "%s: " fmt, DRIVER_NAME, ##__VA_ARGS__) + +struct progress_info +{ + uint16_t percentage; +}; + +struct virtio_esm +{ + struct virtio_device *vdev; + struct virtqueue *vq; + + struct progress_info progress; + struct scatterlist sg[1]; +}; + +static struct virtio_device_id id_table[] = { + { VIRTIO_ID_ESM, VIRTIO_DEV_ANY_ID }, + { 0 }, +}; + + +struct virtio_esm *vesm; + +static dev_t first; +static struct class *cl; +static struct cdev c_dev; + +static void vq_esm_callback(struct virtqueue *vq) +{ + int len = 0; + + VESM_LOG(KERN_DEBUG, "virtqueue callback.\n"); + // get buffer and drop it. + virtqueue_get_buf(vq, &len); +} + +static int esm_open(struct inode *i, struct file *f) +{ + VESM_LOG(KERN_DEBUG, "esm_open\n"); + return 0; +} + +static int esm_close(struct inode *i, struct file *f) +{ + VESM_LOG(KERN_DEBUG, "esm_close\n"); + return 0; +} + +static ssize_t esm_read(struct file *f, char __user *buf, size_t len, loff_t *off) +{ + VESM_LOG(KERN_DEBUG, "esm_read\n"); + return 0; +} + +static ssize_t esm_write(struct inode *i, const char __user *ubuf, size_t len, loff_t *off) +{ + int err = 0; + ssize_t ret = 0; + char buf[4]; + + if(vesm == NULL) { + VESM_LOG(KERN_ERR, "Device or driver is malfunction.\n"); + return 0; + } + + len = min((size_t)4, len); + + ret = copy_from_user(buf, ubuf, len); + if (ret) { + ret = -EFAULT; + return 0; + } + buf[len - 1] = '\0'; + + kstrtou16(buf, 10, &vesm->progress.percentage); + + VESM_LOG(KERN_DEBUG, "boot up progress is [%u] percent done.\n", vesm->progress.percentage); + + sg_init_one(vesm->sg, &vesm->progress, sizeof(vesm->progress)); + err = virtqueue_add_buf (vesm->vq, vesm->sg, 1, 0, &vesm->progress, GFP_ATOMIC); + if (err < 0) { + VESM_LOG(KERN_ERR, "%d\n", err); + VESM_LOG(KERN_ERR, "failed to add buffer to virtqueue.\n"); + return 0; + } + + virtqueue_kick(vesm->vq); + + VESM_LOG(KERN_DEBUG, "esm_write\n"); + return len; +} + +static struct file_operations esm_fops = +{ + .owner = THIS_MODULE, + .open = esm_open, + .release = esm_close, + .read = esm_read, + .write = esm_write, +}; + +static int virtio_esm_probe(struct virtio_device *vdev) +{ + int ret = 0; + + VESM_LOG(KERN_INFO, "driver is probed\n"); + + if(device_create(cl, NULL, first, NULL, "esm") == NULL) + { + class_destroy(cl); + unregister_chrdev_region(first, 1); + return -1; + } + + cdev_init(&c_dev, &esm_fops); + if(cdev_add(&c_dev, first, 1) == -1) + { + device_destroy(cl, first); + class_destroy(cl); + unregister_chrdev_region(first, 1); + return -1; + } + + vdev->priv = vesm = kmalloc(sizeof(struct virtio_esm), GFP_KERNEL); + if (!vesm) { + return -ENOMEM; + } + + vesm->vdev = vdev; + vesm->vq = virtio_find_single_vq(vesm->vdev, vq_esm_callback, "virtio-esm-vq"); + if (IS_ERR(vesm->vq)) { + ret = PTR_ERR(vesm->vq); + goto error1; + } + + memset(&vesm->progress, 0x00, sizeof(vesm->progress)); + + sg_set_buf(vesm->sg, &vesm->progress, sizeof(struct progress_info)); + + return 0; + +error1: + kfree(vesm); + vdev->priv = NULL; + + return ret; +} + +static void __devexit virtio_esm_remove(struct virtio_device *vdev) +{ + struct virtio_esm *vesm = vdev->priv; + + VESM_LOG(KERN_INFO, "driver is removed.\n"); + if (!vesm) { + VESM_LOG(KERN_ERR, "vesm is NULL.\n"); + return; + } + + vdev->config->reset(vdev); + vdev->config->del_vqs(vdev); + + kfree(vesm); + vesm = NULL; +} + +MODULE_DEVICE_TABLE(virtio, id_table); + +static struct virtio_driver virtio_esm_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + }, + .id_table = id_table, + .probe = virtio_esm_probe, + .remove = virtio_esm_remove, +#if 0 +#ifdef CONFIG_PM + .freeze = virtio_esm_freeze, + .restore = virtio_esm_restore, +#endif +#endif +}; + +static int __init virtio_esm_init(void) +{ + if(alloc_chrdev_region(&first, 0, 1, "virtio-esm") < 0) + { + return -1; + } + + if((cl = class_create(THIS_MODULE, "esm_chardrv")) == NULL) + { + unregister_chrdev_region(first, 1); + return -1; + } + + VESM_LOG(KERN_INFO, "driver is initialized.\n"); + return register_virtio_driver(&virtio_esm_driver); +} + +static void __exit virtio_esm_exit(void) +{ + cdev_del(&c_dev); + device_destroy(cl, first); + class_destroy(cl); + unregister_chrdev_region(first, 1); + unregister_virtio_driver(&virtio_esm_driver); + + VESM_LOG(KERN_INFO, "driver is destroyed.\n"); +} + +module_init(virtio_esm_init); +module_exit(virtio_esm_exit); -- 2.34.1