Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe/oa: Move functions up so they can be reused for config ioctl

No code changes, only code movement so that functions used during stream
open can be reused for the stream reconfiguration
ioctl (DRM_XE_OBSERVATION_IOCTL_CONFIG).

Reviewed-by: Jonathan Cavitt <jonathan.cavitt@intel.com>
Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241022200352.1192560-6-ashutosh.dixit@intel.com

+229 -229
+229 -229
drivers/gpu/drm/xe/xe_oa.c
··· 1141 1141 return xe_oa_emit_oa_config(stream, stream->oa_config); 1142 1142 } 1143 1143 1144 + static int decode_oa_format(struct xe_oa *oa, u64 fmt, enum xe_oa_format_name *name) 1145 + { 1146 + u32 counter_size = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SIZE, fmt); 1147 + u32 counter_sel = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SEL, fmt); 1148 + u32 bc_report = FIELD_GET(DRM_XE_OA_FORMAT_MASK_BC_REPORT, fmt); 1149 + u32 type = FIELD_GET(DRM_XE_OA_FORMAT_MASK_FMT_TYPE, fmt); 1150 + int idx; 1151 + 1152 + for_each_set_bit(idx, oa->format_mask, __XE_OA_FORMAT_MAX) { 1153 + const struct xe_oa_format *f = &oa->oa_formats[idx]; 1154 + 1155 + if (counter_size == f->counter_size && bc_report == f->bc_report && 1156 + type == f->type && counter_sel == f->counter_select) { 1157 + *name = idx; 1158 + return 0; 1159 + } 1160 + } 1161 + 1162 + return -EINVAL; 1163 + } 1164 + 1165 + static int xe_oa_set_prop_oa_unit_id(struct xe_oa *oa, u64 value, 1166 + struct xe_oa_open_param *param) 1167 + { 1168 + if (value >= oa->oa_unit_ids) { 1169 + drm_dbg(&oa->xe->drm, "OA unit ID out of range %lld\n", value); 1170 + return -EINVAL; 1171 + } 1172 + param->oa_unit_id = value; 1173 + return 0; 1174 + } 1175 + 1176 + static int xe_oa_set_prop_sample_oa(struct xe_oa *oa, u64 value, 1177 + struct xe_oa_open_param *param) 1178 + { 1179 + param->sample = value; 1180 + return 0; 1181 + } 1182 + 1183 + static int xe_oa_set_prop_metric_set(struct xe_oa *oa, u64 value, 1184 + struct xe_oa_open_param *param) 1185 + { 1186 + param->metric_set = value; 1187 + return 0; 1188 + } 1189 + 1190 + static int xe_oa_set_prop_oa_format(struct xe_oa *oa, u64 value, 1191 + struct xe_oa_open_param *param) 1192 + { 1193 + int ret = decode_oa_format(oa, value, &param->oa_format); 1194 + 1195 + if (ret) { 1196 + drm_dbg(&oa->xe->drm, "Unsupported OA report format %#llx\n", value); 1197 + return ret; 1198 + } 1199 + return 0; 1200 + } 1201 + 1202 + static int xe_oa_set_prop_oa_exponent(struct xe_oa *oa, u64 value, 1203 + struct xe_oa_open_param *param) 1204 + { 1205 + #define OA_EXPONENT_MAX 31 1206 + 1207 + if (value > OA_EXPONENT_MAX) { 1208 + drm_dbg(&oa->xe->drm, "OA timer exponent too high (> %u)\n", OA_EXPONENT_MAX); 1209 + return -EINVAL; 1210 + } 1211 + param->period_exponent = value; 1212 + return 0; 1213 + } 1214 + 1215 + static int xe_oa_set_prop_disabled(struct xe_oa *oa, u64 value, 1216 + struct xe_oa_open_param *param) 1217 + { 1218 + param->disabled = value; 1219 + return 0; 1220 + } 1221 + 1222 + static int xe_oa_set_prop_exec_queue_id(struct xe_oa *oa, u64 value, 1223 + struct xe_oa_open_param *param) 1224 + { 1225 + param->exec_queue_id = value; 1226 + return 0; 1227 + } 1228 + 1229 + static int xe_oa_set_prop_engine_instance(struct xe_oa *oa, u64 value, 1230 + struct xe_oa_open_param *param) 1231 + { 1232 + param->engine_instance = value; 1233 + return 0; 1234 + } 1235 + 1236 + static int xe_oa_set_no_preempt(struct xe_oa *oa, u64 value, 1237 + struct xe_oa_open_param *param) 1238 + { 1239 + param->no_preempt = value; 1240 + return 0; 1241 + } 1242 + 1243 + static int xe_oa_set_prop_num_syncs(struct xe_oa *oa, u64 value, 1244 + struct xe_oa_open_param *param) 1245 + { 1246 + param->num_syncs = value; 1247 + return 0; 1248 + } 1249 + 1250 + static int xe_oa_set_prop_syncs_user(struct xe_oa *oa, u64 value, 1251 + struct xe_oa_open_param *param) 1252 + { 1253 + param->syncs_user = u64_to_user_ptr(value); 1254 + return 0; 1255 + } 1256 + 1257 + typedef int (*xe_oa_set_property_fn)(struct xe_oa *oa, u64 value, 1258 + struct xe_oa_open_param *param); 1259 + static const xe_oa_set_property_fn xe_oa_set_property_funcs[] = { 1260 + [DRM_XE_OA_PROPERTY_OA_UNIT_ID] = xe_oa_set_prop_oa_unit_id, 1261 + [DRM_XE_OA_PROPERTY_SAMPLE_OA] = xe_oa_set_prop_sample_oa, 1262 + [DRM_XE_OA_PROPERTY_OA_METRIC_SET] = xe_oa_set_prop_metric_set, 1263 + [DRM_XE_OA_PROPERTY_OA_FORMAT] = xe_oa_set_prop_oa_format, 1264 + [DRM_XE_OA_PROPERTY_OA_PERIOD_EXPONENT] = xe_oa_set_prop_oa_exponent, 1265 + [DRM_XE_OA_PROPERTY_OA_DISABLED] = xe_oa_set_prop_disabled, 1266 + [DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID] = xe_oa_set_prop_exec_queue_id, 1267 + [DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE] = xe_oa_set_prop_engine_instance, 1268 + [DRM_XE_OA_PROPERTY_NO_PREEMPT] = xe_oa_set_no_preempt, 1269 + [DRM_XE_OA_PROPERTY_NUM_SYNCS] = xe_oa_set_prop_num_syncs, 1270 + [DRM_XE_OA_PROPERTY_SYNCS] = xe_oa_set_prop_syncs_user, 1271 + }; 1272 + 1273 + static int xe_oa_user_ext_set_property(struct xe_oa *oa, u64 extension, 1274 + struct xe_oa_open_param *param) 1275 + { 1276 + u64 __user *address = u64_to_user_ptr(extension); 1277 + struct drm_xe_ext_set_property ext; 1278 + int err; 1279 + u32 idx; 1280 + 1281 + err = __copy_from_user(&ext, address, sizeof(ext)); 1282 + if (XE_IOCTL_DBG(oa->xe, err)) 1283 + return -EFAULT; 1284 + 1285 + if (XE_IOCTL_DBG(oa->xe, ext.property >= ARRAY_SIZE(xe_oa_set_property_funcs)) || 1286 + XE_IOCTL_DBG(oa->xe, ext.pad)) 1287 + return -EINVAL; 1288 + 1289 + idx = array_index_nospec(ext.property, ARRAY_SIZE(xe_oa_set_property_funcs)); 1290 + return xe_oa_set_property_funcs[idx](oa, ext.value, param); 1291 + } 1292 + 1293 + typedef int (*xe_oa_user_extension_fn)(struct xe_oa *oa, u64 extension, 1294 + struct xe_oa_open_param *param); 1295 + static const xe_oa_user_extension_fn xe_oa_user_extension_funcs[] = { 1296 + [DRM_XE_OA_EXTENSION_SET_PROPERTY] = xe_oa_user_ext_set_property, 1297 + }; 1298 + 1299 + #define MAX_USER_EXTENSIONS 16 1300 + static int xe_oa_user_extensions(struct xe_oa *oa, u64 extension, int ext_number, 1301 + struct xe_oa_open_param *param) 1302 + { 1303 + u64 __user *address = u64_to_user_ptr(extension); 1304 + struct drm_xe_user_extension ext; 1305 + int err; 1306 + u32 idx; 1307 + 1308 + if (XE_IOCTL_DBG(oa->xe, ext_number >= MAX_USER_EXTENSIONS)) 1309 + return -E2BIG; 1310 + 1311 + err = __copy_from_user(&ext, address, sizeof(ext)); 1312 + if (XE_IOCTL_DBG(oa->xe, err)) 1313 + return -EFAULT; 1314 + 1315 + if (XE_IOCTL_DBG(oa->xe, ext.pad) || 1316 + XE_IOCTL_DBG(oa->xe, ext.name >= ARRAY_SIZE(xe_oa_user_extension_funcs))) 1317 + return -EINVAL; 1318 + 1319 + idx = array_index_nospec(ext.name, ARRAY_SIZE(xe_oa_user_extension_funcs)); 1320 + err = xe_oa_user_extension_funcs[idx](oa, extension, param); 1321 + if (XE_IOCTL_DBG(oa->xe, err)) 1322 + return err; 1323 + 1324 + if (ext.next_extension) 1325 + return xe_oa_user_extensions(oa, ext.next_extension, ++ext_number, param); 1326 + 1327 + return 0; 1328 + } 1329 + 1330 + static int xe_oa_parse_syncs(struct xe_oa *oa, struct xe_oa_open_param *param) 1331 + { 1332 + int ret, num_syncs, num_ufence = 0; 1333 + 1334 + if (param->num_syncs && !param->syncs_user) { 1335 + drm_dbg(&oa->xe->drm, "num_syncs specified without sync array\n"); 1336 + ret = -EINVAL; 1337 + goto exit; 1338 + } 1339 + 1340 + if (param->num_syncs) { 1341 + param->syncs = kcalloc(param->num_syncs, sizeof(*param->syncs), GFP_KERNEL); 1342 + if (!param->syncs) { 1343 + ret = -ENOMEM; 1344 + goto exit; 1345 + } 1346 + } 1347 + 1348 + for (num_syncs = 0; num_syncs < param->num_syncs; num_syncs++) { 1349 + ret = xe_sync_entry_parse(oa->xe, param->xef, &param->syncs[num_syncs], 1350 + &param->syncs_user[num_syncs], 0); 1351 + if (ret) 1352 + goto err_syncs; 1353 + 1354 + if (xe_sync_is_ufence(&param->syncs[num_syncs])) 1355 + num_ufence++; 1356 + } 1357 + 1358 + if (XE_IOCTL_DBG(oa->xe, num_ufence > 1)) { 1359 + ret = -EINVAL; 1360 + goto err_syncs; 1361 + } 1362 + 1363 + return 0; 1364 + 1365 + err_syncs: 1366 + while (num_syncs--) 1367 + xe_sync_entry_cleanup(&param->syncs[num_syncs]); 1368 + kfree(param->syncs); 1369 + exit: 1370 + return ret; 1371 + } 1372 + 1144 1373 static void xe_oa_stream_enable(struct xe_oa_stream *stream) 1145 1374 { 1146 1375 stream->pollin = false; ··· 1946 1717 } 1947 1718 } 1948 1719 1949 - static int decode_oa_format(struct xe_oa *oa, u64 fmt, enum xe_oa_format_name *name) 1950 - { 1951 - u32 counter_size = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SIZE, fmt); 1952 - u32 counter_sel = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SEL, fmt); 1953 - u32 bc_report = FIELD_GET(DRM_XE_OA_FORMAT_MASK_BC_REPORT, fmt); 1954 - u32 type = FIELD_GET(DRM_XE_OA_FORMAT_MASK_FMT_TYPE, fmt); 1955 - int idx; 1956 - 1957 - for_each_set_bit(idx, oa->format_mask, __XE_OA_FORMAT_MAX) { 1958 - const struct xe_oa_format *f = &oa->oa_formats[idx]; 1959 - 1960 - if (counter_size == f->counter_size && bc_report == f->bc_report && 1961 - type == f->type && counter_sel == f->counter_select) { 1962 - *name = idx; 1963 - return 0; 1964 - } 1965 - } 1966 - 1967 - return -EINVAL; 1968 - } 1969 - 1970 1720 /** 1971 1721 * xe_oa_unit_id - Return OA unit ID for a hardware engine 1972 1722 * @hwe: @xe_hw_engine ··· 1989 1781 ret = -EINVAL; 1990 1782 } 1991 1783 1992 - return ret; 1993 - } 1994 - 1995 - static int xe_oa_set_prop_oa_unit_id(struct xe_oa *oa, u64 value, 1996 - struct xe_oa_open_param *param) 1997 - { 1998 - if (value >= oa->oa_unit_ids) { 1999 - drm_dbg(&oa->xe->drm, "OA unit ID out of range %lld\n", value); 2000 - return -EINVAL; 2001 - } 2002 - param->oa_unit_id = value; 2003 - return 0; 2004 - } 2005 - 2006 - static int xe_oa_set_prop_sample_oa(struct xe_oa *oa, u64 value, 2007 - struct xe_oa_open_param *param) 2008 - { 2009 - param->sample = value; 2010 - return 0; 2011 - } 2012 - 2013 - static int xe_oa_set_prop_metric_set(struct xe_oa *oa, u64 value, 2014 - struct xe_oa_open_param *param) 2015 - { 2016 - param->metric_set = value; 2017 - return 0; 2018 - } 2019 - 2020 - static int xe_oa_set_prop_oa_format(struct xe_oa *oa, u64 value, 2021 - struct xe_oa_open_param *param) 2022 - { 2023 - int ret = decode_oa_format(oa, value, &param->oa_format); 2024 - 2025 - if (ret) { 2026 - drm_dbg(&oa->xe->drm, "Unsupported OA report format %#llx\n", value); 2027 - return ret; 2028 - } 2029 - return 0; 2030 - } 2031 - 2032 - static int xe_oa_set_prop_oa_exponent(struct xe_oa *oa, u64 value, 2033 - struct xe_oa_open_param *param) 2034 - { 2035 - #define OA_EXPONENT_MAX 31 2036 - 2037 - if (value > OA_EXPONENT_MAX) { 2038 - drm_dbg(&oa->xe->drm, "OA timer exponent too high (> %u)\n", OA_EXPONENT_MAX); 2039 - return -EINVAL; 2040 - } 2041 - param->period_exponent = value; 2042 - return 0; 2043 - } 2044 - 2045 - static int xe_oa_set_prop_disabled(struct xe_oa *oa, u64 value, 2046 - struct xe_oa_open_param *param) 2047 - { 2048 - param->disabled = value; 2049 - return 0; 2050 - } 2051 - 2052 - static int xe_oa_set_prop_exec_queue_id(struct xe_oa *oa, u64 value, 2053 - struct xe_oa_open_param *param) 2054 - { 2055 - param->exec_queue_id = value; 2056 - return 0; 2057 - } 2058 - 2059 - static int xe_oa_set_prop_engine_instance(struct xe_oa *oa, u64 value, 2060 - struct xe_oa_open_param *param) 2061 - { 2062 - param->engine_instance = value; 2063 - return 0; 2064 - } 2065 - 2066 - static int xe_oa_set_no_preempt(struct xe_oa *oa, u64 value, 2067 - struct xe_oa_open_param *param) 2068 - { 2069 - param->no_preempt = value; 2070 - return 0; 2071 - } 2072 - 2073 - static int xe_oa_set_prop_num_syncs(struct xe_oa *oa, u64 value, 2074 - struct xe_oa_open_param *param) 2075 - { 2076 - param->num_syncs = value; 2077 - return 0; 2078 - } 2079 - 2080 - static int xe_oa_set_prop_syncs_user(struct xe_oa *oa, u64 value, 2081 - struct xe_oa_open_param *param) 2082 - { 2083 - param->syncs_user = u64_to_user_ptr(value); 2084 - return 0; 2085 - } 2086 - 2087 - typedef int (*xe_oa_set_property_fn)(struct xe_oa *oa, u64 value, 2088 - struct xe_oa_open_param *param); 2089 - static const xe_oa_set_property_fn xe_oa_set_property_funcs[] = { 2090 - [DRM_XE_OA_PROPERTY_OA_UNIT_ID] = xe_oa_set_prop_oa_unit_id, 2091 - [DRM_XE_OA_PROPERTY_SAMPLE_OA] = xe_oa_set_prop_sample_oa, 2092 - [DRM_XE_OA_PROPERTY_OA_METRIC_SET] = xe_oa_set_prop_metric_set, 2093 - [DRM_XE_OA_PROPERTY_OA_FORMAT] = xe_oa_set_prop_oa_format, 2094 - [DRM_XE_OA_PROPERTY_OA_PERIOD_EXPONENT] = xe_oa_set_prop_oa_exponent, 2095 - [DRM_XE_OA_PROPERTY_OA_DISABLED] = xe_oa_set_prop_disabled, 2096 - [DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID] = xe_oa_set_prop_exec_queue_id, 2097 - [DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE] = xe_oa_set_prop_engine_instance, 2098 - [DRM_XE_OA_PROPERTY_NO_PREEMPT] = xe_oa_set_no_preempt, 2099 - [DRM_XE_OA_PROPERTY_NUM_SYNCS] = xe_oa_set_prop_num_syncs, 2100 - [DRM_XE_OA_PROPERTY_SYNCS] = xe_oa_set_prop_syncs_user, 2101 - }; 2102 - 2103 - static int xe_oa_user_ext_set_property(struct xe_oa *oa, u64 extension, 2104 - struct xe_oa_open_param *param) 2105 - { 2106 - u64 __user *address = u64_to_user_ptr(extension); 2107 - struct drm_xe_ext_set_property ext; 2108 - int err; 2109 - u32 idx; 2110 - 2111 - err = __copy_from_user(&ext, address, sizeof(ext)); 2112 - if (XE_IOCTL_DBG(oa->xe, err)) 2113 - return -EFAULT; 2114 - 2115 - if (XE_IOCTL_DBG(oa->xe, ext.property >= ARRAY_SIZE(xe_oa_set_property_funcs)) || 2116 - XE_IOCTL_DBG(oa->xe, ext.pad)) 2117 - return -EINVAL; 2118 - 2119 - idx = array_index_nospec(ext.property, ARRAY_SIZE(xe_oa_set_property_funcs)); 2120 - return xe_oa_set_property_funcs[idx](oa, ext.value, param); 2121 - } 2122 - 2123 - typedef int (*xe_oa_user_extension_fn)(struct xe_oa *oa, u64 extension, 2124 - struct xe_oa_open_param *param); 2125 - static const xe_oa_user_extension_fn xe_oa_user_extension_funcs[] = { 2126 - [DRM_XE_OA_EXTENSION_SET_PROPERTY] = xe_oa_user_ext_set_property, 2127 - }; 2128 - 2129 - #define MAX_USER_EXTENSIONS 16 2130 - static int xe_oa_user_extensions(struct xe_oa *oa, u64 extension, int ext_number, 2131 - struct xe_oa_open_param *param) 2132 - { 2133 - u64 __user *address = u64_to_user_ptr(extension); 2134 - struct drm_xe_user_extension ext; 2135 - int err; 2136 - u32 idx; 2137 - 2138 - if (XE_IOCTL_DBG(oa->xe, ext_number >= MAX_USER_EXTENSIONS)) 2139 - return -E2BIG; 2140 - 2141 - err = __copy_from_user(&ext, address, sizeof(ext)); 2142 - if (XE_IOCTL_DBG(oa->xe, err)) 2143 - return -EFAULT; 2144 - 2145 - if (XE_IOCTL_DBG(oa->xe, ext.pad) || 2146 - XE_IOCTL_DBG(oa->xe, ext.name >= ARRAY_SIZE(xe_oa_user_extension_funcs))) 2147 - return -EINVAL; 2148 - 2149 - idx = array_index_nospec(ext.name, ARRAY_SIZE(xe_oa_user_extension_funcs)); 2150 - err = xe_oa_user_extension_funcs[idx](oa, extension, param); 2151 - if (XE_IOCTL_DBG(oa->xe, err)) 2152 - return err; 2153 - 2154 - if (ext.next_extension) 2155 - return xe_oa_user_extensions(oa, ext.next_extension, ++ext_number, param); 2156 - 2157 - return 0; 2158 - } 2159 - 2160 - static int xe_oa_parse_syncs(struct xe_oa *oa, struct xe_oa_open_param *param) 2161 - { 2162 - int ret, num_syncs, num_ufence = 0; 2163 - 2164 - if (param->num_syncs && !param->syncs_user) { 2165 - drm_dbg(&oa->xe->drm, "num_syncs specified without sync array\n"); 2166 - ret = -EINVAL; 2167 - goto exit; 2168 - } 2169 - 2170 - if (param->num_syncs) { 2171 - param->syncs = kcalloc(param->num_syncs, sizeof(*param->syncs), GFP_KERNEL); 2172 - if (!param->syncs) { 2173 - ret = -ENOMEM; 2174 - goto exit; 2175 - } 2176 - } 2177 - 2178 - for (num_syncs = 0; num_syncs < param->num_syncs; num_syncs++) { 2179 - ret = xe_sync_entry_parse(oa->xe, param->xef, &param->syncs[num_syncs], 2180 - &param->syncs_user[num_syncs], 0); 2181 - if (ret) 2182 - goto err_syncs; 2183 - 2184 - if (xe_sync_is_ufence(&param->syncs[num_syncs])) 2185 - num_ufence++; 2186 - } 2187 - 2188 - if (XE_IOCTL_DBG(oa->xe, num_ufence > 1)) { 2189 - ret = -EINVAL; 2190 - goto err_syncs; 2191 - } 2192 - 2193 - return 0; 2194 - 2195 - err_syncs: 2196 - while (num_syncs--) 2197 - xe_sync_entry_cleanup(&param->syncs[num_syncs]); 2198 - kfree(param->syncs); 2199 - exit: 2200 1784 return ret; 2201 1785 } 2202 1786