Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
0002 /*
0003  * Copyright 2013-2016 Freescale Semiconductor Inc.
0004  * Copyright 2019 NXP
0005  */
0006 
0007 #include <linux/vfio.h>
0008 #include <linux/slab.h>
0009 #include <linux/types.h>
0010 #include <linux/eventfd.h>
0011 #include <linux/msi.h>
0012 
0013 #include "linux/fsl/mc.h"
0014 #include "vfio_fsl_mc_private.h"
0015 
0016 static int vfio_fsl_mc_irqs_allocate(struct vfio_fsl_mc_device *vdev)
0017 {
0018     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0019     struct vfio_fsl_mc_irq *mc_irq;
0020     int irq_count;
0021     int ret, i;
0022 
0023     /* Device does not support any interrupt */
0024     if (mc_dev->obj_desc.irq_count == 0)
0025         return 0;
0026 
0027     /* interrupts were already allocated for this device */
0028     if (vdev->mc_irqs)
0029         return 0;
0030 
0031     irq_count = mc_dev->obj_desc.irq_count;
0032 
0033     mc_irq = kcalloc(irq_count, sizeof(*mc_irq), GFP_KERNEL);
0034     if (!mc_irq)
0035         return -ENOMEM;
0036 
0037     /* Allocate IRQs */
0038     ret = fsl_mc_allocate_irqs(mc_dev);
0039     if (ret) {
0040         kfree(mc_irq);
0041         return ret;
0042     }
0043 
0044     for (i = 0; i < irq_count; i++) {
0045         mc_irq[i].count = 1;
0046         mc_irq[i].flags = VFIO_IRQ_INFO_EVENTFD;
0047     }
0048 
0049     vdev->mc_irqs = mc_irq;
0050 
0051     return 0;
0052 }
0053 
0054 static irqreturn_t vfio_fsl_mc_irq_handler(int irq_num, void *arg)
0055 {
0056     struct vfio_fsl_mc_irq *mc_irq = (struct vfio_fsl_mc_irq *)arg;
0057 
0058     eventfd_signal(mc_irq->trigger, 1);
0059     return IRQ_HANDLED;
0060 }
0061 
0062 static int vfio_set_trigger(struct vfio_fsl_mc_device *vdev,
0063                            int index, int fd)
0064 {
0065     struct vfio_fsl_mc_irq *irq = &vdev->mc_irqs[index];
0066     struct eventfd_ctx *trigger;
0067     int hwirq;
0068     int ret;
0069 
0070     hwirq = vdev->mc_dev->irqs[index]->virq;
0071     if (irq->trigger) {
0072         free_irq(hwirq, irq);
0073         kfree(irq->name);
0074         eventfd_ctx_put(irq->trigger);
0075         irq->trigger = NULL;
0076     }
0077 
0078     if (fd < 0) /* Disable only */
0079         return 0;
0080 
0081     irq->name = kasprintf(GFP_KERNEL, "vfio-irq[%d](%s)",
0082                 hwirq, dev_name(&vdev->mc_dev->dev));
0083     if (!irq->name)
0084         return -ENOMEM;
0085 
0086     trigger = eventfd_ctx_fdget(fd);
0087     if (IS_ERR(trigger)) {
0088         kfree(irq->name);
0089         return PTR_ERR(trigger);
0090     }
0091 
0092     irq->trigger = trigger;
0093 
0094     ret = request_irq(hwirq, vfio_fsl_mc_irq_handler, 0,
0095           irq->name, irq);
0096     if (ret) {
0097         kfree(irq->name);
0098         eventfd_ctx_put(trigger);
0099         irq->trigger = NULL;
0100         return ret;
0101     }
0102 
0103     return 0;
0104 }
0105 
0106 static int vfio_fsl_mc_set_irq_trigger(struct vfio_fsl_mc_device *vdev,
0107                        unsigned int index, unsigned int start,
0108                        unsigned int count, u32 flags,
0109                        void *data)
0110 {
0111     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0112     int ret, hwirq;
0113     struct vfio_fsl_mc_irq *irq;
0114     struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev);
0115     struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev);
0116 
0117     if (!count && (flags & VFIO_IRQ_SET_DATA_NONE))
0118         return vfio_set_trigger(vdev, index, -1);
0119 
0120     if (start != 0 || count != 1)
0121         return -EINVAL;
0122 
0123     mutex_lock(&vdev->vdev.dev_set->lock);
0124     ret = fsl_mc_populate_irq_pool(mc_cont,
0125             FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
0126     if (ret)
0127         goto unlock;
0128 
0129     ret = vfio_fsl_mc_irqs_allocate(vdev);
0130     if (ret)
0131         goto unlock;
0132     mutex_unlock(&vdev->vdev.dev_set->lock);
0133 
0134     if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
0135         s32 fd = *(s32 *)data;
0136 
0137         return vfio_set_trigger(vdev, index, fd);
0138     }
0139 
0140     hwirq = vdev->mc_dev->irqs[index]->virq;
0141 
0142     irq = &vdev->mc_irqs[index];
0143 
0144     if (flags & VFIO_IRQ_SET_DATA_NONE) {
0145         vfio_fsl_mc_irq_handler(hwirq, irq);
0146 
0147     } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
0148         u8 trigger = *(u8 *)data;
0149 
0150         if (trigger)
0151             vfio_fsl_mc_irq_handler(hwirq, irq);
0152     }
0153 
0154     return 0;
0155 
0156 unlock:
0157     mutex_unlock(&vdev->vdev.dev_set->lock);
0158     return ret;
0159 
0160 }
0161 
0162 int vfio_fsl_mc_set_irqs_ioctl(struct vfio_fsl_mc_device *vdev,
0163                    u32 flags, unsigned int index,
0164                    unsigned int start, unsigned int count,
0165                    void *data)
0166 {
0167     if (flags & VFIO_IRQ_SET_ACTION_TRIGGER)
0168         return  vfio_fsl_mc_set_irq_trigger(vdev, index, start,
0169               count, flags, data);
0170     else
0171         return -EINVAL;
0172 }
0173 
0174 /* Free All IRQs for the given MC object */
0175 void vfio_fsl_mc_irqs_cleanup(struct vfio_fsl_mc_device *vdev)
0176 {
0177     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0178     int irq_count = mc_dev->obj_desc.irq_count;
0179     int i;
0180 
0181     /*
0182      * Device does not support any interrupt or the interrupts
0183      * were not configured
0184      */
0185     if (!vdev->mc_irqs)
0186         return;
0187 
0188     for (i = 0; i < irq_count; i++)
0189         vfio_set_trigger(vdev, i, -1);
0190 
0191     fsl_mc_free_irqs(mc_dev);
0192     kfree(vdev->mc_irqs);
0193     vdev->mc_irqs = NULL;
0194 }