2019-08-21 20:16:06 +01:00
// SPDX-License-Identifier: MIT
/*
* Copyright © 2019 Intel Corporation
*/
# include "i915_sw_fence_work.h"
2019-12-16 16:17:16 +00:00
static void fence_complete ( struct dma_fence_work * f )
{
if ( f - > ops - > release )
f - > ops - > release ( f ) ;
dma_fence_signal ( & f - > dma ) ;
}
2019-08-21 20:16:06 +01:00
static void fence_work ( struct work_struct * work )
{
struct dma_fence_work * f = container_of ( work , typeof ( * f ) , work ) ;
2021-07-14 14:34:18 -05:00
f - > ops - > work ( f ) ;
2019-12-16 16:17:16 +00:00
fence_complete ( f ) ;
2019-08-21 20:16:06 +01:00
dma_fence_put ( & f - > dma ) ;
}
2021-11-16 11:49:29 -08:00
static int
2019-08-21 20:16:06 +01:00
fence_notify ( struct i915_sw_fence * fence , enum i915_sw_fence_notify state )
{
struct dma_fence_work * f = container_of ( fence , typeof ( * f ) , chain ) ;
switch ( state ) {
case FENCE_COMPLETE :
if ( fence - > error )
dma_fence_set_error ( & f - > dma , fence - > error ) ;
if ( ! f - > dma . error ) {
dma_fence_get ( & f - > dma ) ;
2020-03-25 12:02:27 +00:00
if ( test_bit ( DMA_FENCE_WORK_IMM , & f - > dma . flags ) )
fence_work ( & f - > work ) ;
else
queue_work ( system_unbound_wq , & f - > work ) ;
2019-08-21 20:16:06 +01:00
} else {
2019-12-16 16:17:16 +00:00
fence_complete ( f ) ;
2019-08-21 20:16:06 +01:00
}
break ;
case FENCE_FREE :
dma_fence_put ( & f - > dma ) ;
break ;
}
return NOTIFY_DONE ;
}
static const char * get_driver_name ( struct dma_fence * fence )
{
return " dma-fence " ;
}
static const char * get_timeline_name ( struct dma_fence * fence )
{
struct dma_fence_work * f = container_of ( fence , typeof ( * f ) , dma ) ;
return f - > ops - > name ? : " work " ;
}
static void fence_release ( struct dma_fence * fence )
{
struct dma_fence_work * f = container_of ( fence , typeof ( * f ) , dma ) ;
i915_sw_fence_fini ( & f - > chain ) ;
BUILD_BUG_ON ( offsetof ( typeof ( * f ) , dma ) ) ;
dma_fence_free ( & f - > dma ) ;
}
static const struct dma_fence_ops fence_ops = {
. get_driver_name = get_driver_name ,
. get_timeline_name = get_timeline_name ,
. release = fence_release ,
} ;
void dma_fence_work_init ( struct dma_fence_work * f ,
const struct dma_fence_work_ops * ops )
{
2019-12-12 15:42:24 +00:00
f - > ops = ops ;
2019-08-21 20:16:06 +01:00
spin_lock_init ( & f - > lock ) ;
dma_fence_init ( & f - > dma , & fence_ops , & f - > lock , 0 , 0 ) ;
i915_sw_fence_init ( & f - > chain , fence_notify ) ;
INIT_WORK ( & f - > work , fence_work ) ;
}
int dma_fence_work_chain ( struct dma_fence_work * f , struct dma_fence * signal )
{
if ( ! signal )
return 0 ;
return __i915_sw_fence_await_dma_fence ( & f - > chain , signal , & f - > cb ) ;
}