Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * uio_hv_generic - generic UIO driver for VMBus
0004  *
0005  * Copyright (c) 2013-2016 Brocade Communications Systems, Inc.
0006  * Copyright (c) 2016, Microsoft Corporation.
0007  *
0008  * Since the driver does not declare any device ids, you must allocate
0009  * id and bind the device to the driver yourself.  For example:
0010  *
0011  * Associate Network GUID with UIO device
0012  * # echo "f8615163-df3e-46c5-913f-f2d2f965ed0e" \
0013  *    > /sys/bus/vmbus/drivers/uio_hv_generic/new_id
0014  * Then rebind
0015  * # echo -n "ed963694-e847-4b2a-85af-bc9cfc11d6f3" \
0016  *    > /sys/bus/vmbus/drivers/hv_netvsc/unbind
0017  * # echo -n "ed963694-e847-4b2a-85af-bc9cfc11d6f3" \
0018  *    > /sys/bus/vmbus/drivers/uio_hv_generic/bind
0019  */
0020 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0021 
0022 #include <linux/device.h>
0023 #include <linux/kernel.h>
0024 #include <linux/module.h>
0025 #include <linux/uio_driver.h>
0026 #include <linux/netdevice.h>
0027 #include <linux/if_ether.h>
0028 #include <linux/skbuff.h>
0029 #include <linux/hyperv.h>
0030 #include <linux/vmalloc.h>
0031 #include <linux/slab.h>
0032 
0033 #include "../hv/hyperv_vmbus.h"
0034 
0035 #define DRIVER_VERSION  "0.02.1"
0036 #define DRIVER_AUTHOR   "Stephen Hemminger <sthemmin at microsoft.com>"
0037 #define DRIVER_DESC "Generic UIO driver for VMBus devices"
0038 
0039 #define HV_RING_SIZE     512    /* pages */
0040 #define SEND_BUFFER_SIZE (16 * 1024 * 1024)
0041 #define RECV_BUFFER_SIZE (31 * 1024 * 1024)
0042 
0043 /*
0044  * List of resources to be mapped to user space
0045  * can be extended up to MAX_UIO_MAPS(5) items
0046  */
0047 enum hv_uio_map {
0048     TXRX_RING_MAP = 0,
0049     INT_PAGE_MAP,
0050     MON_PAGE_MAP,
0051     RECV_BUF_MAP,
0052     SEND_BUF_MAP
0053 };
0054 
0055 struct hv_uio_private_data {
0056     struct uio_info info;
0057     struct hv_device *device;
0058     atomic_t refcnt;
0059 
0060     void    *recv_buf;
0061     struct vmbus_gpadl recv_gpadl;
0062     char    recv_name[32];  /* "recv_4294967295" */
0063 
0064     void    *send_buf;
0065     struct vmbus_gpadl send_gpadl;
0066     char    send_name[32];
0067 };
0068 
0069 /*
0070  * This is the irqcontrol callback to be registered to uio_info.
0071  * It can be used to disable/enable interrupt from user space processes.
0072  *
0073  * @param info
0074  *  pointer to uio_info.
0075  * @param irq_state
0076  *  state value. 1 to enable interrupt, 0 to disable interrupt.
0077  */
0078 static int
0079 hv_uio_irqcontrol(struct uio_info *info, s32 irq_state)
0080 {
0081     struct hv_uio_private_data *pdata = info->priv;
0082     struct hv_device *dev = pdata->device;
0083 
0084     dev->channel->inbound.ring_buffer->interrupt_mask = !irq_state;
0085     virt_mb();
0086 
0087     return 0;
0088 }
0089 
0090 /*
0091  * Callback from vmbus_event when something is in inbound ring.
0092  */
0093 static void hv_uio_channel_cb(void *context)
0094 {
0095     struct vmbus_channel *chan = context;
0096     struct hv_device *hv_dev = chan->device_obj;
0097     struct hv_uio_private_data *pdata = hv_get_drvdata(hv_dev);
0098 
0099     chan->inbound.ring_buffer->interrupt_mask = 1;
0100     virt_mb();
0101 
0102     uio_event_notify(&pdata->info);
0103 }
0104 
0105 /*
0106  * Callback from vmbus_event when channel is rescinded.
0107  */
0108 static void hv_uio_rescind(struct vmbus_channel *channel)
0109 {
0110     struct hv_device *hv_dev = channel->primary_channel->device_obj;
0111     struct hv_uio_private_data *pdata = hv_get_drvdata(hv_dev);
0112 
0113     /*
0114      * Turn off the interrupt file handle
0115      * Next read for event will return -EIO
0116      */
0117     pdata->info.irq = 0;
0118 
0119     /* Wake up reader */
0120     uio_event_notify(&pdata->info);
0121 }
0122 
0123 /* Sysfs API to allow mmap of the ring buffers
0124  * The ring buffer is allocated as contiguous memory by vmbus_open
0125  */
0126 static int hv_uio_ring_mmap(struct file *filp, struct kobject *kobj,
0127                 struct bin_attribute *attr,
0128                 struct vm_area_struct *vma)
0129 {
0130     struct vmbus_channel *channel
0131         = container_of(kobj, struct vmbus_channel, kobj);
0132     void *ring_buffer = page_address(channel->ringbuffer_page);
0133 
0134     if (channel->state != CHANNEL_OPENED_STATE)
0135         return -ENODEV;
0136 
0137     return vm_iomap_memory(vma, virt_to_phys(ring_buffer),
0138                    channel->ringbuffer_pagecount << PAGE_SHIFT);
0139 }
0140 
0141 static const struct bin_attribute ring_buffer_bin_attr = {
0142     .attr = {
0143         .name = "ring",
0144         .mode = 0600,
0145     },
0146     .size = 2 * HV_RING_SIZE * PAGE_SIZE,
0147     .mmap = hv_uio_ring_mmap,
0148 };
0149 
0150 /* Callback from VMBUS subsystem when new channel created. */
0151 static void
0152 hv_uio_new_channel(struct vmbus_channel *new_sc)
0153 {
0154     struct hv_device *hv_dev = new_sc->primary_channel->device_obj;
0155     struct device *device = &hv_dev->device;
0156     const size_t ring_bytes = HV_RING_SIZE * PAGE_SIZE;
0157     int ret;
0158 
0159     /* Create host communication ring */
0160     ret = vmbus_open(new_sc, ring_bytes, ring_bytes, NULL, 0,
0161              hv_uio_channel_cb, new_sc);
0162     if (ret) {
0163         dev_err(device, "vmbus_open subchannel failed: %d\n", ret);
0164         return;
0165     }
0166 
0167     /* Disable interrupts on sub channel */
0168     new_sc->inbound.ring_buffer->interrupt_mask = 1;
0169     set_channel_read_mode(new_sc, HV_CALL_ISR);
0170 
0171     ret = sysfs_create_bin_file(&new_sc->kobj, &ring_buffer_bin_attr);
0172     if (ret) {
0173         dev_err(device, "sysfs create ring bin file failed; %d\n", ret);
0174         vmbus_close(new_sc);
0175     }
0176 }
0177 
0178 /* free the reserved buffers for send and receive */
0179 static void
0180 hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)
0181 {
0182     if (pdata->send_gpadl.gpadl_handle) {
0183         vmbus_teardown_gpadl(dev->channel, &pdata->send_gpadl);
0184         vfree(pdata->send_buf);
0185     }
0186 
0187     if (pdata->recv_gpadl.gpadl_handle) {
0188         vmbus_teardown_gpadl(dev->channel, &pdata->recv_gpadl);
0189         vfree(pdata->recv_buf);
0190     }
0191 }
0192 
0193 /* VMBus primary channel is opened on first use */
0194 static int
0195 hv_uio_open(struct uio_info *info, struct inode *inode)
0196 {
0197     struct hv_uio_private_data *pdata
0198         = container_of(info, struct hv_uio_private_data, info);
0199     struct hv_device *dev = pdata->device;
0200     int ret;
0201 
0202     if (atomic_inc_return(&pdata->refcnt) != 1)
0203         return 0;
0204 
0205     vmbus_set_chn_rescind_callback(dev->channel, hv_uio_rescind);
0206     vmbus_set_sc_create_callback(dev->channel, hv_uio_new_channel);
0207 
0208     ret = vmbus_connect_ring(dev->channel,
0209                  hv_uio_channel_cb, dev->channel);
0210     if (ret == 0)
0211         dev->channel->inbound.ring_buffer->interrupt_mask = 1;
0212     else
0213         atomic_dec(&pdata->refcnt);
0214 
0215     return ret;
0216 }
0217 
0218 /* VMBus primary channel is closed on last close */
0219 static int
0220 hv_uio_release(struct uio_info *info, struct inode *inode)
0221 {
0222     struct hv_uio_private_data *pdata
0223         = container_of(info, struct hv_uio_private_data, info);
0224     struct hv_device *dev = pdata->device;
0225     int ret = 0;
0226 
0227     if (atomic_dec_and_test(&pdata->refcnt))
0228         ret = vmbus_disconnect_ring(dev->channel);
0229 
0230     return ret;
0231 }
0232 
0233 static int
0234 hv_uio_probe(struct hv_device *dev,
0235          const struct hv_vmbus_device_id *dev_id)
0236 {
0237     struct vmbus_channel *channel = dev->channel;
0238     struct hv_uio_private_data *pdata;
0239     void *ring_buffer;
0240     int ret;
0241 
0242     /* Communicating with host has to be via shared memory not hypercall */
0243     if (!channel->offermsg.monitor_allocated) {
0244         dev_err(&dev->device, "vmbus channel requires hypercall\n");
0245         return -ENOTSUPP;
0246     }
0247 
0248     pdata = devm_kzalloc(&dev->device, sizeof(*pdata), GFP_KERNEL);
0249     if (!pdata)
0250         return -ENOMEM;
0251 
0252     ret = vmbus_alloc_ring(channel, HV_RING_SIZE * PAGE_SIZE,
0253                    HV_RING_SIZE * PAGE_SIZE);
0254     if (ret)
0255         return ret;
0256 
0257     set_channel_read_mode(channel, HV_CALL_ISR);
0258 
0259     /* Fill general uio info */
0260     pdata->info.name = "uio_hv_generic";
0261     pdata->info.version = DRIVER_VERSION;
0262     pdata->info.irqcontrol = hv_uio_irqcontrol;
0263     pdata->info.open = hv_uio_open;
0264     pdata->info.release = hv_uio_release;
0265     pdata->info.irq = UIO_IRQ_CUSTOM;
0266     atomic_set(&pdata->refcnt, 0);
0267 
0268     /* mem resources */
0269     pdata->info.mem[TXRX_RING_MAP].name = "txrx_rings";
0270     ring_buffer = page_address(channel->ringbuffer_page);
0271     pdata->info.mem[TXRX_RING_MAP].addr
0272         = (uintptr_t)virt_to_phys(ring_buffer);
0273     pdata->info.mem[TXRX_RING_MAP].size
0274         = channel->ringbuffer_pagecount << PAGE_SHIFT;
0275     pdata->info.mem[TXRX_RING_MAP].memtype = UIO_MEM_IOVA;
0276 
0277     pdata->info.mem[INT_PAGE_MAP].name = "int_page";
0278     pdata->info.mem[INT_PAGE_MAP].addr
0279         = (uintptr_t)vmbus_connection.int_page;
0280     pdata->info.mem[INT_PAGE_MAP].size = PAGE_SIZE;
0281     pdata->info.mem[INT_PAGE_MAP].memtype = UIO_MEM_LOGICAL;
0282 
0283     pdata->info.mem[MON_PAGE_MAP].name = "monitor_page";
0284     pdata->info.mem[MON_PAGE_MAP].addr
0285         = (uintptr_t)vmbus_connection.monitor_pages[1];
0286     pdata->info.mem[MON_PAGE_MAP].size = PAGE_SIZE;
0287     pdata->info.mem[MON_PAGE_MAP].memtype = UIO_MEM_LOGICAL;
0288 
0289     pdata->recv_buf = vzalloc(RECV_BUFFER_SIZE);
0290     if (pdata->recv_buf == NULL) {
0291         ret = -ENOMEM;
0292         goto fail_free_ring;
0293     }
0294 
0295     ret = vmbus_establish_gpadl(channel, pdata->recv_buf,
0296                     RECV_BUFFER_SIZE, &pdata->recv_gpadl);
0297     if (ret) {
0298         vfree(pdata->recv_buf);
0299         goto fail_close;
0300     }
0301 
0302     /* put Global Physical Address Label in name */
0303     snprintf(pdata->recv_name, sizeof(pdata->recv_name),
0304          "recv:%u", pdata->recv_gpadl.gpadl_handle);
0305     pdata->info.mem[RECV_BUF_MAP].name = pdata->recv_name;
0306     pdata->info.mem[RECV_BUF_MAP].addr
0307         = (uintptr_t)pdata->recv_buf;
0308     pdata->info.mem[RECV_BUF_MAP].size = RECV_BUFFER_SIZE;
0309     pdata->info.mem[RECV_BUF_MAP].memtype = UIO_MEM_VIRTUAL;
0310 
0311     pdata->send_buf = vzalloc(SEND_BUFFER_SIZE);
0312     if (pdata->send_buf == NULL) {
0313         ret = -ENOMEM;
0314         goto fail_close;
0315     }
0316 
0317     ret = vmbus_establish_gpadl(channel, pdata->send_buf,
0318                     SEND_BUFFER_SIZE, &pdata->send_gpadl);
0319     if (ret) {
0320         vfree(pdata->send_buf);
0321         goto fail_close;
0322     }
0323 
0324     snprintf(pdata->send_name, sizeof(pdata->send_name),
0325          "send:%u", pdata->send_gpadl.gpadl_handle);
0326     pdata->info.mem[SEND_BUF_MAP].name = pdata->send_name;
0327     pdata->info.mem[SEND_BUF_MAP].addr
0328         = (uintptr_t)pdata->send_buf;
0329     pdata->info.mem[SEND_BUF_MAP].size = SEND_BUFFER_SIZE;
0330     pdata->info.mem[SEND_BUF_MAP].memtype = UIO_MEM_VIRTUAL;
0331 
0332     pdata->info.priv = pdata;
0333     pdata->device = dev;
0334 
0335     ret = uio_register_device(&dev->device, &pdata->info);
0336     if (ret) {
0337         dev_err(&dev->device, "hv_uio register failed\n");
0338         goto fail_close;
0339     }
0340 
0341     ret = sysfs_create_bin_file(&channel->kobj, &ring_buffer_bin_attr);
0342     if (ret)
0343         dev_notice(&dev->device,
0344                "sysfs create ring bin file failed; %d\n", ret);
0345 
0346     hv_set_drvdata(dev, pdata);
0347 
0348     return 0;
0349 
0350 fail_close:
0351     hv_uio_cleanup(dev, pdata);
0352 fail_free_ring:
0353     vmbus_free_ring(dev->channel);
0354 
0355     return ret;
0356 }
0357 
0358 static int
0359 hv_uio_remove(struct hv_device *dev)
0360 {
0361     struct hv_uio_private_data *pdata = hv_get_drvdata(dev);
0362 
0363     if (!pdata)
0364         return 0;
0365 
0366     sysfs_remove_bin_file(&dev->channel->kobj, &ring_buffer_bin_attr);
0367     uio_unregister_device(&pdata->info);
0368     hv_uio_cleanup(dev, pdata);
0369 
0370     vmbus_free_ring(dev->channel);
0371     return 0;
0372 }
0373 
0374 static struct hv_driver hv_uio_drv = {
0375     .name = "uio_hv_generic",
0376     .id_table = NULL, /* only dynamic id's */
0377     .probe = hv_uio_probe,
0378     .remove = hv_uio_remove,
0379 };
0380 
0381 static int __init
0382 hyperv_module_init(void)
0383 {
0384     return vmbus_driver_register(&hv_uio_drv);
0385 }
0386 
0387 static void __exit
0388 hyperv_module_exit(void)
0389 {
0390     vmbus_driver_unregister(&hv_uio_drv);
0391 }
0392 
0393 module_init(hyperv_module_init);
0394 module_exit(hyperv_module_exit);
0395 
0396 MODULE_VERSION(DRIVER_VERSION);
0397 MODULE_LICENSE("GPL v2");
0398 MODULE_AUTHOR(DRIVER_AUTHOR);
0399 MODULE_DESCRIPTION(DRIVER_DESC);