brintos

brintos / linux-shallow public Read only

0
0
Text · 14.2 KiB · 36a3b54 Raw
547 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright © 2023 Intel Corporation4 */5 6#include <linux/string.h>7#include <linux/xarray.h>8 9#include <drm/drm_drv.h>10#include <drm/drm_kunit_helpers.h>11 12#include <kunit/test.h>13 14#include "regs/xe_gt_regs.h"15#include "regs/xe_reg_defs.h"16#include "xe_device.h"17#include "xe_device_types.h"18#include "xe_kunit_helpers.h"19#include "xe_pci_test.h"20#include "xe_reg_sr.h"21#include "xe_rtp.h"22 23#define REGULAR_REG1	XE_REG(1)24#define REGULAR_REG2	XE_REG(2)25#define REGULAR_REG3	XE_REG(3)26#define MCR_REG1	XE_REG_MCR(1)27#define MCR_REG2	XE_REG_MCR(2)28#define MCR_REG3	XE_REG_MCR(3)29#define MASKED_REG1	XE_REG(1, XE_REG_OPTION_MASKED)30 31#undef XE_REG_MCR32#define XE_REG_MCR(...)     XE_REG(__VA_ARGS__, .mcr = 1)33 34struct rtp_to_sr_test_case {35	const char *name;36	struct xe_reg expected_reg;37	u32 expected_set_bits;38	u32 expected_clr_bits;39	unsigned long expected_count_sr_entries;40	unsigned int expected_sr_errors;41	unsigned long expected_active;42	const struct xe_rtp_entry_sr *entries;43};44 45struct rtp_test_case {46	const char *name;47	unsigned long expected_active;48	const struct xe_rtp_entry *entries;49};50 51static bool match_yes(const struct xe_gt *gt, const struct xe_hw_engine *hwe)52{53	return true;54}55 56static bool match_no(const struct xe_gt *gt, const struct xe_hw_engine *hwe)57{58	return false;59}60 61static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {62	{63		.name = "coalesce-same-reg",64		.expected_reg = REGULAR_REG1,65		.expected_set_bits = REG_BIT(0) | REG_BIT(1),66		.expected_clr_bits = REG_BIT(0) | REG_BIT(1),67		.expected_active = BIT(0) | BIT(1),68		.expected_count_sr_entries = 1,69		/* Different bits on the same register: create a single entry */70		.entries = (const struct xe_rtp_entry_sr[]) {71			{ XE_RTP_NAME("basic-1"),72			  XE_RTP_RULES(FUNC(match_yes)),73			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))74			},75			{ XE_RTP_NAME("basic-2"),76			  XE_RTP_RULES(FUNC(match_yes)),77			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))78			},79			{}80		},81	},82	{83		.name = "no-match-no-add",84		.expected_reg = REGULAR_REG1,85		.expected_set_bits = REG_BIT(0),86		.expected_clr_bits = REG_BIT(0),87		.expected_active = BIT(0),88		.expected_count_sr_entries = 1,89		/* Don't coalesce second entry since rules don't match */90		.entries = (const struct xe_rtp_entry_sr[]) {91			{ XE_RTP_NAME("basic-1"),92			  XE_RTP_RULES(FUNC(match_yes)),93			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))94			},95			{ XE_RTP_NAME("basic-2"),96			  XE_RTP_RULES(FUNC(match_no)),97			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))98			},99			{}100		},101	},102	{103		.name = "match-or",104		.expected_reg = REGULAR_REG1,105		.expected_set_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2),106		.expected_clr_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2),107		.expected_active = BIT(0) | BIT(1) | BIT(2),108		.expected_count_sr_entries = 1,109		.entries = (const struct xe_rtp_entry_sr[]) {110			{ XE_RTP_NAME("first"),111			  XE_RTP_RULES(FUNC(match_yes), OR, FUNC(match_no)),112			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))113			},114			{ XE_RTP_NAME("middle"),115			  XE_RTP_RULES(FUNC(match_no), FUNC(match_no), OR,116				       FUNC(match_yes), OR,117				       FUNC(match_no)),118			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))119			},120			{ XE_RTP_NAME("last"),121			  XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_yes)),122			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2)))123			},124			{ XE_RTP_NAME("no-match"),125			  XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_no)),126			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(3)))127			},128			{}129		},130	},131	{132		.name = "match-or-xfail",133		.expected_reg = REGULAR_REG1,134		.expected_count_sr_entries = 0,135		.entries = (const struct xe_rtp_entry_sr[]) {136			{ XE_RTP_NAME("leading-or"),137			  XE_RTP_RULES(OR, FUNC(match_yes)),138			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))139			},140			{ XE_RTP_NAME("trailing-or"),141			  /*142			   * First condition is match_no, otherwise the failure143			   * wouldn't really trigger as RTP stops processing as144			   * soon as it has a matching set of rules145			   */146			  XE_RTP_RULES(FUNC(match_no), OR),147			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))148			},149			{ XE_RTP_NAME("no-or-or-yes"),150			  XE_RTP_RULES(FUNC(match_no), OR, OR, FUNC(match_yes)),151			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2)))152			},153			{}154		},155	},156	{157		.name = "no-match-no-add-multiple-rules",158		.expected_reg = REGULAR_REG1,159		.expected_set_bits = REG_BIT(0),160		.expected_clr_bits = REG_BIT(0),161		.expected_active = BIT(0),162		.expected_count_sr_entries = 1,163		/* Don't coalesce second entry due to one of the rules */164		.entries = (const struct xe_rtp_entry_sr[]) {165			{ XE_RTP_NAME("basic-1"),166			  XE_RTP_RULES(FUNC(match_yes)),167			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))168			},169			{ XE_RTP_NAME("basic-2"),170			  XE_RTP_RULES(FUNC(match_yes), FUNC(match_no)),171			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))172			},173			{}174		},175	},176	{177		.name = "two-regs-two-entries",178		.expected_reg = REGULAR_REG1,179		.expected_set_bits = REG_BIT(0),180		.expected_clr_bits = REG_BIT(0),181		.expected_active = BIT(0) | BIT(1),182		.expected_count_sr_entries = 2,183		/* Same bits on different registers are not coalesced */184		.entries = (const struct xe_rtp_entry_sr[]) {185			{ XE_RTP_NAME("basic-1"),186			  XE_RTP_RULES(FUNC(match_yes)),187			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))188			},189			{ XE_RTP_NAME("basic-2"),190			  XE_RTP_RULES(FUNC(match_yes)),191			  XE_RTP_ACTIONS(SET(REGULAR_REG2, REG_BIT(0)))192			},193			{}194		},195	},196	{197		.name = "clr-one-set-other",198		.expected_reg = REGULAR_REG1,199		.expected_set_bits = REG_BIT(0),200		.expected_clr_bits = REG_BIT(1) | REG_BIT(0),201		.expected_active = BIT(0) | BIT(1),202		.expected_count_sr_entries = 1,203		/* Check clr vs set actions on different bits */204		.entries = (const struct xe_rtp_entry_sr[]) {205			{ XE_RTP_NAME("basic-1"),206			  XE_RTP_RULES(FUNC(match_yes)),207			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))208			},209			{ XE_RTP_NAME("basic-2"),210			  XE_RTP_RULES(FUNC(match_yes)),211			  XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_BIT(1)))212			},213			{}214		},215	},216	{217#define TEMP_MASK	REG_GENMASK(10, 8)218#define TEMP_FIELD	REG_FIELD_PREP(TEMP_MASK, 2)219		.name = "set-field",220		.expected_reg = REGULAR_REG1,221		.expected_set_bits = TEMP_FIELD,222		.expected_clr_bits = TEMP_MASK,223		.expected_active = BIT(0),224		.expected_count_sr_entries = 1,225		/* Check FIELD_SET works */226		.entries = (const struct xe_rtp_entry_sr[]) {227			{ XE_RTP_NAME("basic-1"),228			  XE_RTP_RULES(FUNC(match_yes)),229			  XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1,230						   TEMP_MASK, TEMP_FIELD))231			},232			{}233		},234#undef TEMP_MASK235#undef TEMP_FIELD236	},237	{238		.name = "conflict-duplicate",239		.expected_reg = REGULAR_REG1,240		.expected_set_bits = REG_BIT(0),241		.expected_clr_bits = REG_BIT(0),242		.expected_active = BIT(0) | BIT(1),243		.expected_count_sr_entries = 1,244		.expected_sr_errors = 1,245		.entries = (const struct xe_rtp_entry_sr[]) {246			{ XE_RTP_NAME("basic-1"),247			  XE_RTP_RULES(FUNC(match_yes)),248			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))249			},250			/* drop: setting same values twice */251			{ XE_RTP_NAME("basic-2"),252			  XE_RTP_RULES(FUNC(match_yes)),253			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))254			},255			{}256		},257	},258	{259		.name = "conflict-not-disjoint",260		.expected_reg = REGULAR_REG1,261		.expected_set_bits = REG_BIT(0),262		.expected_clr_bits = REG_BIT(0),263		.expected_active = BIT(0) | BIT(1),264		.expected_count_sr_entries = 1,265		.expected_sr_errors = 1,266		.entries = (const struct xe_rtp_entry_sr[]) {267			{ XE_RTP_NAME("basic-1"),268			  XE_RTP_RULES(FUNC(match_yes)),269			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))270			},271			/* drop: bits are not disjoint with previous entries */272			{ XE_RTP_NAME("basic-2"),273			  XE_RTP_RULES(FUNC(match_yes)),274			  XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_GENMASK(1, 0)))275			},276			{}277		},278	},279	{280		.name = "conflict-reg-type",281		.expected_reg = REGULAR_REG1,282		.expected_set_bits = REG_BIT(0),283		.expected_clr_bits = REG_BIT(0),284		.expected_active = BIT(0) | BIT(1) | BIT(2),285		.expected_count_sr_entries = 1,286		.expected_sr_errors = 2,287		.entries = (const struct xe_rtp_entry_sr[]) {288			{ XE_RTP_NAME("basic-1"),289			  XE_RTP_RULES(FUNC(match_yes)),290			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))291			},292			/* drop: regular vs MCR */293			{ XE_RTP_NAME("basic-2"),294			  XE_RTP_RULES(FUNC(match_yes)),295			  XE_RTP_ACTIONS(SET(MCR_REG1, REG_BIT(1)))296			},297			/* drop: regular vs masked */298			{ XE_RTP_NAME("basic-3"),299			  XE_RTP_RULES(FUNC(match_yes)),300			  XE_RTP_ACTIONS(SET(MASKED_REG1, REG_BIT(0)))301			},302			{}303		},304	},305};306 307static void xe_rtp_process_to_sr_tests(struct kunit *test)308{309	const struct rtp_to_sr_test_case *param = test->param_value;310	struct xe_device *xe = test->priv;311	struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt;312	struct xe_reg_sr *reg_sr = &gt->reg_sr;313	const struct xe_reg_sr_entry *sre, *sr_entry = NULL;314	struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);315	unsigned long idx, count_sr_entries = 0, count_rtp_entries = 0, active = 0;316 317	xe_reg_sr_init(reg_sr, "xe_rtp_to_sr_tests", xe);318 319	while (param->entries[count_rtp_entries].rules)320		count_rtp_entries++;321 322	xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, count_rtp_entries);323	xe_rtp_process_to_sr(&ctx, param->entries, reg_sr);324 325	xa_for_each(&reg_sr->xa, idx, sre) {326		if (idx == param->expected_reg.addr)327			sr_entry = sre;328 329		count_sr_entries++;330	}331 332	KUNIT_EXPECT_EQ(test, active, param->expected_active);333 334	KUNIT_EXPECT_EQ(test, count_sr_entries, param->expected_count_sr_entries);335	if (count_sr_entries) {336		KUNIT_EXPECT_EQ(test, sr_entry->clr_bits, param->expected_clr_bits);337		KUNIT_EXPECT_EQ(test, sr_entry->set_bits, param->expected_set_bits);338		KUNIT_EXPECT_EQ(test, sr_entry->reg.raw, param->expected_reg.raw);339	} else {340		KUNIT_EXPECT_NULL(test, sr_entry);341	}342 343	KUNIT_EXPECT_EQ(test, reg_sr->errors, param->expected_sr_errors);344}345 346/*347 * Entries below follow the logic used with xe_wa_oob.rules:348 * 1) Entries with empty name are OR'ed: all entries marked active since the349 *    last entry with a name350 * 2) There are no action associated with rules351 */352static const struct rtp_test_case rtp_cases[] = {353	{354		.name = "active1",355		.expected_active = BIT(0),356		.entries = (const struct xe_rtp_entry[]) {357			{ XE_RTP_NAME("r1"),358			  XE_RTP_RULES(FUNC(match_yes)),359			},360			{}361		},362	},363	{364		.name = "active2",365		.expected_active = BIT(0) | BIT(1),366		.entries = (const struct xe_rtp_entry[]) {367			{ XE_RTP_NAME("r1"),368			  XE_RTP_RULES(FUNC(match_yes)),369			},370			{ XE_RTP_NAME("r2"),371			  XE_RTP_RULES(FUNC(match_yes)),372			},373			{}374		},375	},376	{377		.name = "active-inactive",378		.expected_active = BIT(0),379		.entries = (const struct xe_rtp_entry[]) {380			{ XE_RTP_NAME("r1"),381			  XE_RTP_RULES(FUNC(match_yes)),382			},383			{ XE_RTP_NAME("r2"),384			  XE_RTP_RULES(FUNC(match_no)),385			},386			{}387		},388	},389	{390		.name = "inactive-active",391		.expected_active = BIT(1),392		.entries = (const struct xe_rtp_entry[]) {393			{ XE_RTP_NAME("r1"),394			  XE_RTP_RULES(FUNC(match_no)),395			},396			{ XE_RTP_NAME("r2"),397			  XE_RTP_RULES(FUNC(match_yes)),398			},399			{}400		},401	},402	{403		.name = "inactive-1st_or_active-inactive",404		.expected_active = BIT(1),405		.entries = (const struct xe_rtp_entry[]) {406			{ XE_RTP_NAME("r1"),407			  XE_RTP_RULES(FUNC(match_no)),408			},409			{ XE_RTP_NAME("r2_or_conditions"),410			  XE_RTP_RULES(FUNC(match_yes), OR,411				       FUNC(match_no), OR,412				       FUNC(match_no)) },413			{ XE_RTP_NAME("r3"),414			  XE_RTP_RULES(FUNC(match_no)),415			},416			{}417		},418	},419	{420		.name = "inactive-2nd_or_active-inactive",421		.expected_active = BIT(1),422		.entries = (const struct xe_rtp_entry[]) {423			{ XE_RTP_NAME("r1"),424			  XE_RTP_RULES(FUNC(match_no)),425			},426			{ XE_RTP_NAME("r2_or_conditions"),427			  XE_RTP_RULES(FUNC(match_no), OR,428				       FUNC(match_yes), OR,429				       FUNC(match_no)) },430			{ XE_RTP_NAME("r3"),431			  XE_RTP_RULES(FUNC(match_no)),432			},433			{}434		},435	},436	{437		.name = "inactive-last_or_active-inactive",438		.expected_active = BIT(1),439		.entries = (const struct xe_rtp_entry[]) {440			{ XE_RTP_NAME("r1"),441			  XE_RTP_RULES(FUNC(match_no)),442			},443			{ XE_RTP_NAME("r2_or_conditions"),444			  XE_RTP_RULES(FUNC(match_no), OR,445				       FUNC(match_no), OR,446				       FUNC(match_yes)) },447			{ XE_RTP_NAME("r3"),448			  XE_RTP_RULES(FUNC(match_no)),449			},450			{}451		},452	},453	{454		.name = "inactive-no_or_active-inactive",455		.expected_active = 0,456		.entries = (const struct xe_rtp_entry[]) {457			{ XE_RTP_NAME("r1"),458			  XE_RTP_RULES(FUNC(match_no)),459			},460			{ XE_RTP_NAME("r2_or_conditions"),461			  XE_RTP_RULES(FUNC(match_no), OR,462				       FUNC(match_no), OR,463				       FUNC(match_no)) },464			{ XE_RTP_NAME("r3"),465			  XE_RTP_RULES(FUNC(match_no)),466			},467			{}468		},469	},470};471 472static void xe_rtp_process_tests(struct kunit *test)473{474	const struct rtp_test_case *param = test->param_value;475	struct xe_device *xe = test->priv;476	struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt;477	struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);478	unsigned long count_rtp_entries = 0, active = 0;479 480	while (param->entries[count_rtp_entries].rules)481		count_rtp_entries++;482 483	xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, count_rtp_entries);484	xe_rtp_process(&ctx, param->entries);485 486	KUNIT_EXPECT_EQ(test, active, param->expected_active);487}488 489static void rtp_to_sr_desc(const struct rtp_to_sr_test_case *t, char *desc)490{491	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);492}493 494KUNIT_ARRAY_PARAM(rtp_to_sr, rtp_to_sr_cases, rtp_to_sr_desc);495 496static void rtp_desc(const struct rtp_test_case *t, char *desc)497{498	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);499}500 501KUNIT_ARRAY_PARAM(rtp, rtp_cases, rtp_desc);502 503static int xe_rtp_test_init(struct kunit *test)504{505	struct xe_device *xe;506	struct device *dev;507	int ret;508 509	dev = drm_kunit_helper_alloc_device(test);510	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);511 512	xe = xe_kunit_helper_alloc_xe_device(test, dev);513	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xe);514 515	/* Initialize an empty device */516	test->priv = NULL;517	ret = xe_pci_fake_device_init(xe);518	KUNIT_ASSERT_EQ(test, ret, 0);519 520	xe->drm.dev = dev;521	test->priv = xe;522 523	return 0;524}525 526static void xe_rtp_test_exit(struct kunit *test)527{528	struct xe_device *xe = test->priv;529 530	drm_kunit_helper_free_device(test, xe->drm.dev);531}532 533static struct kunit_case xe_rtp_tests[] = {534	KUNIT_CASE_PARAM(xe_rtp_process_to_sr_tests, rtp_to_sr_gen_params),535	KUNIT_CASE_PARAM(xe_rtp_process_tests, rtp_gen_params),536	{}537};538 539static struct kunit_suite xe_rtp_test_suite = {540	.name = "xe_rtp",541	.init = xe_rtp_test_init,542	.exit = xe_rtp_test_exit,543	.test_cases = xe_rtp_tests,544};545 546kunit_test_suite(xe_rtp_test_suite);547