brintos

brintos / linux-shallow public Read only

0
0
Text · 8.5 KiB · cedd3e8 Raw
296 lines · c
1// SPDX-License-Identifier: GPL-2.0 AND MIT2/*3 * Copyright © 2022 Intel Corporation4 */5 6#include <uapi/drm/xe_drm.h>7 8#include <kunit/test.h>9#include <kunit/visibility.h>10 11#include "tests/xe_kunit_helpers.h"12#include "tests/xe_pci_test.h"13 14#include "xe_pci.h"15#include "xe_pm.h"16 17static bool p2p_enabled(struct dma_buf_test_params *params)18{19	return IS_ENABLED(CONFIG_PCI_P2PDMA) && params->attach_ops &&20		params->attach_ops->allow_peer2peer;21}22 23static bool is_dynamic(struct dma_buf_test_params *params)24{25	return IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY) && params->attach_ops &&26		params->attach_ops->move_notify;27}28 29static void check_residency(struct kunit *test, struct xe_bo *exported,30			    struct xe_bo *imported, struct dma_buf *dmabuf)31{32	struct dma_buf_test_params *params = to_dma_buf_test_params(test->priv);33	u32 mem_type;34	int ret;35 36	xe_bo_assert_held(exported);37	xe_bo_assert_held(imported);38 39	mem_type = XE_PL_VRAM0;40	if (!(params->mem_mask & XE_BO_FLAG_VRAM0))41		/* No VRAM allowed */42		mem_type = XE_PL_TT;43	else if (params->force_different_devices && !p2p_enabled(params))44		/* No P2P */45		mem_type = XE_PL_TT;46	else if (params->force_different_devices && !is_dynamic(params) &&47		 (params->mem_mask & XE_BO_FLAG_SYSTEM))48		/* Pin migrated to TT */49		mem_type = XE_PL_TT;50 51	if (!xe_bo_is_mem_type(exported, mem_type)) {52		KUNIT_FAIL(test, "Exported bo was not in expected memory type.\n");53		return;54	}55 56	if (xe_bo_is_pinned(exported))57		return;58 59	/*60	 * Evict exporter. Note that the gem object dma_buf member isn't61	 * set from xe_gem_prime_export(), and it's needed for the move_notify()62	 * functionality, so hack that up here. Evicting the exported bo will63	 * evict also the imported bo through the move_notify() functionality if64	 * importer is on a different device. If they're on the same device,65	 * the exporter and the importer should be the same bo.66	 */67	swap(exported->ttm.base.dma_buf, dmabuf);68	ret = xe_bo_evict(exported, true);69	swap(exported->ttm.base.dma_buf, dmabuf);70	if (ret) {71		if (ret != -EINTR && ret != -ERESTARTSYS)72			KUNIT_FAIL(test, "Evicting exporter failed with err=%d.\n",73				   ret);74		return;75	}76 77	/* Verify that also importer has been evicted to SYSTEM */78	if (exported != imported && !xe_bo_is_mem_type(imported, XE_PL_SYSTEM)) {79		KUNIT_FAIL(test, "Importer wasn't properly evicted.\n");80		return;81	}82 83	/* Re-validate the importer. This should move also exporter in. */84	ret = xe_bo_validate(imported, NULL, false);85	if (ret) {86		if (ret != -EINTR && ret != -ERESTARTSYS)87			KUNIT_FAIL(test, "Validating importer failed with err=%d.\n",88				   ret);89		return;90	}91 92	/*93	 * If on different devices, the exporter is kept in system  if94	 * possible, saving a migration step as the transfer is just95	 * likely as fast from system memory.96	 */97	if (params->mem_mask & XE_BO_FLAG_SYSTEM)98		KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, XE_PL_TT));99	else100		KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, mem_type));101 102	if (params->force_different_devices)103		KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(imported, XE_PL_TT));104	else105		KUNIT_EXPECT_TRUE(test, exported == imported);106}107 108static void xe_test_dmabuf_import_same_driver(struct xe_device *xe)109{110	struct kunit *test = kunit_get_current_test();111	struct dma_buf_test_params *params = to_dma_buf_test_params(test->priv);112	struct drm_gem_object *import;113	struct dma_buf *dmabuf;114	struct xe_bo *bo;115	size_t size;116 117	/* No VRAM on this device? */118	if (!ttm_manager_type(&xe->ttm, XE_PL_VRAM0) &&119	    (params->mem_mask & XE_BO_FLAG_VRAM0))120		return;121 122	size = PAGE_SIZE;123	if ((params->mem_mask & XE_BO_FLAG_VRAM0) &&124	    xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K)125		size = SZ_64K;126 127	kunit_info(test, "running %s\n", __func__);128	bo = xe_bo_create_user(xe, NULL, NULL, size, DRM_XE_GEM_CPU_CACHING_WC,129			       params->mem_mask);130	if (IS_ERR(bo)) {131		KUNIT_FAIL(test, "xe_bo_create() failed with err=%ld\n",132			   PTR_ERR(bo));133		return;134	}135 136	dmabuf = xe_gem_prime_export(&bo->ttm.base, 0);137	if (IS_ERR(dmabuf)) {138		KUNIT_FAIL(test, "xe_gem_prime_export() failed with err=%ld\n",139			   PTR_ERR(dmabuf));140		goto out;141	}142 143	import = xe_gem_prime_import(&xe->drm, dmabuf);144	if (!IS_ERR(import)) {145		struct xe_bo *import_bo = gem_to_xe_bo(import);146 147		/*148		 * Did import succeed when it shouldn't due to lack of p2p support?149		 */150		if (params->force_different_devices &&151		    !p2p_enabled(params) &&152		    !(params->mem_mask & XE_BO_FLAG_SYSTEM)) {153			KUNIT_FAIL(test,154				   "xe_gem_prime_import() succeeded when it shouldn't have\n");155		} else {156			int err;157 158			/* Is everything where we expect it to be? */159			xe_bo_lock(import_bo, false);160			err = xe_bo_validate(import_bo, NULL, false);161 162			/* Pinning in VRAM is not allowed. */163			if (!is_dynamic(params) &&164			    params->force_different_devices &&165			    !(params->mem_mask & XE_BO_FLAG_SYSTEM))166				KUNIT_EXPECT_EQ(test, err, -EINVAL);167			/* Otherwise only expect interrupts or success. */168			else if (err && err != -EINTR && err != -ERESTARTSYS)169				KUNIT_EXPECT_TRUE(test, !err || err == -EINTR ||170						  err == -ERESTARTSYS);171 172			if (!err)173				check_residency(test, bo, import_bo, dmabuf);174			xe_bo_unlock(import_bo);175		}176		drm_gem_object_put(import);177	} else if (PTR_ERR(import) != -EOPNOTSUPP) {178		/* Unexpected error code. */179		KUNIT_FAIL(test,180			   "xe_gem_prime_import failed with the wrong err=%ld\n",181			   PTR_ERR(import));182	} else if (!params->force_different_devices ||183		   p2p_enabled(params) ||184		   (params->mem_mask & XE_BO_FLAG_SYSTEM)) {185		/* Shouldn't fail if we can reuse same bo, use p2p or use system */186		KUNIT_FAIL(test, "dynamic p2p attachment failed with err=%ld\n",187			   PTR_ERR(import));188	}189	dma_buf_put(dmabuf);190out:191	drm_gem_object_put(&bo->ttm.base);192}193 194static const struct dma_buf_attach_ops nop2p_attach_ops = {195	.allow_peer2peer = false,196	.move_notify = xe_dma_buf_move_notify197};198 199/*200 * We test the implementation with bos of different residency and with201 * importers with different capabilities; some lacking p2p support and some202 * lacking dynamic capabilities (attach_ops == NULL). We also fake203 * different devices avoiding the import shortcut that just reuses the same204 * gem object.205 */206static const struct dma_buf_test_params test_params[] = {207	{.mem_mask = XE_BO_FLAG_VRAM0,208	 .attach_ops = &xe_dma_buf_attach_ops},209	{.mem_mask = XE_BO_FLAG_VRAM0,210	 .attach_ops = &xe_dma_buf_attach_ops,211	 .force_different_devices = true},212 213	{.mem_mask = XE_BO_FLAG_VRAM0,214	 .attach_ops = &nop2p_attach_ops},215	{.mem_mask = XE_BO_FLAG_VRAM0,216	 .attach_ops = &nop2p_attach_ops,217	 .force_different_devices = true},218 219	{.mem_mask = XE_BO_FLAG_VRAM0},220	{.mem_mask = XE_BO_FLAG_VRAM0,221	 .force_different_devices = true},222 223	{.mem_mask = XE_BO_FLAG_SYSTEM,224	 .attach_ops = &xe_dma_buf_attach_ops},225	{.mem_mask = XE_BO_FLAG_SYSTEM,226	 .attach_ops = &xe_dma_buf_attach_ops,227	 .force_different_devices = true},228 229	{.mem_mask = XE_BO_FLAG_SYSTEM,230	 .attach_ops = &nop2p_attach_ops},231	{.mem_mask = XE_BO_FLAG_SYSTEM,232	 .attach_ops = &nop2p_attach_ops,233	 .force_different_devices = true},234 235	{.mem_mask = XE_BO_FLAG_SYSTEM},236	{.mem_mask = XE_BO_FLAG_SYSTEM,237	 .force_different_devices = true},238 239	{.mem_mask = XE_BO_FLAG_SYSTEM | XE_BO_FLAG_VRAM0,240	 .attach_ops = &xe_dma_buf_attach_ops},241	{.mem_mask = XE_BO_FLAG_SYSTEM | XE_BO_FLAG_VRAM0,242	 .attach_ops = &xe_dma_buf_attach_ops,243	 .force_different_devices = true},244 245	{.mem_mask = XE_BO_FLAG_SYSTEM | XE_BO_FLAG_VRAM0,246	 .attach_ops = &nop2p_attach_ops},247	{.mem_mask = XE_BO_FLAG_SYSTEM | XE_BO_FLAG_VRAM0,248	 .attach_ops = &nop2p_attach_ops,249	 .force_different_devices = true},250 251	{.mem_mask = XE_BO_FLAG_SYSTEM | XE_BO_FLAG_VRAM0},252	{.mem_mask = XE_BO_FLAG_SYSTEM | XE_BO_FLAG_VRAM0,253	 .force_different_devices = true},254 255	{}256};257 258static int dma_buf_run_device(struct xe_device *xe)259{260	const struct dma_buf_test_params *params;261	struct kunit *test = kunit_get_current_test();262 263	xe_pm_runtime_get(xe);264	for (params = test_params; params->mem_mask; ++params) {265		struct dma_buf_test_params p = *params;266 267		p.base.id = XE_TEST_LIVE_DMA_BUF;268		test->priv = &p;269		xe_test_dmabuf_import_same_driver(xe);270	}271	xe_pm_runtime_put(xe);272 273	/* A non-zero return would halt iteration over driver devices */274	return 0;275}276 277static void xe_dma_buf_kunit(struct kunit *test)278{279	struct xe_device *xe = test->priv;280 281	dma_buf_run_device(xe);282}283 284static struct kunit_case xe_dma_buf_tests[] = {285	KUNIT_CASE_PARAM(xe_dma_buf_kunit, xe_pci_live_device_gen_param),286	{}287};288 289VISIBLE_IF_KUNIT290struct kunit_suite xe_dma_buf_test_suite = {291	.name = "xe_dma_buf",292	.test_cases = xe_dma_buf_tests,293	.init = xe_kunit_helper_xe_device_live_test_init,294};295EXPORT_SYMBOL_IF_KUNIT(xe_dma_buf_test_suite);296