1/* 2 * Intel MIC Platform Software Stack (MPSS) 3 * 4 * Copyright(c) 2013 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License, version 2, as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * The full GNU General Public License is included in this distribution in 16 * the file called "COPYING". 17 * 18 * Intel MIC Host driver. 19 * 20 */ 21#include <linux/poll.h> 22#include <linux/pci.h> 23 24#include <linux/mic_common.h> 25#include "../common/mic_dev.h" 26#include "mic_device.h" 27#include "mic_fops.h" 28#include "mic_virtio.h" 29 30int mic_open(struct inode *inode, struct file *f) 31{ 32 struct mic_vdev *mvdev; 33 struct mic_device *mdev = container_of(f->private_data, 34 struct mic_device, miscdev); 35 36 mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL); 37 if (!mvdev) 38 return -ENOMEM; 39 40 init_waitqueue_head(&mvdev->waitq); 41 INIT_LIST_HEAD(&mvdev->list); 42 mvdev->mdev = mdev; 43 mvdev->virtio_id = -1; 44 45 f->private_data = mvdev; 46 return 0; 47} 48 49int mic_release(struct inode *inode, struct file *f) 50{ 51 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; 52 53 if (-1 != mvdev->virtio_id) 54 mic_virtio_del_device(mvdev); 55 f->private_data = NULL; 56 kfree(mvdev); 57 return 0; 58} 59 60long mic_ioctl(struct file *f, unsigned int cmd, unsigned long arg) 61{ 62 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; 63 void __user *argp = (void __user *)arg; 64 int ret; 65 66 switch (cmd) { 67 case MIC_VIRTIO_ADD_DEVICE: 68 { 69 ret = mic_virtio_add_device(mvdev, argp); 70 if (ret < 0) { 71 dev_err(mic_dev(mvdev), 72 "%s %d errno ret %d\n", 73 __func__, __LINE__, ret); 74 return ret; 75 } 76 break; 77 } 78 case MIC_VIRTIO_COPY_DESC: 79 { 80 struct mic_copy_desc copy; 81 82 ret = mic_vdev_inited(mvdev); 83 if (ret) 84 return ret; 85 86 if (copy_from_user(©, argp, sizeof(copy))) 87 return -EFAULT; 88 89 dev_dbg(mic_dev(mvdev), 90 "%s %d === iovcnt 0x%x vr_idx 0x%x update_used %d\n", 91 __func__, __LINE__, copy.iovcnt, copy.vr_idx, 92 copy.update_used); 93 94 ret = mic_virtio_copy_desc(mvdev, ©); 95 if (ret < 0) { 96 dev_err(mic_dev(mvdev), 97 "%s %d errno ret %d\n", 98 __func__, __LINE__, ret); 99 return ret; 100 } 101 if (copy_to_user( 102 &((struct mic_copy_desc __user *)argp)->out_len, 103 ©.out_len, sizeof(copy.out_len))) { 104 dev_err(mic_dev(mvdev), "%s %d errno ret %d\n", 105 __func__, __LINE__, -EFAULT); 106 return -EFAULT; 107 } 108 break; 109 } 110 case MIC_VIRTIO_CONFIG_CHANGE: 111 { 112 ret = mic_vdev_inited(mvdev); 113 if (ret) 114 return ret; 115 116 ret = mic_virtio_config_change(mvdev, argp); 117 if (ret < 0) { 118 dev_err(mic_dev(mvdev), 119 "%s %d errno ret %d\n", 120 __func__, __LINE__, ret); 121 return ret; 122 } 123 break; 124 } 125 default: 126 return -ENOIOCTLCMD; 127 }; 128 return 0; 129} 130 131/* 132 * We return POLLIN | POLLOUT from poll when new buffers are enqueued, and 133 * not when previously enqueued buffers may be available. This means that 134 * in the card->host (TX) path, when userspace is unblocked by poll it 135 * must drain all available descriptors or it can stall. 136 */ 137unsigned int mic_poll(struct file *f, poll_table *wait) 138{ 139 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; 140 int mask = 0; 141 142 poll_wait(f, &mvdev->waitq, wait); 143 144 if (mic_vdev_inited(mvdev)) { 145 mask = POLLERR; 146 } else if (mvdev->poll_wake) { 147 mvdev->poll_wake = 0; 148 mask = POLLIN | POLLOUT; 149 } 150 151 return mask; 152} 153 154static inline int 155mic_query_offset(struct mic_vdev *mvdev, unsigned long offset, 156 unsigned long *size, unsigned long *pa) 157{ 158 struct mic_device *mdev = mvdev->mdev; 159 unsigned long start = MIC_DP_SIZE; 160 int i; 161 162 /* 163 * MMAP interface is as follows: 164 * offset region 165 * 0x0 virtio device_page 166 * 0x1000 first vring 167 * 0x1000 + size of 1st vring second vring 168 * .... 169 */ 170 if (!offset) { 171 *pa = virt_to_phys(mdev->dp); 172 *size = MIC_DP_SIZE; 173 return 0; 174 } 175 176 for (i = 0; i < mvdev->dd->num_vq; i++) { 177 struct mic_vringh *mvr = &mvdev->mvr[i]; 178 if (offset == start) { 179 *pa = virt_to_phys(mvr->vring.va); 180 *size = mvr->vring.len; 181 return 0; 182 } 183 start += mvr->vring.len; 184 } 185 return -1; 186} 187 188/* 189 * Maps the device page and virtio rings to user space for readonly access. 190 */ 191int 192mic_mmap(struct file *f, struct vm_area_struct *vma) 193{ 194 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; 195 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 196 unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem = size; 197 int i, err; 198 199 err = mic_vdev_inited(mvdev); 200 if (err) 201 return err; 202 203 if (vma->vm_flags & VM_WRITE) 204 return -EACCES; 205 206 while (size_rem) { 207 i = mic_query_offset(mvdev, offset, &size, &pa); 208 if (i < 0) 209 return -EINVAL; 210 err = remap_pfn_range(vma, vma->vm_start + offset, 211 pa >> PAGE_SHIFT, size, vma->vm_page_prot); 212 if (err) 213 return err; 214 dev_dbg(mic_dev(mvdev), 215 "%s %d type %d size 0x%lx off 0x%lx pa 0x%lx vma 0x%lx\n", 216 __func__, __LINE__, mvdev->virtio_id, size, offset, 217 pa, vma->vm_start + offset); 218 size_rem -= size; 219 offset += size; 220 } 221 return 0; 222} 223