@@ -36,6 +36,10 @@ static bool nointxmask;
3636static bool disable_vga ;
3737static bool disable_idle_d3 ;
3838
39+ /* List of PF's that vfio_pci_core_sriov_configure() has been called on */
40+ static DEFINE_MUTEX (vfio_pci_sriov_pfs_mutex );
41+ static LIST_HEAD (vfio_pci_sriov_pfs );
42+
3943static inline bool vfio_vga_disabled (void )
4044{
4145#ifdef CONFIG_VFIO_PCI_VGA
@@ -434,47 +438,17 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
434438}
435439EXPORT_SYMBOL_GPL (vfio_pci_core_disable );
436440
437- static struct vfio_pci_core_device * get_pf_vdev (struct vfio_pci_core_device * vdev )
438- {
439- struct pci_dev * physfn = pci_physfn (vdev -> pdev );
440- struct vfio_device * pf_dev ;
441-
442- if (!vdev -> pdev -> is_virtfn )
443- return NULL ;
444-
445- pf_dev = vfio_device_get_from_dev (& physfn -> dev );
446- if (!pf_dev )
447- return NULL ;
448-
449- if (pci_dev_driver (physfn ) != pci_dev_driver (vdev -> pdev )) {
450- vfio_device_put (pf_dev );
451- return NULL ;
452- }
453-
454- return container_of (pf_dev , struct vfio_pci_core_device , vdev );
455- }
456-
457- static void vfio_pci_vf_token_user_add (struct vfio_pci_core_device * vdev , int val )
458- {
459- struct vfio_pci_core_device * pf_vdev = get_pf_vdev (vdev );
460-
461- if (!pf_vdev )
462- return ;
463-
464- mutex_lock (& pf_vdev -> vf_token -> lock );
465- pf_vdev -> vf_token -> users += val ;
466- WARN_ON (pf_vdev -> vf_token -> users < 0 );
467- mutex_unlock (& pf_vdev -> vf_token -> lock );
468-
469- vfio_device_put (& pf_vdev -> vdev );
470- }
471-
472441void vfio_pci_core_close_device (struct vfio_device * core_vdev )
473442{
474443 struct vfio_pci_core_device * vdev =
475444 container_of (core_vdev , struct vfio_pci_core_device , vdev );
476445
477- vfio_pci_vf_token_user_add (vdev , -1 );
446+ if (vdev -> sriov_pf_core_dev ) {
447+ mutex_lock (& vdev -> sriov_pf_core_dev -> vf_token -> lock );
448+ WARN_ON (!vdev -> sriov_pf_core_dev -> vf_token -> users );
449+ vdev -> sriov_pf_core_dev -> vf_token -> users -- ;
450+ mutex_unlock (& vdev -> sriov_pf_core_dev -> vf_token -> lock );
451+ }
478452 vfio_spapr_pci_eeh_release (vdev -> pdev );
479453 vfio_pci_core_disable (vdev );
480454
@@ -495,7 +469,12 @@ void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev)
495469{
496470 vfio_pci_probe_mmaps (vdev );
497471 vfio_spapr_pci_eeh_open (vdev -> pdev );
498- vfio_pci_vf_token_user_add (vdev , 1 );
472+
473+ if (vdev -> sriov_pf_core_dev ) {
474+ mutex_lock (& vdev -> sriov_pf_core_dev -> vf_token -> lock );
475+ vdev -> sriov_pf_core_dev -> vf_token -> users ++ ;
476+ mutex_unlock (& vdev -> sriov_pf_core_dev -> vf_token -> lock );
477+ }
499478}
500479EXPORT_SYMBOL_GPL (vfio_pci_core_finish_enable );
501480
@@ -1583,11 +1562,8 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
15831562 *
15841563 * If the VF token is provided but unused, an error is generated.
15851564 */
1586- if (!vdev -> pdev -> is_virtfn && !vdev -> vf_token && !vf_token )
1587- return 0 ; /* No VF token provided or required */
1588-
15891565 if (vdev -> pdev -> is_virtfn ) {
1590- struct vfio_pci_core_device * pf_vdev = get_pf_vdev ( vdev ) ;
1566+ struct vfio_pci_core_device * pf_vdev = vdev -> sriov_pf_core_dev ;
15911567 bool match ;
15921568
15931569 if (!pf_vdev ) {
@@ -1600,7 +1576,6 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
16001576 }
16011577
16021578 if (!vf_token ) {
1603- vfio_device_put (& pf_vdev -> vdev );
16041579 pci_info_ratelimited (vdev -> pdev ,
16051580 "VF token required to access device\n" );
16061581 return - EACCES ;
@@ -1610,8 +1585,6 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
16101585 match = uuid_equal (uuid , & pf_vdev -> vf_token -> uuid );
16111586 mutex_unlock (& pf_vdev -> vf_token -> lock );
16121587
1613- vfio_device_put (& pf_vdev -> vdev );
1614-
16151588 if (!match ) {
16161589 pci_info_ratelimited (vdev -> pdev ,
16171590 "Incorrect VF token provided for device\n" );
@@ -1732,8 +1705,30 @@ static int vfio_pci_bus_notifier(struct notifier_block *nb,
17321705static int vfio_pci_vf_init (struct vfio_pci_core_device * vdev )
17331706{
17341707 struct pci_dev * pdev = vdev -> pdev ;
1708+ struct vfio_pci_core_device * cur ;
1709+ struct pci_dev * physfn ;
17351710 int ret ;
17361711
1712+ if (pdev -> is_virtfn ) {
1713+ /*
1714+ * If this VF was created by our vfio_pci_core_sriov_configure()
1715+ * then we can find the PF vfio_pci_core_device now, and due to
1716+ * the locking in pci_disable_sriov() it cannot change until
1717+ * this VF device driver is removed.
1718+ */
1719+ physfn = pci_physfn (vdev -> pdev );
1720+ mutex_lock (& vfio_pci_sriov_pfs_mutex );
1721+ list_for_each_entry (cur , & vfio_pci_sriov_pfs , sriov_pfs_item ) {
1722+ if (cur -> pdev == physfn ) {
1723+ vdev -> sriov_pf_core_dev = cur ;
1724+ break ;
1725+ }
1726+ }
1727+ mutex_unlock (& vfio_pci_sriov_pfs_mutex );
1728+ return 0 ;
1729+ }
1730+
1731+ /* Not a SRIOV PF */
17371732 if (!pdev -> is_physfn )
17381733 return 0 ;
17391734
@@ -1805,6 +1800,7 @@ void vfio_pci_core_init_device(struct vfio_pci_core_device *vdev,
18051800 INIT_LIST_HEAD (& vdev -> ioeventfds_list );
18061801 mutex_init (& vdev -> vma_lock );
18071802 INIT_LIST_HEAD (& vdev -> vma_list );
1803+ INIT_LIST_HEAD (& vdev -> sriov_pfs_item );
18081804 init_rwsem (& vdev -> memory_lock );
18091805}
18101806EXPORT_SYMBOL_GPL (vfio_pci_core_init_device );
@@ -1896,7 +1892,7 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev)
18961892{
18971893 struct pci_dev * pdev = vdev -> pdev ;
18981894
1899- pci_disable_sriov (pdev );
1895+ vfio_pci_core_sriov_configure (pdev , 0 );
19001896
19011897 vfio_unregister_group_dev (& vdev -> vdev );
19021898
@@ -1935,21 +1931,49 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_aer_err_detected);
19351931
19361932int vfio_pci_core_sriov_configure (struct pci_dev * pdev , int nr_virtfn )
19371933{
1934+ struct vfio_pci_core_device * vdev ;
19381935 struct vfio_device * device ;
19391936 int ret = 0 ;
19401937
1938+ device_lock_assert (& pdev -> dev );
1939+
19411940 device = vfio_device_get_from_dev (& pdev -> dev );
19421941 if (!device )
19431942 return - ENODEV ;
19441943
1945- if (nr_virtfn == 0 )
1946- pci_disable_sriov (pdev );
1947- else
1944+ vdev = container_of (device , struct vfio_pci_core_device , vdev );
1945+
1946+ if (nr_virtfn ) {
1947+ mutex_lock (& vfio_pci_sriov_pfs_mutex );
1948+ /*
1949+ * The thread that adds the vdev to the list is the only thread
1950+ * that gets to call pci_enable_sriov() and we will only allow
1951+ * it to be called once without going through
1952+ * pci_disable_sriov()
1953+ */
1954+ if (!list_empty (& vdev -> sriov_pfs_item )) {
1955+ ret = - EINVAL ;
1956+ goto out_unlock ;
1957+ }
1958+ list_add_tail (& vdev -> sriov_pfs_item , & vfio_pci_sriov_pfs );
1959+ mutex_unlock (& vfio_pci_sriov_pfs_mutex );
19481960 ret = pci_enable_sriov (pdev , nr_virtfn );
1961+ if (ret )
1962+ goto out_del ;
1963+ ret = nr_virtfn ;
1964+ goto out_put ;
1965+ }
19491966
1950- vfio_device_put ( device );
1967+ pci_disable_sriov ( pdev );
19511968
1952- return ret < 0 ? ret : nr_virtfn ;
1969+ out_del :
1970+ mutex_lock (& vfio_pci_sriov_pfs_mutex );
1971+ list_del_init (& vdev -> sriov_pfs_item );
1972+ out_unlock :
1973+ mutex_unlock (& vfio_pci_sriov_pfs_mutex );
1974+ out_put :
1975+ vfio_device_put (device );
1976+ return ret ;
19531977}
19541978EXPORT_SYMBOL_GPL (vfio_pci_core_sriov_configure );
19551979
0 commit comments