@@ -65,6 +65,18 @@ static void cs_put(struct hl_cs *cs)
65
65
kref_put (& cs -> refcount , cs_do_release );
66
66
}
67
67
68
+ static bool is_cb_patched (struct hl_device * hdev , struct hl_cs_job * job )
69
+ {
70
+ /*
71
+ * Patched CB is created for external queues jobs, and for H/W queues
72
+ * jobs if the user CB was allocated by driver and MMU is disabled.
73
+ */
74
+ return (job -> queue_type == QUEUE_TYPE_EXT ||
75
+ (job -> queue_type == QUEUE_TYPE_HW &&
76
+ job -> is_kernel_allocated_cb &&
77
+ !hdev -> mmu_enable ));
78
+ }
79
+
68
80
/*
69
81
* cs_parser - parse the user command submission
70
82
*
@@ -91,11 +103,13 @@ static int cs_parser(struct hl_fpriv *hpriv, struct hl_cs_job *job)
91
103
parser .patched_cb = NULL ;
92
104
parser .user_cb = job -> user_cb ;
93
105
parser .user_cb_size = job -> user_cb_size ;
94
- parser .ext_queue = job -> ext_queue ;
106
+ parser .queue_type = job -> queue_type ;
107
+ parser .is_kernel_allocated_cb = job -> is_kernel_allocated_cb ;
95
108
job -> patched_cb = NULL ;
96
109
97
110
rc = hdev -> asic_funcs -> cs_parser (hdev , & parser );
98
- if (job -> ext_queue ) {
111
+
112
+ if (is_cb_patched (hdev , job )) {
99
113
if (!rc ) {
100
114
job -> patched_cb = parser .patched_cb ;
101
115
job -> job_cb_size = parser .patched_cb_size ;
@@ -124,7 +138,7 @@ static void free_job(struct hl_device *hdev, struct hl_cs_job *job)
124
138
{
125
139
struct hl_cs * cs = job -> cs ;
126
140
127
- if (job -> ext_queue ) {
141
+ if (is_cb_patched ( hdev , job ) ) {
128
142
hl_userptr_delete_list (hdev , & job -> userptr_list );
129
143
130
144
/*
@@ -140,6 +154,19 @@ static void free_job(struct hl_device *hdev, struct hl_cs_job *job)
140
154
}
141
155
}
142
156
157
+ /* For H/W queue jobs, if a user CB was allocated by driver and MMU is
158
+ * enabled, the user CB isn't released in cs_parser() and thus should be
159
+ * released here.
160
+ */
161
+ if (job -> queue_type == QUEUE_TYPE_HW &&
162
+ job -> is_kernel_allocated_cb && hdev -> mmu_enable ) {
163
+ spin_lock (& job -> user_cb -> lock );
164
+ job -> user_cb -> cs_cnt -- ;
165
+ spin_unlock (& job -> user_cb -> lock );
166
+
167
+ hl_cb_put (job -> user_cb );
168
+ }
169
+
143
170
/*
144
171
* This is the only place where there can be multiple threads
145
172
* modifying the list at the same time
@@ -150,7 +177,8 @@ static void free_job(struct hl_device *hdev, struct hl_cs_job *job)
150
177
151
178
hl_debugfs_remove_job (hdev , job );
152
179
153
- if (job -> ext_queue )
180
+ if (job -> queue_type == QUEUE_TYPE_EXT ||
181
+ job -> queue_type == QUEUE_TYPE_HW )
154
182
cs_put (cs );
155
183
156
184
kfree (job );
@@ -387,39 +415,43 @@ static void job_wq_completion(struct work_struct *work)
387
415
free_job (hdev , job );
388
416
}
389
417
390
- static struct hl_cb * validate_queue_index (struct hl_device * hdev ,
391
- struct hl_cb_mgr * cb_mgr ,
392
- struct hl_cs_chunk * chunk ,
393
- bool * ext_queue )
418
+ static int validate_queue_index (struct hl_device * hdev ,
419
+ struct hl_cs_chunk * chunk ,
420
+ enum hl_queue_type * queue_type ,
421
+ bool * is_kernel_allocated_cb )
394
422
{
395
423
struct asic_fixed_properties * asic = & hdev -> asic_prop ;
396
424
struct hw_queue_properties * hw_queue_prop ;
397
- u32 cb_handle ;
398
- struct hl_cb * cb ;
399
-
400
- /* Assume external queue */
401
- * ext_queue = true;
402
425
403
426
hw_queue_prop = & asic -> hw_queues_props [chunk -> queue_index ];
404
427
405
428
if ((chunk -> queue_index >= HL_MAX_QUEUES ) ||
406
429
(hw_queue_prop -> type == QUEUE_TYPE_NA )) {
407
430
dev_err (hdev -> dev , "Queue index %d is invalid\n" ,
408
431
chunk -> queue_index );
409
- return NULL ;
432
+ return - EINVAL ;
410
433
}
411
434
412
435
if (hw_queue_prop -> driver_only ) {
413
436
dev_err (hdev -> dev ,
414
437
"Queue index %d is restricted for the kernel driver\n" ,
415
438
chunk -> queue_index );
416
- return NULL ;
417
- } else if (hw_queue_prop -> type == QUEUE_TYPE_INT ) {
418
- * ext_queue = false;
419
- return (struct hl_cb * ) (uintptr_t ) chunk -> cb_handle ;
439
+ return - EINVAL ;
420
440
}
421
441
422
- /* Retrieve CB object */
442
+ * queue_type = hw_queue_prop -> type ;
443
+ * is_kernel_allocated_cb = !!hw_queue_prop -> requires_kernel_cb ;
444
+
445
+ return 0 ;
446
+ }
447
+
448
+ static struct hl_cb * get_cb_from_cs_chunk (struct hl_device * hdev ,
449
+ struct hl_cb_mgr * cb_mgr ,
450
+ struct hl_cs_chunk * chunk )
451
+ {
452
+ struct hl_cb * cb ;
453
+ u32 cb_handle ;
454
+
423
455
cb_handle = (u32 ) (chunk -> cb_handle >> PAGE_SHIFT );
424
456
425
457
cb = hl_cb_get (hdev , cb_mgr , cb_handle );
@@ -444,20 +476,23 @@ static struct hl_cb *validate_queue_index(struct hl_device *hdev,
444
476
return NULL ;
445
477
}
446
478
447
- struct hl_cs_job * hl_cs_allocate_job (struct hl_device * hdev , bool ext_queue )
479
+ struct hl_cs_job * hl_cs_allocate_job (struct hl_device * hdev ,
480
+ enum hl_queue_type queue_type , bool is_kernel_allocated_cb )
448
481
{
449
482
struct hl_cs_job * job ;
450
483
451
484
job = kzalloc (sizeof (* job ), GFP_ATOMIC );
452
485
if (!job )
453
486
return NULL ;
454
487
455
- job -> ext_queue = ext_queue ;
488
+ job -> queue_type = queue_type ;
489
+ job -> is_kernel_allocated_cb = is_kernel_allocated_cb ;
456
490
457
- if (job -> ext_queue ) {
491
+ if (is_cb_patched ( hdev , job ))
458
492
INIT_LIST_HEAD (& job -> userptr_list );
493
+
494
+ if (job -> queue_type == QUEUE_TYPE_EXT )
459
495
INIT_WORK (& job -> finish_work , job_wq_completion );
460
- }
461
496
462
497
return job ;
463
498
}
@@ -470,7 +505,7 @@ static int _hl_cs_ioctl(struct hl_fpriv *hpriv, void __user *chunks,
470
505
struct hl_cs_job * job ;
471
506
struct hl_cs * cs ;
472
507
struct hl_cb * cb ;
473
- bool ext_queue_present = false ;
508
+ bool int_queues_only = true ;
474
509
u32 size_to_copy ;
475
510
int rc , i , parse_cnt ;
476
511
@@ -514,23 +549,33 @@ static int _hl_cs_ioctl(struct hl_fpriv *hpriv, void __user *chunks,
514
549
/* Validate ALL the CS chunks before submitting the CS */
515
550
for (i = 0 , parse_cnt = 0 ; i < num_chunks ; i ++ , parse_cnt ++ ) {
516
551
struct hl_cs_chunk * chunk = & cs_chunk_array [i ];
517
- bool ext_queue ;
552
+ enum hl_queue_type queue_type ;
553
+ bool is_kernel_allocated_cb ;
554
+
555
+ rc = validate_queue_index (hdev , chunk , & queue_type ,
556
+ & is_kernel_allocated_cb );
557
+ if (rc )
558
+ goto free_cs_object ;
518
559
519
- cb = validate_queue_index (hdev , & hpriv -> cb_mgr , chunk ,
520
- & ext_queue );
521
- if (ext_queue ) {
522
- ext_queue_present = true;
560
+ if (is_kernel_allocated_cb ) {
561
+ cb = get_cb_from_cs_chunk (hdev , & hpriv -> cb_mgr , chunk );
523
562
if (!cb ) {
524
563
rc = - EINVAL ;
525
564
goto free_cs_object ;
526
565
}
566
+ } else {
567
+ cb = (struct hl_cb * ) (uintptr_t ) chunk -> cb_handle ;
527
568
}
528
569
529
- job = hl_cs_allocate_job (hdev , ext_queue );
570
+ if (queue_type == QUEUE_TYPE_EXT || queue_type == QUEUE_TYPE_HW )
571
+ int_queues_only = false;
572
+
573
+ job = hl_cs_allocate_job (hdev , queue_type ,
574
+ is_kernel_allocated_cb );
530
575
if (!job ) {
531
576
dev_err (hdev -> dev , "Failed to allocate a new job\n" );
532
577
rc = - ENOMEM ;
533
- if (ext_queue )
578
+ if (is_kernel_allocated_cb )
534
579
goto release_cb ;
535
580
else
536
581
goto free_cs_object ;
@@ -540,7 +585,7 @@ static int _hl_cs_ioctl(struct hl_fpriv *hpriv, void __user *chunks,
540
585
job -> cs = cs ;
541
586
job -> user_cb = cb ;
542
587
job -> user_cb_size = chunk -> cb_size ;
543
- if (job -> ext_queue )
588
+ if (is_kernel_allocated_cb )
544
589
job -> job_cb_size = cb -> size ;
545
590
else
546
591
job -> job_cb_size = chunk -> cb_size ;
@@ -553,10 +598,11 @@ static int _hl_cs_ioctl(struct hl_fpriv *hpriv, void __user *chunks,
553
598
/*
554
599
* Increment CS reference. When CS reference is 0, CS is
555
600
* done and can be signaled to user and free all its resources
556
- * Only increment for JOB on external queues, because only
557
- * for those JOBs we get completion
601
+ * Only increment for JOB on external or H/W queues, because
602
+ * only for those JOBs we get completion
558
603
*/
559
- if (job -> ext_queue )
604
+ if (job -> queue_type == QUEUE_TYPE_EXT ||
605
+ job -> queue_type == QUEUE_TYPE_HW )
560
606
cs_get (cs );
561
607
562
608
hl_debugfs_add_job (hdev , job );
@@ -570,19 +616,20 @@ static int _hl_cs_ioctl(struct hl_fpriv *hpriv, void __user *chunks,
570
616
}
571
617
}
572
618
573
- if (! ext_queue_present ) {
619
+ if (int_queues_only ) {
574
620
dev_err (hdev -> dev ,
575
- "Reject CS %d.%llu because no external queues jobs\n" ,
621
+ "Reject CS %d.%llu because only internal queues jobs are present \n" ,
576
622
cs -> ctx -> asid , cs -> sequence );
577
623
rc = - EINVAL ;
578
624
goto free_cs_object ;
579
625
}
580
626
581
627
rc = hl_hw_queue_schedule_cs (cs );
582
628
if (rc ) {
583
- dev_err (hdev -> dev ,
584
- "Failed to submit CS %d.%llu to H/W queues, error %d\n" ,
585
- cs -> ctx -> asid , cs -> sequence , rc );
629
+ if (rc != - EAGAIN )
630
+ dev_err (hdev -> dev ,
631
+ "Failed to submit CS %d.%llu to H/W queues, error %d\n" ,
632
+ cs -> ctx -> asid , cs -> sequence , rc );
586
633
goto free_cs_object ;
587
634
}
588
635
0 commit comments