4444/* list of all detected zpci devices */
4545static LIST_HEAD (zpci_list );
4646static DEFINE_SPINLOCK (zpci_list_lock );
47+ static DEFINE_MUTEX (zpci_add_remove_lock );
4748
4849static DECLARE_BITMAP (zpci_domain , ZPCI_DOMAIN_BITMAP_SIZE ) ;
4950static DEFINE_SPINLOCK (zpci_domain_lock );
@@ -69,6 +70,15 @@ EXPORT_SYMBOL_GPL(zpci_aipb);
6970struct airq_iv * zpci_aif_sbv ;
7071EXPORT_SYMBOL_GPL (zpci_aif_sbv );
7172
73+ void zpci_zdev_put (struct zpci_dev * zdev )
74+ {
75+ if (!zdev )
76+ return ;
77+ mutex_lock (& zpci_add_remove_lock );
78+ kref_put_lock (& zdev -> kref , zpci_release_device , & zpci_list_lock );
79+ mutex_unlock (& zpci_add_remove_lock );
80+ }
81+
7282struct zpci_dev * get_zdev_by_fid (u32 fid )
7383{
7484 struct zpci_dev * tmp , * zdev = NULL ;
@@ -831,6 +841,7 @@ int zpci_add_device(struct zpci_dev *zdev)
831841{
832842 int rc ;
833843
844+ mutex_lock (& zpci_add_remove_lock );
834845 zpci_dbg (1 , "add fid:%x, fh:%x, c:%d\n" , zdev -> fid , zdev -> fh , zdev -> state );
835846 rc = zpci_init_iommu (zdev );
836847 if (rc )
@@ -844,12 +855,14 @@ int zpci_add_device(struct zpci_dev *zdev)
844855 spin_lock (& zpci_list_lock );
845856 list_add_tail (& zdev -> entry , & zpci_list );
846857 spin_unlock (& zpci_list_lock );
858+ mutex_unlock (& zpci_add_remove_lock );
847859 return 0 ;
848860
849861error_destroy_iommu :
850862 zpci_destroy_iommu (zdev );
851863error :
852864 zpci_dbg (0 , "add fid:%x, rc:%d\n" , zdev -> fid , rc );
865+ mutex_unlock (& zpci_add_remove_lock );
853866 return rc ;
854867}
855868
@@ -919,60 +932,44 @@ int zpci_deconfigure_device(struct zpci_dev *zdev)
919932 * @zdev: the zpci_dev that was reserved
920933 *
921934 * Handle the case that a given zPCI function was reserved by another system.
922- * After a call to this function the zpci_dev can not be found via
923- * get_zdev_by_fid() anymore but may still be accessible via existing
924- * references though it will not be functional anymore.
925935 */
926936void zpci_device_reserved (struct zpci_dev * zdev )
927937{
928- /*
929- * Remove device from zpci_list as it is going away. This also
930- * makes sure we ignore subsequent zPCI events for this device.
931- */
932- spin_lock (& zpci_list_lock );
933- list_del (& zdev -> entry );
934- spin_unlock (& zpci_list_lock );
938+ lockdep_assert_held (& zdev -> state_lock );
939+ /* We may declare the device reserved multiple times */
940+ if (zdev -> state == ZPCI_FN_STATE_RESERVED )
941+ return ;
935942 zdev -> state = ZPCI_FN_STATE_RESERVED ;
936943 zpci_dbg (3 , "rsv fid:%x\n" , zdev -> fid );
944+ /*
945+ * The underlying device is gone. Allow the zdev to be freed
946+ * as soon as all other references are gone by accounting for
947+ * the removal as a dropped reference.
948+ */
937949 zpci_zdev_put (zdev );
938950}
939951
940952void zpci_release_device (struct kref * kref )
941953{
942954 struct zpci_dev * zdev = container_of (kref , struct zpci_dev , kref );
943- int ret ;
955+
956+ lockdep_assert_held (& zpci_add_remove_lock );
957+ WARN_ON (zdev -> state != ZPCI_FN_STATE_RESERVED );
958+ /*
959+ * We already hold zpci_list_lock thanks to kref_put_lock().
960+ * This makes sure no new reference can be taken from the list.
961+ */
962+ list_del (& zdev -> entry );
963+ spin_unlock (& zpci_list_lock );
944964
945965 if (zdev -> has_hp_slot )
946966 zpci_exit_slot (zdev );
947967
948- if (zdev -> zbus -> bus )
949- zpci_bus_remove_device (zdev , false);
950-
951- if (zdev_enabled (zdev ))
952- zpci_disable_device (zdev );
968+ if (zdev -> has_resources )
969+ zpci_cleanup_bus_resources (zdev );
953970
954- switch (zdev -> state ) {
955- case ZPCI_FN_STATE_CONFIGURED :
956- ret = sclp_pci_deconfigure (zdev -> fid );
957- zpci_dbg (3 , "deconf fid:%x, rc:%d\n" , zdev -> fid , ret );
958- fallthrough ;
959- case ZPCI_FN_STATE_STANDBY :
960- if (zdev -> has_hp_slot )
961- zpci_exit_slot (zdev );
962- spin_lock (& zpci_list_lock );
963- list_del (& zdev -> entry );
964- spin_unlock (& zpci_list_lock );
965- zpci_dbg (3 , "rsv fid:%x\n" , zdev -> fid );
966- fallthrough ;
967- case ZPCI_FN_STATE_RESERVED :
968- if (zdev -> has_resources )
969- zpci_cleanup_bus_resources (zdev );
970- zpci_bus_device_unregister (zdev );
971- zpci_destroy_iommu (zdev );
972- fallthrough ;
973- default :
974- break ;
975- }
971+ zpci_bus_device_unregister (zdev );
972+ zpci_destroy_iommu (zdev );
976973 zpci_dbg (3 , "rem fid:%x\n" , zdev -> fid );
977974 kfree_rcu (zdev , rcu );
978975}
0 commit comments