2013-03-22 18:34:01 +04:00
/*
* Tegra host1x Syncpoints
*
2016-11-08 20:51:33 +03:00
* Copyright ( c ) 2010 - 2015 , NVIDIA Corporation .
2013-03-22 18:34:01 +04:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <linux/module.h>
# include <linux/device.h>
# include <linux/slab.h>
# include <trace/events/host1x.h>
# include "syncpt.h"
# include "dev.h"
2013-03-22 18:34:02 +04:00
# include "intr.h"
2013-03-22 18:34:04 +04:00
# include "debug.h"
2013-03-22 18:34:02 +04:00
# define SYNCPT_CHECK_PERIOD (2 * HZ)
# define MAX_STUCK_CHECK_COUNT 15
2013-03-22 18:34:01 +04:00
2013-10-14 16:21:53 +04:00
static struct host1x_syncpt_base *
host1x_syncpt_base_request ( struct host1x * host )
{
struct host1x_syncpt_base * bases = host - > bases ;
unsigned int i ;
for ( i = 0 ; i < host - > info - > nb_bases ; i + + )
if ( ! bases [ i ] . requested )
break ;
if ( i > = host - > info - > nb_bases )
return NULL ;
bases [ i ] . requested = true ;
return & bases [ i ] ;
}
static void host1x_syncpt_base_free ( struct host1x_syncpt_base * base )
{
if ( base )
base - > requested = false ;
}
2013-10-14 16:21:52 +04:00
static struct host1x_syncpt * host1x_syncpt_alloc ( struct host1x * host ,
2017-08-30 13:48:31 +03:00
struct host1x_client * client ,
2013-10-14 16:21:52 +04:00
unsigned long flags )
2013-03-22 18:34:01 +04:00
{
struct host1x_syncpt * sp = host - > syncpt ;
2018-03-23 15:31:24 +03:00
unsigned int i ;
2013-03-22 18:34:01 +04:00
char * name ;
2016-11-08 20:51:33 +03:00
mutex_lock ( & host - > syncpt_mutex ) ;
2013-03-22 18:34:01 +04:00
for ( i = 0 ; i < host - > info - > nb_pts & & sp - > name ; i + + , sp + + )
;
2013-05-29 14:26:06 +04:00
if ( i > = host - > info - > nb_pts )
2016-11-08 20:51:33 +03:00
goto unlock ;
2013-03-22 18:34:01 +04:00
2013-10-14 16:21:53 +04:00
if ( flags & HOST1X_SYNCPT_HAS_BASE ) {
sp - > base = host1x_syncpt_base_request ( host ) ;
if ( ! sp - > base )
2016-11-08 20:51:33 +03:00
goto unlock ;
2013-10-14 16:21:53 +04:00
}
2016-06-23 12:19:00 +03:00
name = kasprintf ( GFP_KERNEL , " %02u-%s " , sp - > id ,
2017-08-30 13:48:31 +03:00
client ? dev_name ( client - > dev ) : NULL ) ;
2013-03-22 18:34:01 +04:00
if ( ! name )
2016-11-08 20:51:33 +03:00
goto free_base ;
2013-03-22 18:34:01 +04:00
2017-08-30 13:48:31 +03:00
sp - > client = client ;
2013-03-22 18:34:01 +04:00
sp - > name = name ;
2013-10-14 16:21:52 +04:00
if ( flags & HOST1X_SYNCPT_CLIENT_MANAGED )
sp - > client_managed = true ;
else
sp - > client_managed = false ;
2013-03-22 18:34:01 +04:00
2016-11-08 20:51:33 +03:00
mutex_unlock ( & host - > syncpt_mutex ) ;
2013-03-22 18:34:01 +04:00
return sp ;
2016-11-08 20:51:33 +03:00
free_base :
host1x_syncpt_base_free ( sp - > base ) ;
sp - > base = NULL ;
unlock :
mutex_unlock ( & host - > syncpt_mutex ) ;
return NULL ;
2013-03-22 18:34:01 +04:00
}
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_id ( ) - retrieve syncpoint ID
* @ sp : host1x syncpoint
*
* Given a pointer to a struct host1x_syncpt , retrieves its ID . This ID is
* often used as a value to program into registers that control how hardware
* blocks interact with syncpoints .
*/
2013-03-22 18:34:01 +04:00
u32 host1x_syncpt_id ( struct host1x_syncpt * sp )
{
return sp - > id ;
}
2013-11-08 14:41:42 +04:00
EXPORT_SYMBOL ( host1x_syncpt_id ) ;
2013-03-22 18:34:01 +04:00
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_incr_max ( ) - update the value sent to hardware
* @ sp : host1x syncpoint
* @ incrs : number of increments
2013-03-22 18:34:01 +04:00
*/
u32 host1x_syncpt_incr_max ( struct host1x_syncpt * sp , u32 incrs )
{
return ( u32 ) atomic_add_return ( incrs , & sp - > max_val ) ;
}
2014-02-20 02:48:36 +04:00
EXPORT_SYMBOL ( host1x_syncpt_incr_max ) ;
2013-03-22 18:34:01 +04:00
/*
* Write cached syncpoint and waitbase values to hardware .
*/
void host1x_syncpt_restore ( struct host1x * host )
{
struct host1x_syncpt * sp_base = host - > syncpt ;
2016-06-22 17:44:07 +03:00
unsigned int i ;
2013-03-22 18:34:01 +04:00
for ( i = 0 ; i < host1x_syncpt_nb_pts ( host ) ; i + + )
host1x_hw_syncpt_restore ( host , sp_base + i ) ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:01 +04:00
for ( i = 0 ; i < host1x_syncpt_nb_bases ( host ) ; i + + )
host1x_hw_syncpt_restore_wait_base ( host , sp_base + i ) ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:01 +04:00
wmb ( ) ;
}
/*
* Update the cached syncpoint and waitbase values by reading them
* from the registers .
*/
void host1x_syncpt_save ( struct host1x * host )
{
struct host1x_syncpt * sp_base = host - > syncpt ;
2016-06-22 17:44:07 +03:00
unsigned int i ;
2013-03-22 18:34:01 +04:00
for ( i = 0 ; i < host1x_syncpt_nb_pts ( host ) ; i + + ) {
if ( host1x_syncpt_client_managed ( sp_base + i ) )
host1x_hw_syncpt_load ( host , sp_base + i ) ;
else
WARN_ON ( ! host1x_syncpt_idle ( sp_base + i ) ) ;
}
for ( i = 0 ; i < host1x_syncpt_nb_bases ( host ) ; i + + )
host1x_hw_syncpt_load_wait_base ( host , sp_base + i ) ;
}
/*
* Updates the cached syncpoint value by reading a new value from the hardware
* register
*/
u32 host1x_syncpt_load ( struct host1x_syncpt * sp )
{
u32 val ;
2016-06-23 12:33:31 +03:00
2013-03-22 18:34:01 +04:00
val = host1x_hw_syncpt_load ( sp - > host , sp ) ;
trace_host1x_syncpt_load_min ( sp - > id , val ) ;
return val ;
}
/*
* Get the current syncpoint base
*/
u32 host1x_syncpt_load_wait_base ( struct host1x_syncpt * sp )
{
host1x_hw_syncpt_load_wait_base ( sp - > host , sp ) ;
2016-06-23 12:39:11 +03:00
return sp - > base_val ;
2013-03-22 18:34:01 +04:00
}
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_incr ( ) - increment syncpoint value from CPU , updating cache
* @ sp : host1x syncpoint
2013-03-22 18:34:01 +04:00
*/
2013-05-29 14:26:08 +04:00
int host1x_syncpt_incr ( struct host1x_syncpt * sp )
2013-03-22 18:34:01 +04:00
{
2013-05-29 14:26:08 +04:00
return host1x_hw_syncpt_cpu_incr ( sp - > host , sp ) ;
2013-03-22 18:34:01 +04:00
}
2013-11-08 14:41:42 +04:00
EXPORT_SYMBOL ( host1x_syncpt_incr ) ;
2013-03-22 18:34:01 +04:00
2013-03-22 18:34:02 +04:00
/*
* Updated sync point form hardware , and returns true if syncpoint is expired ,
* false if we may need to wait
*/
static bool syncpt_load_min_is_expired ( struct host1x_syncpt * sp , u32 thresh )
{
host1x_hw_syncpt_load ( sp - > host , sp ) ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
return host1x_syncpt_is_expired ( sp , thresh ) ;
}
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_wait ( ) - wait for a syncpoint to reach a given value
* @ sp : host1x syncpoint
* @ thresh : threshold
* @ timeout : maximum time to wait for the syncpoint to reach the given value
* @ value : return location for the syncpoint value
2013-03-22 18:34:02 +04:00
*/
int host1x_syncpt_wait ( struct host1x_syncpt * sp , u32 thresh , long timeout ,
2016-06-23 12:35:50 +03:00
u32 * value )
2013-03-22 18:34:02 +04:00
{
DECLARE_WAIT_QUEUE_HEAD_ONSTACK ( wq ) ;
void * ref ;
struct host1x_waitlist * waiter ;
int err = 0 , check_count = 0 ;
u32 val ;
if ( value )
* value = 0 ;
/* first check cache */
if ( host1x_syncpt_is_expired ( sp , thresh ) ) {
if ( value )
* value = host1x_syncpt_load ( sp ) ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
return 0 ;
}
/* try to read from register */
val = host1x_hw_syncpt_load ( sp - > host , sp ) ;
if ( host1x_syncpt_is_expired ( sp , thresh ) ) {
if ( value )
* value = val ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
goto done ;
}
if ( ! timeout ) {
err = - EAGAIN ;
goto done ;
}
/* allocate a waiter */
waiter = kzalloc ( sizeof ( * waiter ) , GFP_KERNEL ) ;
if ( ! waiter ) {
err = - ENOMEM ;
goto done ;
}
/* schedule a wakeup when the syncpoint value is reached */
2018-05-16 15:29:33 +03:00
err = host1x_intr_add_action ( sp - > host , sp , thresh ,
2013-03-22 18:34:02 +04:00
HOST1X_INTR_ACTION_WAKEUP_INTERRUPTIBLE ,
& wq , waiter , & ref ) ;
if ( err )
goto done ;
err = - EAGAIN ;
/* Caller-specified timeout may be impractically low */
if ( timeout < 0 )
timeout = LONG_MAX ;
/* wait for the syncpoint, or timeout, or signal */
while ( timeout ) {
long check = min_t ( long , SYNCPT_CHECK_PERIOD , timeout ) ;
2016-06-23 12:35:50 +03:00
int remain ;
remain = wait_event_interruptible_timeout ( wq ,
2013-03-22 18:34:02 +04:00
syncpt_load_min_is_expired ( sp , thresh ) ,
check ) ;
if ( remain > 0 | | host1x_syncpt_is_expired ( sp , thresh ) ) {
if ( value )
* value = host1x_syncpt_load ( sp ) ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
err = 0 ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
break ;
}
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
if ( remain < 0 ) {
err = remain ;
break ;
}
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
timeout - = check ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
if ( timeout & & check_count < = MAX_STUCK_CHECK_COUNT ) {
dev_warn ( sp - > host - > dev ,
2016-06-23 12:19:00 +03:00
" %s: syncpoint id %u (%s) stuck waiting %d, timeout=%ld \n " ,
2013-03-22 18:34:02 +04:00
current - > comm , sp - > id , sp - > name ,
thresh , timeout ) ;
2013-03-22 18:34:04 +04:00
host1x_debug_dump_syncpts ( sp - > host ) ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:04 +04:00
if ( check_count = = MAX_STUCK_CHECK_COUNT )
host1x_debug_dump ( sp - > host ) ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
check_count + + ;
}
}
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
host1x_intr_put_ref ( sp - > host , sp - > id , ref ) ;
done :
return err ;
}
EXPORT_SYMBOL ( host1x_syncpt_wait ) ;
/*
* Returns true if syncpoint is expired , false if we may need to wait
*/
bool host1x_syncpt_is_expired ( struct host1x_syncpt * sp , u32 thresh )
{
u32 current_val ;
u32 future_val ;
2016-06-23 12:33:31 +03:00
2013-03-22 18:34:02 +04:00
smp_rmb ( ) ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:02 +04:00
current_val = ( u32 ) atomic_read ( & sp - > min_val ) ;
future_val = ( u32 ) atomic_read ( & sp - > max_val ) ;
/* Note the use of unsigned arithmetic here (mod 1<<32).
*
* c = current_val = min_val = the current value of the syncpoint .
* t = thresh = the value we are checking
* f = future_val = max_val = the value c will reach when all
* outstanding increments have completed .
*
* Note that c always chases f until it reaches f .
*
* Dtf = ( f - t )
* Dtc = ( c - t )
*
* Consider all cases :
*
* A ) . . . . . c . . t . . f . . . . . Dtf < Dtc need to wait
* B ) . . . . . c . . . . . f . . t . . Dtf > Dtc expired
* C ) . . t . . c . . . . . f . . . . . Dtf > Dtc expired ( Dct very large )
*
* Any case where f = = c : always expired ( for any t ) . Dtf = = Dcf
* Any case where t = = c : always expired ( for any f ) . Dtf > = Dtc ( because Dtc = = 0 )
* Any case where t = = f ! = c : always wait . Dtf < Dtc ( because Dtf = = 0 ,
* Dtc ! = 0 )
*
* Other cases :
*
* A ) . . . . . t . . f . . c . . . . . Dtf < Dtc need to wait
* A ) . . . . . f . . c . . t . . . . . Dtf < Dtc need to wait
* A ) . . . . . f . . t . . c . . . . . Dtf > Dtc expired
*
* So :
* Dtf > = Dtc implies EXPIRED ( return true )
* Dtf < Dtc implies WAIT ( return false )
*
* Note : If t is expired then we * cannot * wait on it . We would wait
* forever ( hang the system ) .
*
* Note : do NOT get clever and remove the - thresh from both sides . It
* is NOT the same .
*
* If future valueis zero , we have a client managed sync point . In that
* case we do a direct comparison .
*/
if ( ! host1x_syncpt_client_managed ( sp ) )
return future_val - thresh > = current_val - thresh ;
else
return ( s32 ) ( current_val - thresh ) > = 0 ;
}
2013-03-22 18:34:01 +04:00
int host1x_syncpt_init ( struct host1x * host )
{
2013-10-14 16:21:53 +04:00
struct host1x_syncpt_base * bases ;
2013-03-22 18:34:01 +04:00
struct host1x_syncpt * syncpt ;
2016-06-22 17:44:07 +03:00
unsigned int i ;
2013-03-22 18:34:01 +04:00
2016-06-23 12:24:59 +03:00
syncpt = devm_kcalloc ( host - > dev , host - > info - > nb_pts , sizeof ( * syncpt ) ,
2013-10-14 16:21:53 +04:00
GFP_KERNEL ) ;
2013-03-22 18:34:01 +04:00
if ( ! syncpt )
return - ENOMEM ;
2016-06-23 12:24:59 +03:00
bases = devm_kcalloc ( host - > dev , host - > info - > nb_bases , sizeof ( * bases ) ,
2013-10-14 16:21:53 +04:00
GFP_KERNEL ) ;
if ( ! bases )
return - ENOMEM ;
for ( i = 0 ; i < host - > info - > nb_pts ; i + + ) {
2013-03-22 18:34:01 +04:00
syncpt [ i ] . id = i ;
syncpt [ i ] . host = host ;
2017-09-28 15:50:39 +03:00
/*
* Unassign syncpt from channels for purposes of Tegra186
* syncpoint protection . This prevents any channel from
* accessing it until it is reassigned .
*/
host1x_hw_syncpt_assign_to_channel ( host , & syncpt [ i ] , NULL ) ;
2013-03-22 18:34:01 +04:00
}
2013-10-14 16:21:53 +04:00
for ( i = 0 ; i < host - > info - > nb_bases ; i + + )
bases [ i ] . id = i ;
2016-11-08 20:51:33 +03:00
mutex_init ( & host - > syncpt_mutex ) ;
2013-03-22 18:34:01 +04:00
host - > syncpt = syncpt ;
2013-10-14 16:21:53 +04:00
host - > bases = bases ;
2013-03-22 18:34:01 +04:00
host1x_syncpt_restore ( host ) ;
2017-09-28 15:50:39 +03:00
host1x_hw_syncpt_enable_protection ( host ) ;
2013-03-22 18:34:01 +04:00
2013-03-22 18:34:03 +04:00
/* Allocate sync point to use for clearing waits for expired fences */
2013-10-14 16:21:52 +04:00
host - > nop_sp = host1x_syncpt_alloc ( host , NULL , 0 ) ;
2013-03-22 18:34:03 +04:00
if ( ! host - > nop_sp )
return - ENOMEM ;
2013-03-22 18:34:01 +04:00
return 0 ;
}
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_request ( ) - request a syncpoint
2017-08-30 13:48:31 +03:00
* @ client : client requesting the syncpoint
2017-04-10 13:27:01 +03:00
* @ flags : flags
*
* host1x client drivers can use this function to allocate a syncpoint for
* subsequent use . A syncpoint returned by this function will be reserved for
* use by the client exclusively . When no longer using a syncpoint , a host1x
* client driver needs to release it using host1x_syncpt_free ( ) .
*/
2017-08-30 13:48:31 +03:00
struct host1x_syncpt * host1x_syncpt_request ( struct host1x_client * client ,
2013-10-14 16:21:52 +04:00
unsigned long flags )
2013-03-22 18:34:01 +04:00
{
2017-08-30 13:48:31 +03:00
struct host1x * host = dev_get_drvdata ( client - > parent - > parent ) ;
2016-06-23 12:35:50 +03:00
2017-08-30 13:48:31 +03:00
return host1x_syncpt_alloc ( host , client , flags ) ;
2013-03-22 18:34:01 +04:00
}
2013-11-08 14:41:42 +04:00
EXPORT_SYMBOL ( host1x_syncpt_request ) ;
2013-03-22 18:34:01 +04:00
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_free ( ) - free a requested syncpoint
* @ sp : host1x syncpoint
*
* Release a syncpoint previously allocated using host1x_syncpt_request ( ) . A
* host1x client driver should call this when the syncpoint is no longer in
* use . Note that client drivers must ensure that the syncpoint doesn ' t remain
* under the control of hardware after calling this function , otherwise two
* clients may end up trying to access the same syncpoint concurrently .
*/
2013-03-22 18:34:01 +04:00
void host1x_syncpt_free ( struct host1x_syncpt * sp )
{
if ( ! sp )
return ;
2016-11-08 20:51:33 +03:00
mutex_lock ( & sp - > host - > syncpt_mutex ) ;
2013-10-14 16:21:53 +04:00
host1x_syncpt_base_free ( sp - > base ) ;
2013-03-22 18:34:01 +04:00
kfree ( sp - > name ) ;
2013-10-14 16:21:53 +04:00
sp - > base = NULL ;
2017-08-30 13:48:31 +03:00
sp - > client = NULL ;
2013-03-22 18:34:01 +04:00
sp - > name = NULL ;
2013-05-29 14:26:07 +04:00
sp - > client_managed = false ;
2016-11-08 20:51:33 +03:00
mutex_unlock ( & sp - > host - > syncpt_mutex ) ;
2013-03-22 18:34:01 +04:00
}
2013-11-08 14:41:42 +04:00
EXPORT_SYMBOL ( host1x_syncpt_free ) ;
2013-03-22 18:34:01 +04:00
void host1x_syncpt_deinit ( struct host1x * host )
{
struct host1x_syncpt * sp = host - > syncpt ;
2016-06-22 17:44:07 +03:00
unsigned int i ;
2013-03-22 18:34:01 +04:00
for ( i = 0 ; i < host - > info - > nb_pts ; i + + , sp + + )
kfree ( sp - > name ) ;
}
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_read_max ( ) - read maximum syncpoint value
* @ sp : host1x syncpoint
*
* The maximum syncpoint value indicates how many operations there are in
* queue , either in channel or in a software thread .
2016-06-23 12:33:31 +03:00
*/
2013-09-24 18:30:32 +04:00
u32 host1x_syncpt_read_max ( struct host1x_syncpt * sp )
{
smp_rmb ( ) ;
2016-06-23 12:35:50 +03:00
2013-09-24 18:30:32 +04:00
return ( u32 ) atomic_read ( & sp - > max_val ) ;
}
2013-11-08 14:41:42 +04:00
EXPORT_SYMBOL ( host1x_syncpt_read_max ) ;
2013-09-24 18:30:32 +04:00
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_read_min ( ) - read minimum syncpoint value
* @ sp : host1x syncpoint
*
* The minimum syncpoint value is a shadow of the current sync point value in
* hardware .
2013-09-24 18:30:32 +04:00
*/
u32 host1x_syncpt_read_min ( struct host1x_syncpt * sp )
{
smp_rmb ( ) ;
2016-06-23 12:35:50 +03:00
2013-09-24 18:30:32 +04:00
return ( u32 ) atomic_read ( & sp - > min_val ) ;
}
2013-11-08 14:41:42 +04:00
EXPORT_SYMBOL ( host1x_syncpt_read_min ) ;
2013-09-24 18:30:32 +04:00
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_read ( ) - read the current syncpoint value
* @ sp : host1x syncpoint
*/
2015-01-28 16:29:02 +03:00
u32 host1x_syncpt_read ( struct host1x_syncpt * sp )
{
return host1x_syncpt_load ( sp ) ;
}
EXPORT_SYMBOL ( host1x_syncpt_read ) ;
2016-06-22 17:44:07 +03:00
unsigned int host1x_syncpt_nb_pts ( struct host1x * host )
2013-03-22 18:34:01 +04:00
{
return host - > info - > nb_pts ;
}
2016-06-22 17:44:07 +03:00
unsigned int host1x_syncpt_nb_bases ( struct host1x * host )
2013-03-22 18:34:01 +04:00
{
return host - > info - > nb_bases ;
}
2016-06-22 17:44:07 +03:00
unsigned int host1x_syncpt_nb_mlocks ( struct host1x * host )
2013-03-22 18:34:01 +04:00
{
return host - > info - > nb_mlocks ;
}
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_get ( ) - obtain a syncpoint by ID
* @ host : host1x controller
* @ id : syncpoint ID
*/
2016-06-23 12:19:00 +03:00
struct host1x_syncpt * host1x_syncpt_get ( struct host1x * host , unsigned int id )
2013-03-22 18:34:01 +04:00
{
2017-03-09 22:04:57 +03:00
if ( id > = host - > info - > nb_pts )
2013-03-22 18:34:01 +04:00
return NULL ;
2016-06-23 12:35:50 +03:00
2013-03-22 18:34:01 +04:00
return host - > syncpt + id ;
}
2013-11-08 14:41:42 +04:00
EXPORT_SYMBOL ( host1x_syncpt_get ) ;
2013-10-14 16:21:53 +04:00
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_get_base ( ) - obtain the wait base associated with a syncpoint
* @ sp : host1x syncpoint
*/
2013-10-14 16:21:53 +04:00
struct host1x_syncpt_base * host1x_syncpt_get_base ( struct host1x_syncpt * sp )
{
return sp ? sp - > base : NULL ;
}
2013-11-08 14:41:42 +04:00
EXPORT_SYMBOL ( host1x_syncpt_get_base ) ;
2013-10-14 16:21:53 +04:00
2017-04-10 13:27:01 +03:00
/**
* host1x_syncpt_base_id ( ) - retrieve the ID of a syncpoint wait base
* @ base : host1x syncpoint wait base
*/
2013-10-14 16:21:53 +04:00
u32 host1x_syncpt_base_id ( struct host1x_syncpt_base * base )
{
return base - > id ;
}
2013-11-08 14:41:42 +04:00
EXPORT_SYMBOL ( host1x_syncpt_base_id ) ;