@@ -562,6 +562,7 @@ nouveau_drm_device_init(struct drm_device *dev)
562562 nvkm_dbgopt (nouveau_debug , "DRM" );
563563
564564 INIT_LIST_HEAD (& drm -> clients );
565+ mutex_init (& drm -> clients_lock );
565566 spin_lock_init (& drm -> tile .lock );
566567
567568 /* workaround an odd issue on nvc1 by disabling the device's
@@ -632,6 +633,7 @@ nouveau_drm_device_init(struct drm_device *dev)
632633static void
633634nouveau_drm_device_fini (struct drm_device * dev )
634635{
636+ struct nouveau_cli * cli , * temp_cli ;
635637 struct nouveau_drm * drm = nouveau_drm (dev );
636638
637639 if (nouveau_pmops_runtime ()) {
@@ -656,9 +658,28 @@ nouveau_drm_device_fini(struct drm_device *dev)
656658 nouveau_ttm_fini (drm );
657659 nouveau_vga_fini (drm );
658660
661+ /*
662+ * There may be existing clients from as-yet unclosed files. For now,
663+ * clean them up here rather than deferring until the file is closed,
664+ * but this likely not correct if we want to support hot-unplugging
665+ * properly.
666+ */
667+ mutex_lock (& drm -> clients_lock );
668+ list_for_each_entry_safe (cli , temp_cli , & drm -> clients , head ) {
669+ list_del (& cli -> head );
670+ mutex_lock (& cli -> mutex );
671+ if (cli -> abi16 )
672+ nouveau_abi16_fini (cli -> abi16 );
673+ mutex_unlock (& cli -> mutex );
674+ nouveau_cli_fini (cli );
675+ kfree (cli );
676+ }
677+ mutex_unlock (& drm -> clients_lock );
678+
659679 nouveau_cli_fini (& drm -> client );
660680 nouveau_cli_fini (& drm -> master );
661681 nvif_parent_dtor (& drm -> parent );
682+ mutex_destroy (& drm -> clients_lock );
662683 kfree (drm );
663684}
664685
@@ -796,7 +817,7 @@ nouveau_drm_device_remove(struct drm_device *dev)
796817 struct nvkm_client * client ;
797818 struct nvkm_device * device ;
798819
799- drm_dev_unregister (dev );
820+ drm_dev_unplug (dev );
800821
801822 client = nvxx_client (& drm -> client .base );
802823 device = nvkm_device_find (client -> device );
@@ -1090,9 +1111,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
10901111
10911112 fpriv -> driver_priv = cli ;
10921113
1093- mutex_lock (& drm -> client . mutex );
1114+ mutex_lock (& drm -> clients_lock );
10941115 list_add (& cli -> head , & drm -> clients );
1095- mutex_unlock (& drm -> client . mutex );
1116+ mutex_unlock (& drm -> clients_lock );
10961117
10971118done :
10981119 if (ret && cli ) {
@@ -1110,6 +1131,16 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
11101131{
11111132 struct nouveau_cli * cli = nouveau_cli (fpriv );
11121133 struct nouveau_drm * drm = nouveau_drm (dev );
1134+ int dev_index ;
1135+
1136+ /*
1137+ * The device is gone, and as it currently stands all clients are
1138+ * cleaned up in the removal codepath. In the future this may change
1139+ * so that we can support hot-unplugging, but for now we immediately
1140+ * return to avoid a double-free situation.
1141+ */
1142+ if (!drm_dev_enter (dev , & dev_index ))
1143+ return ;
11131144
11141145 pm_runtime_get_sync (dev -> dev );
11151146
@@ -1118,14 +1149,15 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
11181149 nouveau_abi16_fini (cli -> abi16 );
11191150 mutex_unlock (& cli -> mutex );
11201151
1121- mutex_lock (& drm -> client . mutex );
1152+ mutex_lock (& drm -> clients_lock );
11221153 list_del (& cli -> head );
1123- mutex_unlock (& drm -> client . mutex );
1154+ mutex_unlock (& drm -> clients_lock );
11241155
11251156 nouveau_cli_fini (cli );
11261157 kfree (cli );
11271158 pm_runtime_mark_last_busy (dev -> dev );
11281159 pm_runtime_put_autosuspend (dev -> dev );
1160+ drm_dev_exit (dev_index );
11291161}
11301162
11311163static const struct drm_ioctl_desc
0 commit comments