drivers/gpu/drm/xe/tests/xe_guc_g2g_test.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xe/tests/xe_guc_g2g_test.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/tests/xe_guc_g2g_test.c
Extension
.c
Size
22089 bytes
Lines
834
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct g2g_test_payload  {
	u32 tx_dev;
	u32 tx_tile;
	u32 rx_dev;
	u32 rx_tile;
	u32 seqno;
};

static int slot_index_from_gts(struct xe_gt *tx_gt, struct xe_gt *rx_gt)
{
	struct xe_device *xe = gt_to_xe(tx_gt);
	int idx = 0, found = 0, id, tx_idx, rx_idx;
	struct xe_gt *gt;
	struct kunit *test = kunit_get_current_test();

	for (id = 0; id < xe->info.tile_count * xe->info.max_gt_per_tile; id++) {
		gt = xe_device_get_gt(xe, id);
		if (!gt)
			continue;
		if (gt == tx_gt) {
			tx_idx = idx;
			found++;
		}
		if (gt == rx_gt) {
			rx_idx = idx;
			found++;
		}

		if (found == 2)
			break;

		idx++;
	}

	if (found != 2)
		KUNIT_FAIL(test, "GT index not found");

	return (tx_idx * xe->info.gt_count) + rx_idx;
}

static void g2g_test_send(struct kunit *test, struct xe_guc *guc,
			  u32 far_tile, u32 far_dev,
			  struct g2g_test_payload *payload)
{
	struct xe_device *xe = guc_to_xe(guc);
	struct xe_gt *gt = guc_to_gt(guc);
	u32 *action, total;
	size_t payload_len;
	int ret;

	static_assert(IS_ALIGNED(sizeof(*payload), sizeof(u32)));
	payload_len = sizeof(*payload) / sizeof(u32);

	total = 4 + payload_len;
	action = kunit_kmalloc_array(test, total, sizeof(*action), GFP_KERNEL);
	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, action);

	action[0] = XE_GUC_ACTION_TEST_G2G_SEND;
	action[1] = far_tile;
	action[2] = far_dev;
	action[3] = payload_len;
	memcpy(action + 4, payload, payload_len * sizeof(u32));

	atomic_inc(&xe->g2g_test_count);

	/*
	 * Should specify the expected response notification here. Problem is that
	 * the response will be coming from a different GuC. By the end, it should
	 * all add up as long as an equal number of messages are sent from each GuC
	 * and to each GuC. However, in the middle negative reservation space errors
	 * and such like can occur. Rather than add intrusive changes to the CT layer
	 * it is simpler to just not bother counting it at all. The system should be
	 * idle when running the selftest, and the selftest's notification total size
	 * is well within the G2H allocation size. So there should be no issues with
	 * needing to block for space, which is all the tracking code is really for.
	 */
	ret = xe_guc_ct_send(&guc->ct, action, total, 0, 0);
	kunit_kfree(test, action);
	KUNIT_ASSERT_EQ_MSG(test, 0, ret, "G2G send failed: %d [%d:%d -> %d:%d]\n", ret,
			    gt_to_tile(gt)->id, G2G_DEV(gt), far_tile, far_dev);
}

/*
 * NB: Can't use KUNIT_ASSERT and friends in here as this is called asynchronously
 * from the G2H notification handler. Need that to actually complete rather than
 * thread-abort in order to keep the rest of the driver alive!
 */
int xe_guc_g2g_test_notification(struct xe_guc *guc, u32 *msg, u32 len)
{
	struct xe_device *xe = guc_to_xe(guc);

Annotation

Implementation Notes