diff options
| -rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 33 | ||||
| -rw-r--r-- | drivers/vfio/pci/vfio_pci_private.h | 2 |
2 files changed, 23 insertions, 12 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index fc011e13213b..c9d756b7ee9e 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
| @@ -37,6 +37,8 @@ module_param_named(nointxmask, nointxmask, bool, S_IRUGO | S_IWUSR); | |||
| 37 | MODULE_PARM_DESC(nointxmask, | 37 | MODULE_PARM_DESC(nointxmask, |
| 38 | "Disable support for PCI 2.3 style INTx masking. If this resolves problems for specific devices, report lspci -vvvxxx to linux-pci@vger.kernel.org so the device can be fixed automatically via the broken_intx_masking flag."); | 38 | "Disable support for PCI 2.3 style INTx masking. If this resolves problems for specific devices, report lspci -vvvxxx to linux-pci@vger.kernel.org so the device can be fixed automatically via the broken_intx_masking flag."); |
| 39 | 39 | ||
| 40 | static DEFINE_MUTEX(driver_lock); | ||
| 41 | |||
| 40 | static int vfio_pci_enable(struct vfio_pci_device *vdev) | 42 | static int vfio_pci_enable(struct vfio_pci_device *vdev) |
| 41 | { | 43 | { |
| 42 | struct pci_dev *pdev = vdev->pdev; | 44 | struct pci_dev *pdev = vdev->pdev; |
| @@ -163,23 +165,29 @@ static void vfio_pci_release(void *device_data) | |||
| 163 | { | 165 | { |
| 164 | struct vfio_pci_device *vdev = device_data; | 166 | struct vfio_pci_device *vdev = device_data; |
| 165 | 167 | ||
| 166 | if (atomic_dec_and_test(&vdev->refcnt)) { | 168 | mutex_lock(&driver_lock); |
| 169 | |||
| 170 | if (!(--vdev->refcnt)) { | ||
| 167 | vfio_spapr_pci_eeh_release(vdev->pdev); | 171 | vfio_spapr_pci_eeh_release(vdev->pdev); |
| 168 | vfio_pci_disable(vdev); | 172 | vfio_pci_disable(vdev); |
| 169 | } | 173 | } |
| 170 | 174 | ||
| 175 | mutex_unlock(&driver_lock); | ||
| 176 | |||
| 171 | module_put(THIS_MODULE); | 177 | module_put(THIS_MODULE); |
| 172 | } | 178 | } |
| 173 | 179 | ||
| 174 | static int vfio_pci_open(void *device_data) | 180 | static int vfio_pci_open(void *device_data) |
| 175 | { | 181 | { |
| 176 | struct vfio_pci_device *vdev = device_data; | 182 | struct vfio_pci_device *vdev = device_data; |
| 177 | int ret; | 183 | int ret = 0; |
| 178 | 184 | ||
| 179 | if (!try_module_get(THIS_MODULE)) | 185 | if (!try_module_get(THIS_MODULE)) |
| 180 | return -ENODEV; | 186 | return -ENODEV; |
| 181 | 187 | ||
| 182 | if (atomic_inc_return(&vdev->refcnt) == 1) { | 188 | mutex_lock(&driver_lock); |
| 189 | |||
| 190 | if (!vdev->refcnt) { | ||
| 183 | ret = vfio_pci_enable(vdev); | 191 | ret = vfio_pci_enable(vdev); |
| 184 | if (ret) | 192 | if (ret) |
| 185 | goto error; | 193 | goto error; |
| @@ -190,10 +198,11 @@ static int vfio_pci_open(void *device_data) | |||
| 190 | goto error; | 198 | goto error; |
| 191 | } | 199 | } |
| 192 | } | 200 | } |
| 193 | 201 | vdev->refcnt++; | |
| 194 | return 0; | ||
| 195 | error: | 202 | error: |
| 196 | module_put(THIS_MODULE); | 203 | mutex_unlock(&driver_lock); |
| 204 | if (ret) | ||
| 205 | module_put(THIS_MODULE); | ||
| 197 | return ret; | 206 | return ret; |
| 198 | } | 207 | } |
| 199 | 208 | ||
| @@ -849,7 +858,6 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 849 | vdev->irq_type = VFIO_PCI_NUM_IRQS; | 858 | vdev->irq_type = VFIO_PCI_NUM_IRQS; |
| 850 | mutex_init(&vdev->igate); | 859 | mutex_init(&vdev->igate); |
| 851 | spin_lock_init(&vdev->irqlock); | 860 | spin_lock_init(&vdev->irqlock); |
| 852 | atomic_set(&vdev->refcnt, 0); | ||
| 853 | 861 | ||
| 854 | ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev); | 862 | ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev); |
| 855 | if (ret) { | 863 | if (ret) { |
| @@ -864,12 +872,15 @@ static void vfio_pci_remove(struct pci_dev *pdev) | |||
| 864 | { | 872 | { |
| 865 | struct vfio_pci_device *vdev; | 873 | struct vfio_pci_device *vdev; |
| 866 | 874 | ||
| 875 | mutex_lock(&driver_lock); | ||
| 876 | |||
| 867 | vdev = vfio_del_group_dev(&pdev->dev); | 877 | vdev = vfio_del_group_dev(&pdev->dev); |
| 868 | if (!vdev) | 878 | if (vdev) { |
| 869 | return; | 879 | iommu_group_put(pdev->dev.iommu_group); |
| 880 | kfree(vdev); | ||
| 881 | } | ||
| 870 | 882 | ||
| 871 | iommu_group_put(pdev->dev.iommu_group); | 883 | mutex_unlock(&driver_lock); |
| 872 | kfree(vdev); | ||
| 873 | } | 884 | } |
| 874 | 885 | ||
| 875 | static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, | 886 | static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, |
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h index 9c6d5d0f3b02..31e7a30196ab 100644 --- a/drivers/vfio/pci/vfio_pci_private.h +++ b/drivers/vfio/pci/vfio_pci_private.h | |||
| @@ -55,7 +55,7 @@ struct vfio_pci_device { | |||
| 55 | bool bardirty; | 55 | bool bardirty; |
| 56 | bool has_vga; | 56 | bool has_vga; |
| 57 | struct pci_saved_state *pci_saved_state; | 57 | struct pci_saved_state *pci_saved_state; |
| 58 | atomic_t refcnt; | 58 | int refcnt; |
| 59 | struct eventfd_ctx *err_trigger; | 59 | struct eventfd_ctx *err_trigger; |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
