1 /* 2 * uio_hv_generic - generic UIO driver for VMBus 3 * 4 * Copyright (c) 2013-2016 Brocade Communications Systems, Inc. 5 * Copyright (c) 2016, Microsoft Corporation. 6 * 7 * 8 * This work is licensed under the terms of the GNU GPL, version 2. 9 * 10 * Since the driver does not declare any device ids, you must allocate 11 * id and bind the device to the driver yourself. For example: 12 * 13 * # echo "f8615163-df3e-46c5-913f-f2d2f965ed0e" \ 14 * > /sys/bus/vmbus/drivers/uio_hv_generic 15 * # echo -n vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3 \ 16 * > /sys/bus/vmbus/drivers/hv_netvsc/unbind 17 * # echo -n vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3 \ 18 * > /sys/bus/vmbus/drivers/uio_hv_generic/bind 19 */ 20 21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22 23 #include <linux/device.h> 24 #include <linux/kernel.h> 25 #include <linux/module.h> 26 #include <linux/uio_driver.h> 27 #include <linux/netdevice.h> 28 #include <linux/if_ether.h> 29 #include <linux/skbuff.h> 30 #include <linux/hyperv.h> 31 #include <linux/vmalloc.h> 32 #include <linux/slab.h> 33 34 #include "../hv/hyperv_vmbus.h" 35 36 #define DRIVER_VERSION "0.02.0" 37 #define DRIVER_AUTHOR "Stephen Hemminger <sthemmin at microsoft.com>" 38 #define DRIVER_DESC "Generic UIO driver for VMBus devices" 39 40 /* 41 * List of resources to be mapped to user space 42 * can be extended up to MAX_UIO_MAPS(5) items 43 */ 44 enum hv_uio_map { 45 TXRX_RING_MAP = 0, 46 INT_PAGE_MAP, 47 MON_PAGE_MAP, 48 }; 49 50 #define HV_RING_SIZE 512 51 52 struct hv_uio_private_data { 53 struct uio_info info; 54 struct hv_device *device; 55 }; 56 57 static int 58 hv_uio_mmap(struct uio_info *info, struct vm_area_struct *vma) 59 { 60 int mi; 61 62 if (vma->vm_pgoff >= MAX_UIO_MAPS) 63 return -EINVAL; 64 65 if (info->mem[vma->vm_pgoff].size == 0) 66 return -EINVAL; 67 68 mi = (int)vma->vm_pgoff; 69 70 return remap_pfn_range(vma, vma->vm_start, 71 info->mem[mi].addr >> PAGE_SHIFT, 72 vma->vm_end - vma->vm_start, vma->vm_page_prot); 73 } 74 75 /* 76 * This is the irqcontrol callback to be registered to uio_info. 77 * It can be used to disable/enable interrupt from user space processes. 78 * 79 * @param info 80 * pointer to uio_info. 81 * @param irq_state 82 * state value. 1 to enable interrupt, 0 to disable interrupt. 83 */ 84 static int 85 hv_uio_irqcontrol(struct uio_info *info, s32 irq_state) 86 { 87 struct hv_uio_private_data *pdata = info->priv; 88 struct hv_device *dev = pdata->device; 89 90 dev->channel->inbound.ring_buffer->interrupt_mask = !irq_state; 91 virt_mb(); 92 93 return 0; 94 } 95 96 /* 97 * Callback from vmbus_event when something is in inbound ring. 98 */ 99 static void hv_uio_channel_cb(void *context) 100 { 101 struct hv_uio_private_data *pdata = context; 102 struct hv_device *dev = pdata->device; 103 104 dev->channel->inbound.ring_buffer->interrupt_mask = 1; 105 virt_mb(); 106 107 uio_event_notify(&pdata->info); 108 } 109 110 static int 111 hv_uio_probe(struct hv_device *dev, 112 const struct hv_vmbus_device_id *dev_id) 113 { 114 struct hv_uio_private_data *pdata; 115 int ret; 116 117 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 118 if (!pdata) 119 return -ENOMEM; 120 121 ret = vmbus_open(dev->channel, HV_RING_SIZE * PAGE_SIZE, 122 HV_RING_SIZE * PAGE_SIZE, NULL, 0, 123 hv_uio_channel_cb, pdata); 124 if (ret) 125 goto fail; 126 127 dev->channel->inbound.ring_buffer->interrupt_mask = 1; 128 set_channel_read_mode(dev->channel, HV_CALL_DIRECT); 129 130 /* Fill general uio info */ 131 pdata->info.name = "uio_hv_generic"; 132 pdata->info.version = DRIVER_VERSION; 133 pdata->info.irqcontrol = hv_uio_irqcontrol; 134 pdata->info.mmap = hv_uio_mmap; 135 pdata->info.irq = UIO_IRQ_CUSTOM; 136 137 /* mem resources */ 138 pdata->info.mem[TXRX_RING_MAP].name = "txrx_rings"; 139 pdata->info.mem[TXRX_RING_MAP].addr 140 = virt_to_phys(dev->channel->ringbuffer_pages); 141 pdata->info.mem[TXRX_RING_MAP].size 142 = dev->channel->ringbuffer_pagecount * PAGE_SIZE; 143 pdata->info.mem[TXRX_RING_MAP].memtype = UIO_MEM_LOGICAL; 144 145 pdata->info.mem[INT_PAGE_MAP].name = "int_page"; 146 pdata->info.mem[INT_PAGE_MAP].addr = 147 virt_to_phys(vmbus_connection.int_page); 148 pdata->info.mem[INT_PAGE_MAP].size = PAGE_SIZE; 149 pdata->info.mem[INT_PAGE_MAP].memtype = UIO_MEM_LOGICAL; 150 151 pdata->info.mem[MON_PAGE_MAP].name = "monitor_pages"; 152 pdata->info.mem[MON_PAGE_MAP].addr = 153 virt_to_phys(vmbus_connection.monitor_pages[1]); 154 pdata->info.mem[MON_PAGE_MAP].size = PAGE_SIZE; 155 pdata->info.mem[MON_PAGE_MAP].memtype = UIO_MEM_LOGICAL; 156 157 pdata->info.priv = pdata; 158 pdata->device = dev; 159 160 ret = uio_register_device(&dev->device, &pdata->info); 161 if (ret) { 162 dev_err(&dev->device, "hv_uio register failed\n"); 163 goto fail_close; 164 } 165 166 hv_set_drvdata(dev, pdata); 167 168 return 0; 169 170 fail_close: 171 vmbus_close(dev->channel); 172 fail: 173 kfree(pdata); 174 175 return ret; 176 } 177 178 static int 179 hv_uio_remove(struct hv_device *dev) 180 { 181 struct hv_uio_private_data *pdata = hv_get_drvdata(dev); 182 183 if (!pdata) 184 return 0; 185 186 uio_unregister_device(&pdata->info); 187 hv_set_drvdata(dev, NULL); 188 vmbus_close(dev->channel); 189 kfree(pdata); 190 return 0; 191 } 192 193 static struct hv_driver hv_uio_drv = { 194 .name = "uio_hv_generic", 195 .id_table = NULL, /* only dynamic id's */ 196 .probe = hv_uio_probe, 197 .remove = hv_uio_remove, 198 }; 199 200 static int __init 201 hyperv_module_init(void) 202 { 203 return vmbus_driver_register(&hv_uio_drv); 204 } 205 206 static void __exit 207 hyperv_module_exit(void) 208 { 209 vmbus_driver_unregister(&hv_uio_drv); 210 } 211 212 module_init(hyperv_module_init); 213 module_exit(hyperv_module_exit); 214 215 MODULE_VERSION(DRIVER_VERSION); 216 MODULE_LICENSE("GPL v2"); 217 MODULE_AUTHOR(DRIVER_AUTHOR); 218 MODULE_DESCRIPTION(DRIVER_DESC); 219