aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/vfio/pci/vfio_pci.c33
-rw-r--r--drivers/vfio/pci/vfio_pci_private.h2
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);
37MODULE_PARM_DESC(nointxmask, 37MODULE_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
40static DEFINE_MUTEX(driver_lock);
41
40static int vfio_pci_enable(struct vfio_pci_device *vdev) 42static 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
174static int vfio_pci_open(void *device_data) 180static 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;
195error: 202error:
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
875static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, 886static 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