@@ -62,11 +62,16 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
62
62
63
63
void msm_gem_submit_free (struct msm_gem_submit * submit )
64
64
{
65
+ unsigned i ;
66
+
65
67
dma_fence_put (submit -> fence );
66
68
list_del (& submit -> node );
67
69
put_pid (submit -> pid );
68
70
msm_submitqueue_put (submit -> queue );
69
71
72
+ for (i = 0 ; i < submit -> nr_cmds ; i ++ )
73
+ kfree (submit -> cmd [i ].relocs );
74
+
70
75
kfree (submit );
71
76
}
72
77
@@ -150,6 +155,66 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
150
155
return ret ;
151
156
}
152
157
158
+ static int submit_lookup_cmds (struct msm_gem_submit * submit ,
159
+ struct drm_msm_gem_submit * args , struct drm_file * file )
160
+ {
161
+ unsigned i , sz ;
162
+ int ret = 0 ;
163
+
164
+ for (i = 0 ; i < args -> nr_cmds ; i ++ ) {
165
+ struct drm_msm_gem_submit_cmd submit_cmd ;
166
+ void __user * userptr =
167
+ u64_to_user_ptr (args -> cmds + (i * sizeof (submit_cmd )));
168
+
169
+ ret = copy_from_user (& submit_cmd , userptr , sizeof (submit_cmd ));
170
+ if (ret ) {
171
+ ret = - EFAULT ;
172
+ goto out ;
173
+ }
174
+
175
+ /* validate input from userspace: */
176
+ switch (submit_cmd .type ) {
177
+ case MSM_SUBMIT_CMD_BUF :
178
+ case MSM_SUBMIT_CMD_IB_TARGET_BUF :
179
+ case MSM_SUBMIT_CMD_CTX_RESTORE_BUF :
180
+ break ;
181
+ default :
182
+ DRM_ERROR ("invalid type: %08x\n" , submit_cmd .type );
183
+ return - EINVAL ;
184
+ }
185
+
186
+ if (submit_cmd .size % 4 ) {
187
+ DRM_ERROR ("non-aligned cmdstream buffer size: %u\n" ,
188
+ submit_cmd .size );
189
+ ret = - EINVAL ;
190
+ goto out ;
191
+ }
192
+
193
+ submit -> cmd [i ].type = submit_cmd .type ;
194
+ submit -> cmd [i ].size = submit_cmd .size / 4 ;
195
+ submit -> cmd [i ].offset = submit_cmd .submit_offset / 4 ;
196
+ submit -> cmd [i ].idx = submit_cmd .submit_idx ;
197
+ submit -> cmd [i ].nr_relocs = submit_cmd .nr_relocs ;
198
+
199
+ sz = array_size (submit_cmd .nr_relocs ,
200
+ sizeof (struct drm_msm_gem_submit_reloc ));
201
+ /* check for overflow: */
202
+ if (sz == SIZE_MAX ) {
203
+ ret = - ENOMEM ;
204
+ goto out ;
205
+ }
206
+ submit -> cmd [i ].relocs = kmalloc (sz , GFP_KERNEL );
207
+ ret = copy_from_user (submit -> cmd [i ].relocs , userptr , sz );
208
+ if (ret ) {
209
+ ret = - EFAULT ;
210
+ goto out ;
211
+ }
212
+ }
213
+
214
+ out :
215
+ return ret ;
216
+ }
217
+
153
218
static void submit_unlock_unpin_bo (struct msm_gem_submit * submit ,
154
219
int i , bool backoff )
155
220
{
@@ -301,7 +366,7 @@ static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
301
366
302
367
/* process the reloc's and patch up the cmdstream as needed: */
303
368
static int submit_reloc (struct msm_gem_submit * submit , struct msm_gem_object * obj ,
304
- uint32_t offset , uint32_t nr_relocs , uint64_t relocs )
369
+ uint32_t offset , uint32_t nr_relocs , struct drm_msm_gem_submit_reloc * relocs )
305
370
{
306
371
uint32_t i , last_offset = 0 ;
307
372
uint32_t * ptr ;
@@ -327,18 +392,11 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
327
392
}
328
393
329
394
for (i = 0 ; i < nr_relocs ; i ++ ) {
330
- struct drm_msm_gem_submit_reloc submit_reloc ;
331
- void __user * userptr =
332
- u64_to_user_ptr (relocs + (i * sizeof (submit_reloc )));
395
+ struct drm_msm_gem_submit_reloc submit_reloc = relocs [i ];
333
396
uint32_t off ;
334
397
uint64_t iova ;
335
398
bool valid ;
336
399
337
- if (copy_from_user (& submit_reloc , userptr , sizeof (submit_reloc ))) {
338
- ret = - EFAULT ;
339
- goto out ;
340
- }
341
-
342
400
if (submit_reloc .submit_offset % 4 ) {
343
401
DRM_ERROR ("non-aligned reloc offset: %u\n" ,
344
402
submit_reloc .submit_offset );
@@ -694,6 +752,10 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
694
752
if (ret )
695
753
goto out ;
696
754
755
+ ret = submit_lookup_cmds (submit , args , file );
756
+ if (ret )
757
+ goto out ;
758
+
697
759
/* copy_*_user while holding a ww ticket upsets lockdep */
698
760
ww_acquire_init (& submit -> ticket , & reservation_ww_class );
699
761
has_ww_ticket = true;
@@ -710,60 +772,29 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
710
772
goto out ;
711
773
712
774
for (i = 0 ; i < args -> nr_cmds ; i ++ ) {
713
- struct drm_msm_gem_submit_cmd submit_cmd ;
714
- void __user * userptr =
715
- u64_to_user_ptr (args -> cmds + (i * sizeof (submit_cmd )));
716
775
struct msm_gem_object * msm_obj ;
717
776
uint64_t iova ;
718
777
719
- ret = copy_from_user (& submit_cmd , userptr , sizeof (submit_cmd ));
720
- if (ret ) {
721
- ret = - EFAULT ;
722
- goto out ;
723
- }
724
-
725
- /* validate input from userspace: */
726
- switch (submit_cmd .type ) {
727
- case MSM_SUBMIT_CMD_BUF :
728
- case MSM_SUBMIT_CMD_IB_TARGET_BUF :
729
- case MSM_SUBMIT_CMD_CTX_RESTORE_BUF :
730
- break ;
731
- default :
732
- DRM_ERROR ("invalid type: %08x\n" , submit_cmd .type );
733
- ret = - EINVAL ;
734
- goto out ;
735
- }
736
-
737
- ret = submit_bo (submit , submit_cmd .submit_idx ,
778
+ ret = submit_bo (submit , submit -> cmd [i ].idx ,
738
779
& msm_obj , & iova , NULL );
739
780
if (ret )
740
781
goto out ;
741
782
742
- if (submit_cmd .size % 4 ) {
743
- DRM_ERROR ("non-aligned cmdstream buffer size: %u\n" ,
744
- submit_cmd .size );
783
+ if (!submit -> cmd [i ].size ||
784
+ ((submit -> cmd [i ].size + submit -> cmd [i ].offset ) >
785
+ msm_obj -> base .size / 4 )) {
786
+ DRM_ERROR ("invalid cmdstream size: %u\n" , submit -> cmd [i ].size * 4 );
745
787
ret = - EINVAL ;
746
788
goto out ;
747
789
}
748
790
749
- if (!submit_cmd .size ||
750
- ((submit_cmd .size + submit_cmd .submit_offset ) >
751
- msm_obj -> base .size )) {
752
- DRM_ERROR ("invalid cmdstream size: %u\n" , submit_cmd .size );
753
- ret = - EINVAL ;
754
- goto out ;
755
- }
756
-
757
- submit -> cmd [i ].type = submit_cmd .type ;
758
- submit -> cmd [i ].size = submit_cmd .size / 4 ;
759
- submit -> cmd [i ].iova = iova + submit_cmd .submit_offset ;
760
- submit -> cmd [i ].idx = submit_cmd .submit_idx ;
791
+ submit -> cmd [i ].iova = iova + (submit -> cmd [i ].offset * 4 );
761
792
762
793
if (submit -> valid )
763
794
continue ;
764
795
765
- ret = submit_reloc (submit , msm_obj , submit_cmd . submit_offset ,
766
- submit_cmd .nr_relocs , submit_cmd .relocs );
796
+ ret = submit_reloc (submit , msm_obj , submit -> cmd [ i ]. offset * 4 ,
797
+ submit -> cmd [ i ] .nr_relocs , submit -> cmd [ i ] .relocs );
767
798
if (ret )
768
799
goto out ;
769
800
}
0 commit comments