@@ -33,13 +33,21 @@ enum {
3333
3434#define VHOST_VDPA_DEV_MAX (1U << MINORBITS)
3535
36+ #define VHOST_VDPA_IOTLB_BUCKETS 16
37+
38+ struct vhost_vdpa_as {
39+ struct hlist_node hash_link ;
40+ struct vhost_iotlb iotlb ;
41+ u32 id ;
42+ };
43+
3644struct vhost_vdpa {
3745 struct vhost_dev vdev ;
3846 struct iommu_domain * domain ;
3947 struct vhost_virtqueue * vqs ;
4048 struct completion completion ;
4149 struct vdpa_device * vdpa ;
42- struct vhost_iotlb * iotlb ;
50+ struct hlist_head as [ VHOST_VDPA_IOTLB_BUCKETS ] ;
4351 struct device dev ;
4452 struct cdev cdev ;
4553 atomic_t opened ;
@@ -55,6 +63,51 @@ static DEFINE_IDA(vhost_vdpa_ida);
5563
5664static dev_t vhost_vdpa_major ;
5765
66+ static struct vhost_vdpa_as * asid_to_as (struct vhost_vdpa * v , u32 asid )
67+ {
68+ struct hlist_head * head = & v -> as [asid % VHOST_VDPA_IOTLB_BUCKETS ];
69+ struct vhost_vdpa_as * as ;
70+
71+ hlist_for_each_entry (as , head , hash_link )
72+ if (as -> id == asid )
73+ return as ;
74+
75+ return NULL ;
76+ }
77+
78+ static struct vhost_vdpa_as * vhost_vdpa_alloc_as (struct vhost_vdpa * v , u32 asid )
79+ {
80+ struct hlist_head * head = & v -> as [asid % VHOST_VDPA_IOTLB_BUCKETS ];
81+ struct vhost_vdpa_as * as ;
82+
83+ if (asid_to_as (v , asid ))
84+ return NULL ;
85+
86+ as = kmalloc (sizeof (* as ), GFP_KERNEL );
87+ if (!as )
88+ return NULL ;
89+
90+ vhost_iotlb_init (& as -> iotlb , 0 , 0 );
91+ as -> id = asid ;
92+ hlist_add_head (& as -> hash_link , head );
93+
94+ return as ;
95+ }
96+
97+ static int vhost_vdpa_remove_as (struct vhost_vdpa * v , u32 asid )
98+ {
99+ struct vhost_vdpa_as * as = asid_to_as (v , asid );
100+
101+ if (!as )
102+ return - EINVAL ;
103+
104+ hlist_del (& as -> hash_link );
105+ vhost_iotlb_reset (& as -> iotlb );
106+ kfree (as );
107+
108+ return 0 ;
109+ }
110+
58111static void handle_vq_kick (struct vhost_work * work )
59112{
60113 struct vhost_virtqueue * vq = container_of (work , struct vhost_virtqueue ,
@@ -588,15 +641,6 @@ static void vhost_vdpa_iotlb_unmap(struct vhost_vdpa *v,
588641 return vhost_vdpa_pa_unmap (v , iotlb , start , last );
589642}
590643
591- static void vhost_vdpa_iotlb_free (struct vhost_vdpa * v )
592- {
593- struct vhost_iotlb * iotlb = v -> iotlb ;
594-
595- vhost_vdpa_iotlb_unmap (v , iotlb , 0ULL , 0ULL - 1 );
596- kfree (v -> iotlb );
597- v -> iotlb = NULL ;
598- }
599-
600644static int perm_to_iommu_flags (u32 perm )
601645{
602646 int flags = 0 ;
@@ -876,7 +920,8 @@ static int vhost_vdpa_process_iotlb_msg(struct vhost_dev *dev, u32 asid,
876920 struct vhost_vdpa * v = container_of (dev , struct vhost_vdpa , vdev );
877921 struct vdpa_device * vdpa = v -> vdpa ;
878922 const struct vdpa_config_ops * ops = vdpa -> config ;
879- struct vhost_iotlb * iotlb = v -> iotlb ;
923+ struct vhost_vdpa_as * as = asid_to_as (v , 0 );
924+ struct vhost_iotlb * iotlb = & as -> iotlb ;
880925 int r = 0 ;
881926
882927 if (asid != 0 )
@@ -987,6 +1032,13 @@ static void vhost_vdpa_set_iova_range(struct vhost_vdpa *v)
9871032 }
9881033}
9891034
1035+ static void vhost_vdpa_cleanup (struct vhost_vdpa * v )
1036+ {
1037+ vhost_dev_cleanup (& v -> vdev );
1038+ kfree (v -> vdev .vqs );
1039+ vhost_vdpa_remove_as (v , 0 );
1040+ }
1041+
9901042static int vhost_vdpa_open (struct inode * inode , struct file * filep )
9911043{
9921044 struct vhost_vdpa * v ;
@@ -1020,27 +1072,21 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep)
10201072 vhost_dev_init (dev , vqs , nvqs , 0 , 0 , 0 , false,
10211073 vhost_vdpa_process_iotlb_msg );
10221074
1023- v -> iotlb = vhost_iotlb_alloc (0 , 0 );
1024- if (!v -> iotlb ) {
1025- r = - ENOMEM ;
1026- goto err_init_iotlb ;
1027- }
1075+ if (!vhost_vdpa_alloc_as (v , 0 ))
1076+ goto err_alloc_as ;
10281077
10291078 r = vhost_vdpa_alloc_domain (v );
10301079 if (r )
1031- goto err_alloc_domain ;
1080+ goto err_alloc_as ;
10321081
10331082 vhost_vdpa_set_iova_range (v );
10341083
10351084 filep -> private_data = v ;
10361085
10371086 return 0 ;
10381087
1039- err_alloc_domain :
1040- vhost_vdpa_iotlb_free (v );
1041- err_init_iotlb :
1042- vhost_dev_cleanup (& v -> vdev );
1043- kfree (vqs );
1088+ err_alloc_as :
1089+ vhost_vdpa_cleanup (v );
10441090err :
10451091 atomic_dec (& v -> opened );
10461092 return r ;
@@ -1064,11 +1110,9 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep)
10641110 vhost_vdpa_clean_irq (v );
10651111 vhost_vdpa_reset (v );
10661112 vhost_dev_stop (& v -> vdev );
1067- vhost_vdpa_iotlb_free (v );
10681113 vhost_vdpa_free_domain (v );
10691114 vhost_vdpa_config_put (v );
10701115 vhost_dev_cleanup (& v -> vdev );
1071- kfree (v -> vdev .vqs );
10721116 mutex_unlock (& d -> mutex );
10731117
10741118 atomic_dec (& v -> opened );
@@ -1164,7 +1208,7 @@ static int vhost_vdpa_probe(struct vdpa_device *vdpa)
11641208 const struct vdpa_config_ops * ops = vdpa -> config ;
11651209 struct vhost_vdpa * v ;
11661210 int minor ;
1167- int r ;
1211+ int i , r ;
11681212
11691213 /* Only support 1 address space and 1 groups */
11701214 if (vdpa -> ngroups != 1 || vdpa -> nas != 1 )
@@ -1212,6 +1256,9 @@ static int vhost_vdpa_probe(struct vdpa_device *vdpa)
12121256 init_completion (& v -> completion );
12131257 vdpa_set_drvdata (vdpa , v );
12141258
1259+ for (i = 0 ; i < VHOST_VDPA_IOTLB_BUCKETS ; i ++ )
1260+ INIT_HLIST_HEAD (& v -> as [i ]);
1261+
12151262 return 0 ;
12161263
12171264err :
0 commit comments