3636#include "xe_pm.h"
3737#include "xe_sched_job.h"
3838#include "xe_sriov.h"
39+ #include "xe_sync.h"
3940
4041#define DEFAULT_POLL_FREQUENCY_HZ 200
4142#define DEFAULT_POLL_PERIOD_NS (NSEC_PER_SEC / DEFAULT_POLL_FREQUENCY_HZ)
@@ -70,6 +71,7 @@ struct flex {
7071};
7172
7273struct xe_oa_open_param {
74+ struct xe_file * xef ;
7375 u32 oa_unit_id ;
7476 bool sample ;
7577 u32 metric_set ;
@@ -81,6 +83,9 @@ struct xe_oa_open_param {
8183 struct xe_exec_queue * exec_q ;
8284 struct xe_hw_engine * hwe ;
8385 bool no_preempt ;
86+ struct drm_xe_sync __user * syncs_user ;
87+ int num_syncs ;
88+ struct xe_sync_entry * syncs ;
8489};
8590
8691struct xe_oa_config_bo {
@@ -1398,6 +1403,9 @@ static int xe_oa_stream_init(struct xe_oa_stream *stream,
13981403 stream -> period_exponent = param -> period_exponent ;
13991404 stream -> no_preempt = param -> no_preempt ;
14001405
1406+ stream -> num_syncs = param -> num_syncs ;
1407+ stream -> syncs = param -> syncs ;
1408+
14011409 /*
14021410 * For Xe2+, when overrun mode is enabled, there are no partial reports at the end
14031411 * of buffer, making the OA buffer effectively a non-power-of-2 size circular
@@ -1752,6 +1760,20 @@ static int xe_oa_set_no_preempt(struct xe_oa *oa, u64 value,
17521760 return 0 ;
17531761}
17541762
1763+ static int xe_oa_set_prop_num_syncs (struct xe_oa * oa , u64 value ,
1764+ struct xe_oa_open_param * param )
1765+ {
1766+ param -> num_syncs = value ;
1767+ return 0 ;
1768+ }
1769+
1770+ static int xe_oa_set_prop_syncs_user (struct xe_oa * oa , u64 value ,
1771+ struct xe_oa_open_param * param )
1772+ {
1773+ param -> syncs_user = u64_to_user_ptr (value );
1774+ return 0 ;
1775+ }
1776+
17551777typedef int (* xe_oa_set_property_fn )(struct xe_oa * oa , u64 value ,
17561778 struct xe_oa_open_param * param );
17571779static const xe_oa_set_property_fn xe_oa_set_property_funcs [] = {
@@ -1764,6 +1786,8 @@ static const xe_oa_set_property_fn xe_oa_set_property_funcs[] = {
17641786 [DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID ] = xe_oa_set_prop_exec_queue_id ,
17651787 [DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE ] = xe_oa_set_prop_engine_instance ,
17661788 [DRM_XE_OA_PROPERTY_NO_PREEMPT ] = xe_oa_set_no_preempt ,
1789+ [DRM_XE_OA_PROPERTY_NUM_SYNCS ] = xe_oa_set_prop_num_syncs ,
1790+ [DRM_XE_OA_PROPERTY_SYNCS ] = xe_oa_set_prop_syncs_user ,
17671791};
17681792
17691793static int xe_oa_user_ext_set_property (struct xe_oa * oa , u64 extension ,
@@ -1823,6 +1847,49 @@ static int xe_oa_user_extensions(struct xe_oa *oa, u64 extension, int ext_number
18231847 return 0 ;
18241848}
18251849
1850+ static int xe_oa_parse_syncs (struct xe_oa * oa , struct xe_oa_open_param * param )
1851+ {
1852+ int ret , num_syncs , num_ufence = 0 ;
1853+
1854+ if (param -> num_syncs && !param -> syncs_user ) {
1855+ drm_dbg (& oa -> xe -> drm , "num_syncs specified without sync array\n" );
1856+ ret = - EINVAL ;
1857+ goto exit ;
1858+ }
1859+
1860+ if (param -> num_syncs ) {
1861+ param -> syncs = kcalloc (param -> num_syncs , sizeof (* param -> syncs ), GFP_KERNEL );
1862+ if (!param -> syncs ) {
1863+ ret = - ENOMEM ;
1864+ goto exit ;
1865+ }
1866+ }
1867+
1868+ for (num_syncs = 0 ; num_syncs < param -> num_syncs ; num_syncs ++ ) {
1869+ ret = xe_sync_entry_parse (oa -> xe , param -> xef , & param -> syncs [num_syncs ],
1870+ & param -> syncs_user [num_syncs ], 0 );
1871+ if (ret )
1872+ goto err_syncs ;
1873+
1874+ if (xe_sync_is_ufence (& param -> syncs [num_syncs ]))
1875+ num_ufence ++ ;
1876+ }
1877+
1878+ if (XE_IOCTL_DBG (oa -> xe , num_ufence > 1 )) {
1879+ ret = - EINVAL ;
1880+ goto err_syncs ;
1881+ }
1882+
1883+ return 0 ;
1884+
1885+ err_syncs :
1886+ while (num_syncs -- )
1887+ xe_sync_entry_cleanup (& param -> syncs [num_syncs ]);
1888+ kfree (param -> syncs );
1889+ exit :
1890+ return ret ;
1891+ }
1892+
18261893/**
18271894 * xe_oa_stream_open_ioctl - Opens an OA stream
18281895 * @dev: @drm_device
@@ -1848,6 +1915,7 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
18481915 return - ENODEV ;
18491916 }
18501917
1918+ param .xef = xef ;
18511919 ret = xe_oa_user_extensions (oa , data , 0 , & param );
18521920 if (ret )
18531921 return ret ;
@@ -1916,11 +1984,24 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
19161984 drm_dbg (& oa -> xe -> drm , "Using periodic sampling freq %lld Hz\n" , oa_freq_hz );
19171985 }
19181986
1987+ ret = xe_oa_parse_syncs (oa , & param );
1988+ if (ret )
1989+ goto err_exec_q ;
1990+
19191991 mutex_lock (& param .hwe -> gt -> oa .gt_lock );
19201992 ret = xe_oa_stream_open_ioctl_locked (oa , & param );
19211993 mutex_unlock (& param .hwe -> gt -> oa .gt_lock );
1994+ if (ret < 0 )
1995+ goto err_sync_cleanup ;
1996+
1997+ return ret ;
1998+
1999+ err_sync_cleanup :
2000+ while (param .num_syncs -- )
2001+ xe_sync_entry_cleanup (& param .syncs [param .num_syncs ]);
2002+ kfree (param .syncs );
19222003err_exec_q :
1923- if (ret < 0 && param .exec_q )
2004+ if (param .exec_q )
19242005 xe_exec_queue_put (param .exec_q );
19252006 return ret ;
19262007}
0 commit comments