LCOV - code coverage report
Current view: top level - drivers/gpu/drm/scheduler - sched_fence.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4 56 7.1 %
Date: 2022-12-09 01:23:36 Functions: 1 13 7.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 Advanced Micro Devices, Inc.
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      19             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  */
      23             : 
      24             : #include <linux/kthread.h>
      25             : #include <linux/module.h>
      26             : #include <linux/sched.h>
      27             : #include <linux/slab.h>
      28             : #include <linux/wait.h>
      29             : 
      30             : #include <drm/gpu_scheduler.h>
      31             : 
      32             : static struct kmem_cache *sched_fence_slab;
      33             : 
      34           1 : static int __init drm_sched_fence_slab_init(void)
      35             : {
      36           1 :         sched_fence_slab = kmem_cache_create(
      37             :                 "drm_sched_fence", sizeof(struct drm_sched_fence), 0,
      38             :                 SLAB_HWCACHE_ALIGN, NULL);
      39           1 :         if (!sched_fence_slab)
      40             :                 return -ENOMEM;
      41             : 
      42           1 :         return 0;
      43             : }
      44             : 
      45           0 : static void __exit drm_sched_fence_slab_fini(void)
      46             : {
      47           0 :         rcu_barrier();
      48           0 :         kmem_cache_destroy(sched_fence_slab);
      49           0 : }
      50             : 
      51           0 : void drm_sched_fence_scheduled(struct drm_sched_fence *fence)
      52             : {
      53           0 :         dma_fence_signal(&fence->scheduled);
      54           0 : }
      55             : 
      56           0 : void drm_sched_fence_finished(struct drm_sched_fence *fence)
      57             : {
      58           0 :         dma_fence_signal(&fence->finished);
      59           0 : }
      60             : 
      61           0 : static const char *drm_sched_fence_get_driver_name(struct dma_fence *fence)
      62             : {
      63           0 :         return "drm_sched";
      64             : }
      65             : 
      66           0 : static const char *drm_sched_fence_get_timeline_name(struct dma_fence *f)
      67             : {
      68           0 :         struct drm_sched_fence *fence = to_drm_sched_fence(f);
      69           0 :         return (const char *)fence->sched->name;
      70             : }
      71             : 
      72           0 : static void drm_sched_fence_free_rcu(struct rcu_head *rcu)
      73             : {
      74           0 :         struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);
      75           0 :         struct drm_sched_fence *fence = to_drm_sched_fence(f);
      76             : 
      77           0 :         if (!WARN_ON_ONCE(!fence))
      78           0 :                 kmem_cache_free(sched_fence_slab, fence);
      79           0 : }
      80             : 
      81             : /**
      82             :  * drm_sched_fence_free - free up an uninitialized fence
      83             :  *
      84             :  * @fence: fence to free
      85             :  *
      86             :  * Free up the fence memory. Should only be used if drm_sched_fence_init()
      87             :  * has not been called yet.
      88             :  */
      89           0 : void drm_sched_fence_free(struct drm_sched_fence *fence)
      90             : {
      91             :         /* This function should not be called if the fence has been initialized. */
      92           0 :         if (!WARN_ON_ONCE(fence->sched))
      93           0 :                 kmem_cache_free(sched_fence_slab, fence);
      94           0 : }
      95             : 
      96             : /**
      97             :  * drm_sched_fence_release_scheduled - callback that fence can be freed
      98             :  *
      99             :  * @f: fence
     100             :  *
     101             :  * This function is called when the reference count becomes zero.
     102             :  * It just RCU schedules freeing up the fence.
     103             :  */
     104           0 : static void drm_sched_fence_release_scheduled(struct dma_fence *f)
     105             : {
     106           0 :         struct drm_sched_fence *fence = to_drm_sched_fence(f);
     107             : 
     108           0 :         dma_fence_put(fence->parent);
     109           0 :         call_rcu(&fence->finished.rcu, drm_sched_fence_free_rcu);
     110           0 : }
     111             : 
     112             : /**
     113             :  * drm_sched_fence_release_finished - drop extra reference
     114             :  *
     115             :  * @f: fence
     116             :  *
     117             :  * Drop the extra reference from the scheduled fence to the base fence.
     118             :  */
     119           0 : static void drm_sched_fence_release_finished(struct dma_fence *f)
     120             : {
     121           0 :         struct drm_sched_fence *fence = to_drm_sched_fence(f);
     122             : 
     123           0 :         dma_fence_put(&fence->scheduled);
     124           0 : }
     125             : 
     126             : static const struct dma_fence_ops drm_sched_fence_ops_scheduled = {
     127             :         .get_driver_name = drm_sched_fence_get_driver_name,
     128             :         .get_timeline_name = drm_sched_fence_get_timeline_name,
     129             :         .release = drm_sched_fence_release_scheduled,
     130             : };
     131             : 
     132             : static const struct dma_fence_ops drm_sched_fence_ops_finished = {
     133             :         .get_driver_name = drm_sched_fence_get_driver_name,
     134             :         .get_timeline_name = drm_sched_fence_get_timeline_name,
     135             :         .release = drm_sched_fence_release_finished,
     136             : };
     137             : 
     138           0 : struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f)
     139             : {
     140           0 :         if (f->ops == &drm_sched_fence_ops_scheduled)
     141             :                 return container_of(f, struct drm_sched_fence, scheduled);
     142             : 
     143           0 :         if (f->ops == &drm_sched_fence_ops_finished)
     144           0 :                 return container_of(f, struct drm_sched_fence, finished);
     145             : 
     146             :         return NULL;
     147             : }
     148             : EXPORT_SYMBOL(to_drm_sched_fence);
     149             : 
     150           0 : struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *entity,
     151             :                                               void *owner)
     152             : {
     153           0 :         struct drm_sched_fence *fence = NULL;
     154             : 
     155           0 :         fence = kmem_cache_zalloc(sched_fence_slab, GFP_KERNEL);
     156           0 :         if (fence == NULL)
     157             :                 return NULL;
     158             : 
     159           0 :         fence->owner = owner;
     160           0 :         spin_lock_init(&fence->lock);
     161             : 
     162           0 :         return fence;
     163             : }
     164             : 
     165           0 : void drm_sched_fence_init(struct drm_sched_fence *fence,
     166             :                           struct drm_sched_entity *entity)
     167             : {
     168             :         unsigned seq;
     169             : 
     170           0 :         fence->sched = entity->rq->sched;
     171           0 :         seq = atomic_inc_return(&entity->fence_seq);
     172           0 :         dma_fence_init(&fence->scheduled, &drm_sched_fence_ops_scheduled,
     173             :                        &fence->lock, entity->fence_context, seq);
     174           0 :         dma_fence_init(&fence->finished, &drm_sched_fence_ops_finished,
     175           0 :                        &fence->lock, entity->fence_context + 1, seq);
     176           0 : }
     177             : 
     178             : module_init(drm_sched_fence_slab_init);
     179             : module_exit(drm_sched_fence_slab_fini);
     180             : 
     181             : MODULE_DESCRIPTION("DRM GPU scheduler");
     182             : MODULE_LICENSE("GPL and additional rights");

Generated by: LCOV version 1.14