diff options
-rw-r--r-- | loopback_driver.c | 99 | ||||
-rw-r--r-- | loopback_driver.h | 4 |
2 files changed, 42 insertions, 61 deletions
diff --git a/loopback_driver.c b/loopback_driver.c index f271480..452726c 100644 --- a/loopback_driver.c +++ b/loopback_driver.c @@ -64,7 +64,7 @@ #include <linux/pagemap.h> -#include <linux/kfifo.h> +#include <linux/delay.h> /* Features */ MODULE_LICENSE("GPL v2"); @@ -104,6 +104,15 @@ const struct vring *global_vring; static int interrupt_cnt; static int notify_sent, notify_received; +/* Define a structure for your notify_list */ +struct notify_data { + uint32_t index; + struct list_head list; +}; +static LIST_HEAD(notify_list); +/* Define workqueues for notifications and interrupts */ +static struct workqueue_struct *notify_workqueue, *interrupt_workqueue; + static struct platform_device virtio_loopback_device = { .name = "loopback-transport", .id = -1, @@ -139,8 +148,6 @@ static struct loopback_device_data loopback_data[MAX_DEV]; unsigned long loopback_flags; #define IN_USE_BIT 0 -#define KFIFO_SIZE 1024 -static struct kfifo notify_queue; int32_t notified_vq_index; int notify_flag; int cur_ram_idx; @@ -315,28 +322,19 @@ static void vm_reset(struct virtio_device *vdev) write_adapter(0, VIRTIO_MMIO_STATUS, 4); } -static struct workqueue_struct *notify_workqueue, *interrupt_workqueue; static void async_work_handler(struct work_struct *work) { - int vq_index, ret; - - mutex_lock(¬ify_lock); + struct notify_data *entry, *tmp; mutex_lock(¬ify_q_lock); - ret = kfifo_get(¬ify_queue, &vq_index); - if (ret == 0) { - DBG("fifo is empty\n"); - DBG("kfifo_len -> %d\n", kfifo_len(¬ify_queue)); - mutex_unlock(¬ify_q_lock); - mutex_unlock(¬ify_lock); - return; - } + list_for_each_entry_safe(entry, tmp, ¬ify_list, list) { + pr_crit("notify_received: %d, VQ: %d\n", notify_received++, entry->index); + write_adapter(entry->index, VIRTIO_MMIO_QUEUE_NOTIFY, 4); + list_del(&entry->list); + kfree(entry); + } mutex_unlock(¬ify_q_lock); - DBG("notify_received: %d, VQ: %d\n", notify_received++, vq_index); - write_adapter(vq_index, VIRTIO_MMIO_QUEUE_NOTIFY, 4); - - mutex_unlock(¬ify_lock); } DECLARE_WORK(async_work, async_work_handler); @@ -344,31 +342,26 @@ DECLARE_WORK(async_work, async_work_handler); /* the notify function used when creating a virt queue */ static bool vm_notify(struct virtqueue *vq) { - int ret, prev_len, vq_index; + //uint32_t ret, prev_len, vq_index; + struct notify_data *data; /* * We write the queue's selector into * the notification register to signal * the other end */ mutex_lock(¬ify_q_lock); + pr_crit("vm_notify\n"); - prev_len = kfifo_len(¬ify_queue); - vq_index = vq->index; - - ret = kfifo_put(¬ify_queue, vq_index); - if (ret == 0) { - if (prev_len == kfifo_len(¬ify_queue)) { - DBG("fifo is full: len = %d\n", kfifo_len(¬ify_queue)); - DBG("kfifo_put failed with error: %d\n", ret); - mutex_unlock(¬ify_q_lock); - return false; - } - } + data = kmalloc(sizeof(struct notify_data), GFP_KERNEL); + data->index = vq->index; + INIT_LIST_HEAD(&data->list); + list_add_tail(&data->list, ¬ify_list); - DBG("ADD in kfifo: %d, VQ: %d\n", notify_sent++, vq_index); /* This doesn't make any difference in or out of the block */ - queue_work(notify_workqueue, &async_work); + if (!queue_work(notify_workqueue, &async_work)) { + pr_info("Fails to start work_queue, but no problem\n"); + } mutex_unlock(¬ify_q_lock); return true; @@ -384,7 +377,7 @@ static void vm_interrupt(struct work_struct *work) /* STATUS and ACK should ne done without any intermediate status change */ mutex_lock(&interrupt_lock); - DBG("interrupt_cnt: %d\n", interrupt_cnt++); + pr_crit("interrupt_cnt: %d\n", interrupt_cnt++); /* Read and acknowledge interrupts */ status = read_adapter(VIRTIO_MMIO_INTERRUPT_STATUS, 4); @@ -482,6 +475,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int in goto error_new_virtqueue; } + vq->num_max = num; + /* Activate the queue */ write_adapter(virtqueue_get_vring_size(vq), VIRTIO_MMIO_QUEUE_NUM, 4); if (vm_dev->version == 1) { @@ -953,8 +948,7 @@ int pf_mmap_vm_page(struct file *filp, struct vm_area_struct *vma) uint64_t size = (unsigned long)(vma->vm_end - vma->vm_start); uint64_t pfn = ((cur_ram_idx++) * 0x40000); - vma->vm_flags |= VM_PFNMAP; - + vm_flags_set(vma, VM_PFNMAP); add_share_mmap(filp, pfn, vma->vm_start, size); return 0; } @@ -984,7 +978,7 @@ int mmap_communication_shared_space(struct file *filp, struct vm_area_struct *vm uint64_t com_mmap_pfn = ((uint64_t)virt_to_phys(com_mmap_virt)) >> PAGE_SHIFT; int ret; - vma->vm_flags |= VM_RESERVED; + vm_flags_set(vma, VM_RESERVED); ret = remap_pfn_range(vma, vma->vm_start, com_mmap_pfn, size, vma->vm_page_prot); if (ret != 0) @@ -1128,15 +1122,12 @@ loff_t loopback_seek(struct file *file, loff_t offset, int whence) DBG("loopback seek function!\n"); switch (whence) { case SEEK_SET: - DBG("SEEK_SET\n"); new_pos = offset; break; case SEEK_CUR: - DBG("SEEK_CUR\n"); new_pos = file->f_pos + offset; break; case SEEK_END: - DBG("SEEK_END\n"); new_pos = file->f_inode->i_size; break; default: @@ -1174,7 +1165,7 @@ static long loopback_ioctl(struct file *file, userspace_task = pid_task(find_vpid(efd_data.pid), PIDTYPE_PID); rcu_read_lock(); - efd_file = fcheck_files(userspace_task->files, efd_data.efd[0]); + efd_file = files_lookup_fd_rcu(userspace_task->files, efd_data.efd[0]); rcu_read_unlock(); efd_ctx = eventfd_ctx_fileget(efd_file); @@ -1201,7 +1192,7 @@ static long loopback_ioctl(struct file *file, * a) vm_interrupt(NULL); * b) queue_work(interrupt_workqueue, &async_interrupt); */ - queue_work(interrupt_workqueue, &async_interrupt); + vm_interrupt(NULL); break; case SHARE_VQS: if (copy_from_user(&queue_sel, (uint32_t *) arg, sizeof(uint32_t))) @@ -1234,17 +1225,16 @@ static long loopback_ioctl(struct file *file, */ static int loopback_open(struct inode *inode, struct file *file) { - uint32_t val_1gb = 1024 * 1024 * 1024; // 1GB + uint32_t val_1gb = 1024 * 1024 * 1024; // 1GB - int ret; /* Update the global variable, the driver is in use */ if (test_and_set_bit(IN_USE_BIT, &loopback_flags)) { DBG("Driver is busy\n"); return -EBUSY; } - /* Set the i_size for the stat SYS_CALL*/ - file->f_inode->i_size = 10 * val_1gb; + /* Set the i_size for the stat SYS_CALL*/ + file->f_inode->i_size = 10 * val_1gb; /* Init mmap funcitonality */ info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL); @@ -1260,8 +1250,10 @@ static int loopback_open(struct inode *inode, struct file *file) init_waitqueue_head(&wq_notify); /* Create a workqueue for our char device */ - notify_workqueue = create_singlethread_workqueue("notify_workqueue"); - interrupt_workqueue = create_singlethread_workqueue("interrupt_workqueue"); + //notify_workqueue = create_singlethread_workqueue("notify_workqueue"); + notify_workqueue = create_workqueue("notify_workqueue"); + //interrupt_workqueue = create_singlethread_workqueue("interrupt_workqueue"); + interrupt_workqueue = create_workqueue("interrupt_workqueue"); /* Init mutex */ mutex_init(&read_write_lock); @@ -1269,13 +1261,6 @@ static int loopback_open(struct inode *inode, struct file *file) mutex_init(¬ify_q_lock); mutex_init(&interrupt_lock); - /* Allocate memory for the FIFO using kfifo_alloc */ - ret = kfifo_alloc(¬ify_queue, KFIFO_SIZE, GFP_KERNEL); - if (ret) { - printk(KERN_ERR "Failed to allocate memory for kfifo\n"); - return ret; - } - /* Init global variables */ mmap_index = 0; page_fault_index = 0; @@ -1334,7 +1319,7 @@ static int __init loopback_init(void) err = alloc_chrdev_region(&dev, 0, MAX_DEV, "loopback"); dev_major = MAJOR(dev); - loopback_class = class_create(THIS_MODULE, "loopback"); + loopback_class = class_create("loopback"); for (i = 0; i < MAX_DEV; i++) { cdev_init(&loopback_data[i].cdev, &fops); diff --git a/loopback_driver.h b/loopback_driver.h index 0a27382..e2c3707 100644 --- a/loopback_driver.h +++ b/loopback_driver.h @@ -260,10 +260,6 @@ typedef struct efd_data { int pid; } efd_data_t; -/* - * ref: https://elixir.bootlin.com/linux/latest/source/arch/x86/mm/init_64.c#L1419 - */ - /* IOCTL defines */ #define EFD_INIT _IOC(_IOC_WRITE, 'k', 1, sizeof(efd_data)) #define WAKEUP _IOC(_IOC_WRITE, 'k', 2, 0) |