@@ -386,58 +386,69 @@ void panfrost_mmu_pgtable_free(struct panfrost_file_priv *priv)
386
386
free_io_pgtable_ops (mmu -> pgtbl_ops );
387
387
}
388
388
389
- static struct drm_mm_node * addr_to_drm_mm_node (struct panfrost_device * pfdev , int as , u64 addr )
389
+ static struct panfrost_gem_object *
390
+ addr_to_drm_mm_node (struct panfrost_device * pfdev , int as , u64 addr )
390
391
{
391
- struct drm_mm_node * node = NULL ;
392
+ struct panfrost_gem_object * bo = NULL ;
393
+ struct panfrost_file_priv * priv ;
394
+ struct drm_mm_node * node ;
392
395
u64 offset = addr >> PAGE_SHIFT ;
393
396
struct panfrost_mmu * mmu ;
394
397
395
398
spin_lock (& pfdev -> as_lock );
396
399
list_for_each_entry (mmu , & pfdev -> as_lru_list , list ) {
397
- struct panfrost_file_priv * priv ;
398
- if (as != mmu -> as )
399
- continue ;
400
+ if (as == mmu -> as )
401
+ break ;
402
+ }
403
+ if (as != mmu -> as )
404
+ goto out ;
405
+
406
+ priv = container_of (mmu , struct panfrost_file_priv , mmu );
400
407
401
- priv = container_of (mmu , struct panfrost_file_priv , mmu );
402
- drm_mm_for_each_node (node , & priv -> mm ) {
403
- if (offset >= node -> start && offset < (node -> start + node -> size ))
404
- goto out ;
408
+ spin_lock (& priv -> mm_lock );
409
+
410
+ drm_mm_for_each_node (node , & priv -> mm ) {
411
+ if (offset >= node -> start &&
412
+ offset < (node -> start + node -> size )) {
413
+ bo = drm_mm_node_to_panfrost_bo (node );
414
+ drm_gem_object_get (& bo -> base .base );
415
+ break ;
405
416
}
406
417
}
407
418
419
+ spin_unlock (& priv -> mm_lock );
408
420
out :
409
421
spin_unlock (& pfdev -> as_lock );
410
- return node ;
422
+ return bo ;
411
423
}
412
424
413
425
#define NUM_FAULT_PAGES (SZ_2M / PAGE_SIZE)
414
426
415
427
int panfrost_mmu_map_fault_addr (struct panfrost_device * pfdev , int as , u64 addr )
416
428
{
417
429
int ret , i ;
418
- struct drm_mm_node * node ;
419
430
struct panfrost_gem_object * bo ;
420
431
struct address_space * mapping ;
421
432
pgoff_t page_offset ;
422
433
struct sg_table * sgt ;
423
434
struct page * * pages ;
424
435
425
- node = addr_to_drm_mm_node (pfdev , as , addr );
426
- if (!node )
436
+ bo = addr_to_drm_mm_node (pfdev , as , addr );
437
+ if (!bo )
427
438
return - ENOENT ;
428
439
429
- bo = drm_mm_node_to_panfrost_bo (node );
430
440
if (!bo -> is_heap ) {
431
441
dev_WARN (pfdev -> dev , "matching BO is not heap type (GPU VA = %llx)" ,
432
- node -> start << PAGE_SHIFT );
433
- return - EINVAL ;
442
+ bo -> node .start << PAGE_SHIFT );
443
+ ret = - EINVAL ;
444
+ goto err_bo ;
434
445
}
435
446
WARN_ON (bo -> mmu -> as != as );
436
447
437
448
/* Assume 2MB alignment and size multiple */
438
449
addr &= ~((u64 )SZ_2M - 1 );
439
450
page_offset = addr >> PAGE_SHIFT ;
440
- page_offset -= node -> start ;
451
+ page_offset -= bo -> node . start ;
441
452
442
453
mutex_lock (& bo -> base .pages_lock );
443
454
@@ -446,7 +457,8 @@ int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, u64 addr)
446
457
sizeof (struct sg_table ), GFP_KERNEL | __GFP_ZERO );
447
458
if (!bo -> sgts ) {
448
459
mutex_unlock (& bo -> base .pages_lock );
449
- return - ENOMEM ;
460
+ ret = - ENOMEM ;
461
+ goto err_bo ;
450
462
}
451
463
452
464
pages = kvmalloc_array (bo -> base .base .size >> PAGE_SHIFT ,
@@ -455,7 +467,8 @@ int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, u64 addr)
455
467
kfree (bo -> sgts );
456
468
bo -> sgts = NULL ;
457
469
mutex_unlock (& bo -> base .pages_lock );
458
- return - ENOMEM ;
470
+ ret = - ENOMEM ;
471
+ goto err_bo ;
459
472
}
460
473
bo -> base .pages = pages ;
461
474
bo -> base .pages_use_count = 1 ;
@@ -493,12 +506,16 @@ int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, u64 addr)
493
506
494
507
dev_dbg (pfdev -> dev , "mapped page fault @ AS%d %llx" , as , addr );
495
508
509
+ drm_gem_object_put_unlocked (& bo -> base .base );
510
+
496
511
return 0 ;
497
512
498
513
err_map :
499
514
sg_free_table (sgt );
500
515
err_pages :
501
516
drm_gem_shmem_put_pages (& bo -> base );
517
+ err_bo :
518
+ drm_gem_object_put_unlocked (& bo -> base .base );
502
519
return ret ;
503
520
}
504
521
0 commit comments