3535 * PASIDs are global address space identifiers that can be shared
3636 * between the GPU, an IOMMU and the driver. VMs on different devices
3737 * may use the same PASID if they share the same address
38- * space. Therefore PASIDs are allocated using a global IDA. VMs are
39- * looked up from the PASID per amdgpu_device.
38+ * space. Therefore PASIDs are allocated using IDR cyclic allocator
39+ * (similar to kernel PID allocation) which naturally delays reuse.
40+ * VMs are looked up from the PASID per amdgpu_device.
4041 */
41- static DEFINE_IDA (amdgpu_pasid_ida );
42+
43+ static DEFINE_IDR (amdgpu_pasid_idr );
44+ static DEFINE_SPINLOCK (amdgpu_pasid_idr_lock );
4245
4346/* Helper to free pasid from a fence callback */
4447struct amdgpu_pasid_cb {
@@ -50,23 +53,24 @@ struct amdgpu_pasid_cb {
5053 * amdgpu_pasid_alloc - Allocate a PASID
5154 * @bits: Maximum width of the PASID in bits, must be at least 1
5255 *
53- * Allocates a PASID of the given width while keeping smaller PASIDs
54- * available if possible .
56+ * Uses kernel's IDR cyclic allocator (same as PID allocation).
57+ * Allocates sequentially with automatic wrap-around .
5558 *
5659 * Returns a positive integer on success. Returns %-EINVAL if bits==0.
5760 * Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on
5861 * memory allocation failure.
5962 */
6063int amdgpu_pasid_alloc (unsigned int bits )
6164{
62- int pasid = - EINVAL ;
65+ int pasid ;
6366
64- for (bits = min (bits , 31U ); bits > 0 ; bits -- ) {
65- pasid = ida_alloc_range (& amdgpu_pasid_ida , 1U << (bits - 1 ),
66- (1U << bits ) - 1 , GFP_KERNEL );
67- if (pasid != - ENOSPC )
68- break ;
69- }
67+ if (bits == 0 )
68+ return - EINVAL ;
69+
70+ spin_lock (& amdgpu_pasid_idr_lock );
71+ pasid = idr_alloc_cyclic (& amdgpu_pasid_idr , NULL , 1 ,
72+ 1U << bits , GFP_KERNEL );
73+ spin_unlock (& amdgpu_pasid_idr_lock );
7074
7175 if (pasid >= 0 )
7276 trace_amdgpu_pasid_allocated (pasid );
@@ -81,7 +85,10 @@ int amdgpu_pasid_alloc(unsigned int bits)
8185void amdgpu_pasid_free (u32 pasid )
8286{
8387 trace_amdgpu_pasid_freed (pasid );
84- ida_free (& amdgpu_pasid_ida , pasid );
88+
89+ spin_lock (& amdgpu_pasid_idr_lock );
90+ idr_remove (& amdgpu_pasid_idr , pasid );
91+ spin_unlock (& amdgpu_pasid_idr_lock );
8592}
8693
8794static void amdgpu_pasid_free_cb (struct dma_fence * fence ,
@@ -616,3 +623,15 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)
616623 }
617624 }
618625}
626+
627+ /**
628+ * amdgpu_pasid_mgr_cleanup - cleanup PASID manager
629+ *
630+ * Cleanup the IDR allocator.
631+ */
632+ void amdgpu_pasid_mgr_cleanup (void )
633+ {
634+ spin_lock (& amdgpu_pasid_idr_lock );
635+ idr_destroy (& amdgpu_pasid_idr );
636+ spin_unlock (& amdgpu_pasid_idr_lock );
637+ }
0 commit comments