From: Alex Williamson <alex.william...@redhat.com>

This patch refines the implementation of original vfio-mdev-pci driver.

And the vfio-mdev-pci-type_name will be named per the following rule:

        vmdev->attr.name = kasprintf(GFP_KERNEL,
                                     "%04x:%04x:%04x:%04x:%06x:%02x",
                                     pdev->vendor, pdev->device,
                                     pdev->subsystem_vendor,
                                     pdev->subsystem_device, pdev->class,
                                     pdev->revision);

Before usage, check the /sys/bus/pci/devices/$bdf/mdev_supported_types/
to ensure the final mdev_supported_types.

Cc: Kevin Tian <kevin.t...@intel.com>
Cc: Lu Baolu <baolu...@linux.intel.com>
Signed-off-by: Alex Williamson <alex.william...@redhat.com>
Signed-off-by: Liu Yi L <yi.l....@intel.com>
---
 drivers/vfio/pci/vfio_mdev_pci.c | 123 +++++++++++++++++++++++----------------
 1 file changed, 72 insertions(+), 51 deletions(-)

diff --git a/drivers/vfio/pci/vfio_mdev_pci.c b/drivers/vfio/pci/vfio_mdev_pci.c
index 07c8067..09143d3 100644
--- a/drivers/vfio/pci/vfio_mdev_pci.c
+++ b/drivers/vfio/pci/vfio_mdev_pci.c
@@ -65,18 +65,22 @@ MODULE_PARM_DESC(disable_idle_d3,
 
 static struct pci_driver vfio_mdev_pci_driver;
 
-static ssize_t
-name_show(struct kobject *kobj, struct device *dev, char *buf)
-{
-       return sprintf(buf, "%s-type1\n", dev_name(dev));
-}
-
-MDEV_TYPE_ATTR_RO(name);
+struct vfio_mdev_pci_device {
+       struct vfio_pci_device vdev;
+       struct mdev_parent_ops ops;
+       struct attribute_group *groups[2];
+       struct attribute_group attr;
+       atomic_t avail;
+};
 
 static ssize_t
 available_instances_show(struct kobject *kobj, struct device *dev, char *buf)
 {
-       return sprintf(buf, "%d\n", 1);
+       struct vfio_mdev_pci_device *vmdev;
+
+       vmdev = pci_get_drvdata(to_pci_dev(dev));
+
+       return sprintf(buf, "%d\n", atomic_read(&vmdev->avail));
 }
 
 MDEV_TYPE_ATTR_RO(available_instances);
@@ -90,62 +94,57 @@ static ssize_t device_api_show(struct kobject *kobj, struct 
device *dev,
 MDEV_TYPE_ATTR_RO(device_api);
 
 static struct attribute *vfio_mdev_pci_types_attrs[] = {
-       &mdev_type_attr_name.attr,
        &mdev_type_attr_device_api.attr,
        &mdev_type_attr_available_instances.attr,
        NULL,
 };
 
-static struct attribute_group vfio_mdev_pci_type_group1 = {
-       .name  = "type1",
-       .attrs = vfio_mdev_pci_types_attrs,
-};
-
-struct attribute_group *vfio_mdev_pci_type_groups[] = {
-       &vfio_mdev_pci_type_group1,
-       NULL,
-};
-
 struct vfio_mdev_pci {
        struct vfio_pci_device *vdev;
        struct mdev_device *mdev;
-       unsigned long handle;
 };
 
 static int vfio_mdev_pci_create(struct kobject *kobj, struct mdev_device *mdev)
 {
        struct device *pdev;
-       struct vfio_pci_device *vdev;
+       struct vfio_mdev_pci_device *vmdev;
        struct vfio_mdev_pci *pmdev;
        int ret;
 
        pdev = mdev_parent_dev(mdev);
-       vdev = dev_get_drvdata(pdev);
+       vmdev = dev_get_drvdata(pdev);
+
+       if (atomic_dec_if_positive(&vmdev->avail) < 0)
+               return -ENOSPC;
+
        pmdev = kzalloc(sizeof(struct vfio_mdev_pci), GFP_KERNEL);
-       if (pmdev == NULL) {
-               ret = -EBUSY;
-               goto out;
-       }
+       if (!pmdev)
+               return -ENOMEM;
 
        pmdev->mdev = mdev;
-       pmdev->vdev = vdev;
+       pmdev->vdev = &vmdev->vdev;
        mdev_set_drvdata(mdev, pmdev);
        ret = mdev_set_iommu_device(mdev_dev(mdev), pdev);
        if (ret) {
                pr_info("%s, failed to config iommu isolation for mdev: %s on 
pf: %s\n",
                        __func__, dev_name(mdev_dev(mdev)), dev_name(pdev));
-               goto out;
+               kfree(pmdev);
+               atomic_inc(&vmdev->avail);
+               return ret;
        }
 
-out:
-       return ret;
+       return 0;
 }
 
 static int vfio_mdev_pci_remove(struct mdev_device *mdev)
 {
        struct vfio_mdev_pci *pmdev = mdev_get_drvdata(mdev);
+       struct vfio_mdev_pci_device *vmdev;
+
+       vmdev = container_of(pmdev->vdev, struct vfio_mdev_pci_device, vdev);
 
        kfree(pmdev);
+       atomic_inc(&vmdev->avail);
        pr_info("%s, succeeded for mdev: %s\n", __func__,
                     dev_name(mdev_dev(mdev)));
 
@@ -237,24 +236,12 @@ static ssize_t vfio_mdev_pci_write(struct mdev_device 
*mdev,
        return vfio_pci_write(pmdev->vdev, (char __user *)buf, count, ppos);
 }
 
-static const struct mdev_parent_ops vfio_mdev_pci_ops = {
-       .supported_type_groups  = vfio_mdev_pci_type_groups,
-       .create                 = vfio_mdev_pci_create,
-       .remove                 = vfio_mdev_pci_remove,
-
-       .open                   = vfio_mdev_pci_open,
-       .release                = vfio_mdev_pci_release,
-
-       .read                   = vfio_mdev_pci_read,
-       .write                  = vfio_mdev_pci_write,
-       .mmap                   = vfio_mdev_pci_mmap,
-       .ioctl                  = vfio_mdev_pci_ioctl,
-};
-
 static int vfio_mdev_pci_driver_probe(struct pci_dev *pdev,
                                       const struct pci_device_id *id)
 {
+       struct vfio_mdev_pci_device *vmdev;
        struct vfio_pci_device *vdev;
+       const struct mdev_parent_ops *ops;
        int ret;
 
        if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
@@ -273,10 +260,38 @@ static int vfio_mdev_pci_driver_probe(struct pci_dev 
*pdev,
                return -EBUSY;
        }
 
-       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
-       if (!vdev)
+       vmdev = kzalloc(sizeof(*vmdev), GFP_KERNEL);
+       if (!vmdev)
                return -ENOMEM;
 
+       vmdev->attr.name = kasprintf(GFP_KERNEL,
+                                    "%04x:%04x:%04x:%04x:%06x:%02x",
+                                    pdev->vendor, pdev->device,
+                                    pdev->subsystem_vendor,
+                                    pdev->subsystem_device, pdev->class,
+                                    pdev->revision);
+       if (!vmdev->attr.name) {
+               kfree(vmdev);
+               return -ENOMEM;
+       }
+
+       atomic_set(&vmdev->avail, 1);
+
+       vmdev->attr.attrs = vfio_mdev_pci_types_attrs;
+       vmdev->groups[0] = &vmdev->attr;
+
+       vmdev->ops.supported_type_groups = vmdev->groups;
+       vmdev->ops.create = vfio_mdev_pci_create;
+       vmdev->ops.remove = vfio_mdev_pci_remove;
+       vmdev->ops.open = vfio_mdev_pci_open;
+       vmdev->ops.release = vfio_mdev_pci_release;
+       vmdev->ops.read = vfio_mdev_pci_read;
+       vmdev->ops.write = vfio_mdev_pci_write;
+       vmdev->ops.mmap = vfio_mdev_pci_mmap;
+       vmdev->ops.ioctl = vfio_mdev_pci_ioctl;
+       ops = &vmdev->ops;
+
+       vdev = &vmdev->vdev;
        vdev->pdev = pdev;
        vdev->irq_type = VFIO_PCI_NUM_IRQS;
        mutex_init(&vdev->igate);
@@ -289,7 +304,7 @@ static int vfio_mdev_pci_driver_probe(struct pci_dev *pdev,
 #endif
        vdev->disable_idle_d3 = disable_idle_d3;
 
-       pci_set_drvdata(pdev, vdev);
+       pci_set_drvdata(pdev, vmdev);
 
        ret = vfio_pci_reflck_attach(vdev);
        if (ret) {
@@ -320,7 +335,7 @@ static int vfio_mdev_pci_driver_probe(struct pci_dev *pdev,
                vfio_pci_set_power_state(vdev, PCI_D3hot);
        }
 
-       ret = mdev_register_device(&pdev->dev, &vfio_mdev_pci_ops);
+       ret = mdev_register_device(&pdev->dev, ops);
        if (ret)
                pr_err("Cannot register mdev for device %s\n",
                        dev_name(&pdev->dev));
@@ -332,12 +347,17 @@ static int vfio_mdev_pci_driver_probe(struct pci_dev 
*pdev,
 
 static void vfio_mdev_pci_driver_remove(struct pci_dev *pdev)
 {
+       struct vfio_mdev_pci_device *vmdev;
        struct vfio_pci_device *vdev;
 
-       vdev = pci_get_drvdata(pdev);
-       if (!vdev)
+       mdev_unregister_device(&pdev->dev);
+
+       vmdev = pci_get_drvdata(pdev);
+       if (!vmdev)
                return;
 
+       vdev = &vmdev->vdev;
+
        vfio_pci_reflck_put(vdev->reflck);
 
        kfree(vdev->region);
@@ -355,7 +375,8 @@ static void vfio_mdev_pci_driver_remove(struct pci_dev 
*pdev)
                                VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
        }
 
-       kfree(vdev);
+       kfree(vmdev->attr.name);
+       kfree(vmdev);
 }
 
 static struct pci_driver vfio_mdev_pci_driver = {
-- 
2.7.4

Reply via email to