1*456b32c9SJohn Harrison // SPDX-License-Identifier: GPL-2.0 AND MIT 2*456b32c9SJohn Harrison /* 3*456b32c9SJohn Harrison * Copyright © 2025 Intel Corporation 4*456b32c9SJohn Harrison */ 5*456b32c9SJohn Harrison 6*456b32c9SJohn Harrison #include <linux/delay.h> 7*456b32c9SJohn Harrison 8*456b32c9SJohn Harrison #include <kunit/test.h> 9*456b32c9SJohn Harrison #include <kunit/visibility.h> 10*456b32c9SJohn Harrison 11*456b32c9SJohn Harrison #include "tests/xe_kunit_helpers.h" 12*456b32c9SJohn Harrison #include "tests/xe_pci_test.h" 13*456b32c9SJohn Harrison #include "tests/xe_test.h" 14*456b32c9SJohn Harrison 15*456b32c9SJohn Harrison #include "xe_bo.h" 16*456b32c9SJohn Harrison #include "xe_device.h" 17*456b32c9SJohn Harrison #include "xe_pm.h" 18*456b32c9SJohn Harrison 19*456b32c9SJohn Harrison /* 20*456b32c9SJohn Harrison * There are different ways to allocate the G2G buffers. The plan for this test 21*456b32c9SJohn Harrison * is to make sure that all the possible options work. The particular option 22*456b32c9SJohn Harrison * chosen by the driver may vary from one platform to another, it may also change 23*456b32c9SJohn Harrison * with time. So to ensure consistency of testing, the relevant driver code is 24*456b32c9SJohn Harrison * replicated here to guarantee it won't change without the test being updated 25*456b32c9SJohn Harrison * to keep testing the other options. 26*456b32c9SJohn Harrison * 27*456b32c9SJohn Harrison * In order to test the actual code being used by the driver, there is also the 28*456b32c9SJohn Harrison * 'default' scheme. That will use the official driver routines to test whatever 29*456b32c9SJohn Harrison * method the driver is using on the current platform at the current time. 30*456b32c9SJohn Harrison */ 31*456b32c9SJohn Harrison enum { 32*456b32c9SJohn Harrison /* Driver defined allocation scheme */ 33*456b32c9SJohn Harrison G2G_CTB_TYPE_DEFAULT, 34*456b32c9SJohn Harrison /* Single buffer in host memory */ 35*456b32c9SJohn Harrison G2G_CTB_TYPE_HOST, 36*456b32c9SJohn Harrison /* Single buffer in a specific tile, loops across all tiles */ 37*456b32c9SJohn Harrison G2G_CTB_TYPE_TILE, 38*456b32c9SJohn Harrison }; 39*456b32c9SJohn Harrison 40*456b32c9SJohn Harrison /* 41*456b32c9SJohn Harrison * Payload is opaque to GuC. So KMD can define any structure or size it wants. 42*456b32c9SJohn Harrison */ 43*456b32c9SJohn Harrison struct g2g_test_payload { 44*456b32c9SJohn Harrison u32 tx_dev; 45*456b32c9SJohn Harrison u32 tx_tile; 46*456b32c9SJohn Harrison u32 rx_dev; 47*456b32c9SJohn Harrison u32 rx_tile; 48*456b32c9SJohn Harrison u32 seqno; 49*456b32c9SJohn Harrison }; 50*456b32c9SJohn Harrison 51*456b32c9SJohn Harrison static void g2g_test_send(struct kunit *test, struct xe_guc *guc, 52*456b32c9SJohn Harrison u32 far_tile, u32 far_dev, 53*456b32c9SJohn Harrison struct g2g_test_payload *payload) 54*456b32c9SJohn Harrison { 55*456b32c9SJohn Harrison struct xe_device *xe = guc_to_xe(guc); 56*456b32c9SJohn Harrison struct xe_gt *gt = guc_to_gt(guc); 57*456b32c9SJohn Harrison u32 *action, total; 58*456b32c9SJohn Harrison size_t payload_len; 59*456b32c9SJohn Harrison int ret; 60*456b32c9SJohn Harrison 61*456b32c9SJohn Harrison static_assert(IS_ALIGNED(sizeof(*payload), sizeof(u32))); 62*456b32c9SJohn Harrison payload_len = sizeof(*payload) / sizeof(u32); 63*456b32c9SJohn Harrison 64*456b32c9SJohn Harrison total = 4 + payload_len; 65*456b32c9SJohn Harrison action = kunit_kmalloc_array(test, total, sizeof(*action), GFP_KERNEL); 66*456b32c9SJohn Harrison KUNIT_ASSERT_NOT_ERR_OR_NULL(test, action); 67*456b32c9SJohn Harrison 68*456b32c9SJohn Harrison action[0] = XE_GUC_ACTION_TEST_G2G_SEND; 69*456b32c9SJohn Harrison action[1] = far_tile; 70*456b32c9SJohn Harrison action[2] = far_dev; 71*456b32c9SJohn Harrison action[3] = payload_len; 72*456b32c9SJohn Harrison memcpy(action + 4, payload, payload_len * sizeof(u32)); 73*456b32c9SJohn Harrison 74*456b32c9SJohn Harrison atomic_inc(&xe->g2g_test_count); 75*456b32c9SJohn Harrison 76*456b32c9SJohn Harrison /* 77*456b32c9SJohn Harrison * Should specify the expected response notification here. Problem is that 78*456b32c9SJohn Harrison * the response will be coming from a different GuC. By the end, it should 79*456b32c9SJohn Harrison * all add up as long as an equal number of messages are sent from each GuC 80*456b32c9SJohn Harrison * and to each GuC. However, in the middle negative reservation space errors 81*456b32c9SJohn Harrison * and such like can occur. Rather than add intrusive changes to the CT layer 82*456b32c9SJohn Harrison * it is simpler to just not bother counting it at all. The system should be 83*456b32c9SJohn Harrison * idle when running the selftest, and the selftest's notification total size 84*456b32c9SJohn Harrison * is well within the G2H allocation size. So there should be no issues with 85*456b32c9SJohn Harrison * needing to block for space, which is all the tracking code is really for. 86*456b32c9SJohn Harrison */ 87*456b32c9SJohn Harrison ret = xe_guc_ct_send(&guc->ct, action, total, 0, 0); 88*456b32c9SJohn Harrison kunit_kfree(test, action); 89*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, 0, ret, "G2G send failed: %d [%d:%d -> %d:%d]\n", ret, 90*456b32c9SJohn Harrison gt_to_tile(gt)->id, G2G_DEV(gt), far_tile, far_dev); 91*456b32c9SJohn Harrison } 92*456b32c9SJohn Harrison 93*456b32c9SJohn Harrison /* 94*456b32c9SJohn Harrison * NB: Can't use KUNIT_ASSERT and friends in here as this is called asynchronously 95*456b32c9SJohn Harrison * from the G2H notification handler. Need that to actually complete rather than 96*456b32c9SJohn Harrison * thread-abort in order to keep the rest of the driver alive! 97*456b32c9SJohn Harrison */ 98*456b32c9SJohn Harrison int xe_guc_g2g_test_notification(struct xe_guc *guc, u32 *msg, u32 len) 99*456b32c9SJohn Harrison { 100*456b32c9SJohn Harrison struct xe_device *xe = guc_to_xe(guc); 101*456b32c9SJohn Harrison struct xe_gt *rx_gt = guc_to_gt(guc), *test_gt, *tx_gt = NULL; 102*456b32c9SJohn Harrison u32 tx_tile, tx_dev, rx_tile, rx_dev, idx, got_len; 103*456b32c9SJohn Harrison struct g2g_test_payload *payload; 104*456b32c9SJohn Harrison size_t payload_len; 105*456b32c9SJohn Harrison int ret = 0, i; 106*456b32c9SJohn Harrison 107*456b32c9SJohn Harrison payload_len = sizeof(*payload) / sizeof(u32); 108*456b32c9SJohn Harrison 109*456b32c9SJohn Harrison if (unlikely(len != (G2H_LEN_DW_G2G_NOTIFY_MIN + payload_len))) { 110*456b32c9SJohn Harrison xe_gt_err(rx_gt, "G2G test notification invalid length %u", len); 111*456b32c9SJohn Harrison ret = -EPROTO; 112*456b32c9SJohn Harrison goto done; 113*456b32c9SJohn Harrison } 114*456b32c9SJohn Harrison 115*456b32c9SJohn Harrison tx_tile = msg[0]; 116*456b32c9SJohn Harrison tx_dev = msg[1]; 117*456b32c9SJohn Harrison got_len = msg[2]; 118*456b32c9SJohn Harrison payload = (struct g2g_test_payload *)(msg + 3); 119*456b32c9SJohn Harrison 120*456b32c9SJohn Harrison rx_tile = gt_to_tile(rx_gt)->id; 121*456b32c9SJohn Harrison rx_dev = G2G_DEV(rx_gt); 122*456b32c9SJohn Harrison 123*456b32c9SJohn Harrison if (got_len != payload_len) { 124*456b32c9SJohn Harrison xe_gt_err(rx_gt, "G2G: Invalid payload length: %u vs %zu\n", got_len, payload_len); 125*456b32c9SJohn Harrison ret = -EPROTO; 126*456b32c9SJohn Harrison goto done; 127*456b32c9SJohn Harrison } 128*456b32c9SJohn Harrison 129*456b32c9SJohn Harrison if (payload->tx_dev != tx_dev || payload->tx_tile != tx_tile || 130*456b32c9SJohn Harrison payload->rx_dev != rx_dev || payload->rx_tile != rx_tile) { 131*456b32c9SJohn Harrison xe_gt_err(rx_gt, "G2G: Invalid payload: %d:%d -> %d:%d vs %d:%d -> %d:%d! [%d]\n", 132*456b32c9SJohn Harrison payload->tx_tile, payload->tx_dev, payload->rx_tile, payload->rx_dev, 133*456b32c9SJohn Harrison tx_tile, tx_dev, rx_tile, rx_dev, payload->seqno); 134*456b32c9SJohn Harrison ret = -EPROTO; 135*456b32c9SJohn Harrison goto done; 136*456b32c9SJohn Harrison } 137*456b32c9SJohn Harrison 138*456b32c9SJohn Harrison if (!xe->g2g_test_array) { 139*456b32c9SJohn Harrison xe_gt_err(rx_gt, "G2G: Missing test array!\n"); 140*456b32c9SJohn Harrison ret = -ENOMEM; 141*456b32c9SJohn Harrison goto done; 142*456b32c9SJohn Harrison } 143*456b32c9SJohn Harrison 144*456b32c9SJohn Harrison for_each_gt(test_gt, xe, i) { 145*456b32c9SJohn Harrison if (gt_to_tile(test_gt)->id != tx_tile) 146*456b32c9SJohn Harrison continue; 147*456b32c9SJohn Harrison 148*456b32c9SJohn Harrison if (G2G_DEV(test_gt) != tx_dev) 149*456b32c9SJohn Harrison continue; 150*456b32c9SJohn Harrison 151*456b32c9SJohn Harrison if (tx_gt) { 152*456b32c9SJohn Harrison xe_gt_err(rx_gt, "G2G: Got duplicate TX GTs: %d vs %d for %d:%d!\n", 153*456b32c9SJohn Harrison tx_gt->info.id, test_gt->info.id, tx_tile, tx_dev); 154*456b32c9SJohn Harrison ret = -EINVAL; 155*456b32c9SJohn Harrison goto done; 156*456b32c9SJohn Harrison } 157*456b32c9SJohn Harrison 158*456b32c9SJohn Harrison tx_gt = test_gt; 159*456b32c9SJohn Harrison } 160*456b32c9SJohn Harrison if (!tx_gt) { 161*456b32c9SJohn Harrison xe_gt_err(rx_gt, "G2G: Failed to find a TX GT for %d:%d!\n", tx_tile, tx_dev); 162*456b32c9SJohn Harrison ret = -EINVAL; 163*456b32c9SJohn Harrison goto done; 164*456b32c9SJohn Harrison } 165*456b32c9SJohn Harrison 166*456b32c9SJohn Harrison idx = (tx_gt->info.id * xe->info.gt_count) + rx_gt->info.id; 167*456b32c9SJohn Harrison 168*456b32c9SJohn Harrison if (xe->g2g_test_array[idx] != payload->seqno - 1) { 169*456b32c9SJohn Harrison xe_gt_err(rx_gt, "G2G: Seqno mismatch %d vs %d for %d:%d -> %d:%d!\n", 170*456b32c9SJohn Harrison xe->g2g_test_array[idx], payload->seqno - 1, 171*456b32c9SJohn Harrison tx_tile, tx_dev, rx_tile, rx_dev); 172*456b32c9SJohn Harrison ret = -EINVAL; 173*456b32c9SJohn Harrison goto done; 174*456b32c9SJohn Harrison } 175*456b32c9SJohn Harrison 176*456b32c9SJohn Harrison xe->g2g_test_array[idx] = payload->seqno; 177*456b32c9SJohn Harrison 178*456b32c9SJohn Harrison done: 179*456b32c9SJohn Harrison atomic_dec(&xe->g2g_test_count); 180*456b32c9SJohn Harrison return ret; 181*456b32c9SJohn Harrison } 182*456b32c9SJohn Harrison 183*456b32c9SJohn Harrison /* 184*456b32c9SJohn Harrison * Send the given seqno from all GuCs to all other GuCs in tile/GT order 185*456b32c9SJohn Harrison */ 186*456b32c9SJohn Harrison static void g2g_test_in_order(struct kunit *test, struct xe_device *xe, u32 seqno) 187*456b32c9SJohn Harrison { 188*456b32c9SJohn Harrison struct xe_gt *near_gt, *far_gt; 189*456b32c9SJohn Harrison int i, j; 190*456b32c9SJohn Harrison 191*456b32c9SJohn Harrison for_each_gt(near_gt, xe, i) { 192*456b32c9SJohn Harrison u32 near_tile = gt_to_tile(near_gt)->id; 193*456b32c9SJohn Harrison u32 near_dev = G2G_DEV(near_gt); 194*456b32c9SJohn Harrison 195*456b32c9SJohn Harrison for_each_gt(far_gt, xe, j) { 196*456b32c9SJohn Harrison u32 far_tile = gt_to_tile(far_gt)->id; 197*456b32c9SJohn Harrison u32 far_dev = G2G_DEV(far_gt); 198*456b32c9SJohn Harrison struct g2g_test_payload payload; 199*456b32c9SJohn Harrison 200*456b32c9SJohn Harrison if (far_gt->info.id == near_gt->info.id) 201*456b32c9SJohn Harrison continue; 202*456b32c9SJohn Harrison 203*456b32c9SJohn Harrison payload.tx_dev = near_dev; 204*456b32c9SJohn Harrison payload.tx_tile = near_tile; 205*456b32c9SJohn Harrison payload.rx_dev = far_dev; 206*456b32c9SJohn Harrison payload.rx_tile = far_tile; 207*456b32c9SJohn Harrison payload.seqno = seqno; 208*456b32c9SJohn Harrison g2g_test_send(test, &near_gt->uc.guc, far_tile, far_dev, &payload); 209*456b32c9SJohn Harrison } 210*456b32c9SJohn Harrison } 211*456b32c9SJohn Harrison } 212*456b32c9SJohn Harrison 213*456b32c9SJohn Harrison #define WAIT_TIME_MS 100 214*456b32c9SJohn Harrison #define WAIT_COUNT (1000 / WAIT_TIME_MS) 215*456b32c9SJohn Harrison 216*456b32c9SJohn Harrison static void g2g_wait_for_complete(void *_xe) 217*456b32c9SJohn Harrison { 218*456b32c9SJohn Harrison struct xe_device *xe = (struct xe_device *)_xe; 219*456b32c9SJohn Harrison struct kunit *test = kunit_get_current_test(); 220*456b32c9SJohn Harrison int wait = 0; 221*456b32c9SJohn Harrison 222*456b32c9SJohn Harrison /* Wait for all G2H messages to be received */ 223*456b32c9SJohn Harrison while (atomic_read(&xe->g2g_test_count)) { 224*456b32c9SJohn Harrison if (++wait > WAIT_COUNT) 225*456b32c9SJohn Harrison break; 226*456b32c9SJohn Harrison 227*456b32c9SJohn Harrison msleep(WAIT_TIME_MS); 228*456b32c9SJohn Harrison } 229*456b32c9SJohn Harrison 230*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, 0, atomic_read(&xe->g2g_test_count), 231*456b32c9SJohn Harrison "Timed out waiting for notifications\n"); 232*456b32c9SJohn Harrison kunit_info(test, "Got all notifications back\n"); 233*456b32c9SJohn Harrison } 234*456b32c9SJohn Harrison 235*456b32c9SJohn Harrison #undef WAIT_TIME_MS 236*456b32c9SJohn Harrison #undef WAIT_COUNT 237*456b32c9SJohn Harrison 238*456b32c9SJohn Harrison static void g2g_clean_array(void *_xe) 239*456b32c9SJohn Harrison { 240*456b32c9SJohn Harrison struct xe_device *xe = (struct xe_device *)_xe; 241*456b32c9SJohn Harrison 242*456b32c9SJohn Harrison xe->g2g_test_array = NULL; 243*456b32c9SJohn Harrison } 244*456b32c9SJohn Harrison 245*456b32c9SJohn Harrison #define NUM_LOOPS 16 246*456b32c9SJohn Harrison 247*456b32c9SJohn Harrison static void g2g_run_test(struct kunit *test, struct xe_device *xe) 248*456b32c9SJohn Harrison { 249*456b32c9SJohn Harrison u32 seqno, max_array; 250*456b32c9SJohn Harrison int ret, i, j; 251*456b32c9SJohn Harrison 252*456b32c9SJohn Harrison max_array = xe->info.gt_count * xe->info.gt_count; 253*456b32c9SJohn Harrison xe->g2g_test_array = kunit_kcalloc(test, max_array, sizeof(u32), GFP_KERNEL); 254*456b32c9SJohn Harrison KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xe->g2g_test_array); 255*456b32c9SJohn Harrison 256*456b32c9SJohn Harrison ret = kunit_add_action_or_reset(test, g2g_clean_array, xe); 257*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, 0, ret, "Failed to register clean up action\n"); 258*456b32c9SJohn Harrison 259*456b32c9SJohn Harrison /* 260*456b32c9SJohn Harrison * Send incrementing seqnos from all GuCs to all other GuCs in tile/GT order. 261*456b32c9SJohn Harrison * Tile/GT order doesn't really mean anything to the hardware but it is going 262*456b32c9SJohn Harrison * to be a fixed sequence every time. 263*456b32c9SJohn Harrison * 264*456b32c9SJohn Harrison * Verify that each one comes back having taken the correct route. 265*456b32c9SJohn Harrison */ 266*456b32c9SJohn Harrison ret = kunit_add_action(test, g2g_wait_for_complete, xe); 267*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, 0, ret, "Failed to register clean up action\n"); 268*456b32c9SJohn Harrison for (seqno = 1; seqno < NUM_LOOPS; seqno++) 269*456b32c9SJohn Harrison g2g_test_in_order(test, xe, seqno); 270*456b32c9SJohn Harrison seqno--; 271*456b32c9SJohn Harrison 272*456b32c9SJohn Harrison kunit_release_action(test, &g2g_wait_for_complete, xe); 273*456b32c9SJohn Harrison 274*456b32c9SJohn Harrison /* Check for the final seqno in each slot */ 275*456b32c9SJohn Harrison for (i = 0; i < xe->info.gt_count; i++) { 276*456b32c9SJohn Harrison for (j = 0; j < xe->info.gt_count; j++) { 277*456b32c9SJohn Harrison u32 idx = (j * xe->info.gt_count) + i; 278*456b32c9SJohn Harrison 279*456b32c9SJohn Harrison if (i == j) 280*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, 0, xe->g2g_test_array[idx], 281*456b32c9SJohn Harrison "identity seqno modified: %d for %dx%d!\n", 282*456b32c9SJohn Harrison xe->g2g_test_array[idx], i, j); 283*456b32c9SJohn Harrison else 284*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, seqno, xe->g2g_test_array[idx], 285*456b32c9SJohn Harrison "invalid seqno: %d vs %d for %dx%d!\n", 286*456b32c9SJohn Harrison xe->g2g_test_array[idx], seqno, i, j); 287*456b32c9SJohn Harrison } 288*456b32c9SJohn Harrison } 289*456b32c9SJohn Harrison 290*456b32c9SJohn Harrison kunit_kfree(test, xe->g2g_test_array); 291*456b32c9SJohn Harrison kunit_release_action(test, &g2g_clean_array, xe); 292*456b32c9SJohn Harrison 293*456b32c9SJohn Harrison kunit_info(test, "Test passed\n"); 294*456b32c9SJohn Harrison } 295*456b32c9SJohn Harrison 296*456b32c9SJohn Harrison #undef NUM_LOOPS 297*456b32c9SJohn Harrison 298*456b32c9SJohn Harrison static void g2g_ct_stop(struct xe_guc *guc) 299*456b32c9SJohn Harrison { 300*456b32c9SJohn Harrison struct xe_gt *remote_gt, *gt = guc_to_gt(guc); 301*456b32c9SJohn Harrison struct xe_device *xe = gt_to_xe(gt); 302*456b32c9SJohn Harrison int i, t; 303*456b32c9SJohn Harrison 304*456b32c9SJohn Harrison for_each_gt(remote_gt, xe, i) { 305*456b32c9SJohn Harrison u32 tile, dev; 306*456b32c9SJohn Harrison 307*456b32c9SJohn Harrison if (remote_gt->info.id == gt->info.id) 308*456b32c9SJohn Harrison continue; 309*456b32c9SJohn Harrison 310*456b32c9SJohn Harrison tile = gt_to_tile(remote_gt)->id; 311*456b32c9SJohn Harrison dev = G2G_DEV(remote_gt); 312*456b32c9SJohn Harrison 313*456b32c9SJohn Harrison for (t = 0; t < XE_G2G_TYPE_LIMIT; t++) 314*456b32c9SJohn Harrison guc_g2g_deregister(guc, tile, dev, t); 315*456b32c9SJohn Harrison } 316*456b32c9SJohn Harrison } 317*456b32c9SJohn Harrison 318*456b32c9SJohn Harrison /* Size of a single allocation that contains all G2G CTBs across all GTs */ 319*456b32c9SJohn Harrison static u32 g2g_ctb_size(struct kunit *test, struct xe_device *xe) 320*456b32c9SJohn Harrison { 321*456b32c9SJohn Harrison unsigned int count = xe->info.gt_count; 322*456b32c9SJohn Harrison u32 num_channels = (count * (count - 1)) / 2; 323*456b32c9SJohn Harrison 324*456b32c9SJohn Harrison kunit_info(test, "Size: (%d * %d / 2) * %d * 0x%08X + 0x%08X => 0x%08X [%d]\n", 325*456b32c9SJohn Harrison count, count - 1, XE_G2G_TYPE_LIMIT, G2G_BUFFER_SIZE, G2G_DESC_AREA_SIZE, 326*456b32c9SJohn Harrison num_channels * XE_G2G_TYPE_LIMIT * G2G_BUFFER_SIZE + G2G_DESC_AREA_SIZE, 327*456b32c9SJohn Harrison num_channels * XE_G2G_TYPE_LIMIT); 328*456b32c9SJohn Harrison 329*456b32c9SJohn Harrison return num_channels * XE_G2G_TYPE_LIMIT * G2G_BUFFER_SIZE + G2G_DESC_AREA_SIZE; 330*456b32c9SJohn Harrison } 331*456b32c9SJohn Harrison 332*456b32c9SJohn Harrison /* 333*456b32c9SJohn Harrison * Use the driver's regular CTB allocation scheme. 334*456b32c9SJohn Harrison */ 335*456b32c9SJohn Harrison static void g2g_alloc_default(struct kunit *test, struct xe_device *xe) 336*456b32c9SJohn Harrison { 337*456b32c9SJohn Harrison struct xe_gt *gt; 338*456b32c9SJohn Harrison int i; 339*456b32c9SJohn Harrison 340*456b32c9SJohn Harrison kunit_info(test, "Default [tiles = %d, GTs = %d]\n", 341*456b32c9SJohn Harrison xe->info.tile_count, xe->info.gt_count); 342*456b32c9SJohn Harrison 343*456b32c9SJohn Harrison for_each_gt(gt, xe, i) { 344*456b32c9SJohn Harrison struct xe_guc *guc = >->uc.guc; 345*456b32c9SJohn Harrison int ret; 346*456b32c9SJohn Harrison 347*456b32c9SJohn Harrison ret = guc_g2g_alloc(guc); 348*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, 0, ret, "G2G alloc failed: %pe", ERR_PTR(ret)); 349*456b32c9SJohn Harrison continue; 350*456b32c9SJohn Harrison } 351*456b32c9SJohn Harrison } 352*456b32c9SJohn Harrison 353*456b32c9SJohn Harrison static void g2g_distribute(struct kunit *test, struct xe_device *xe, struct xe_bo *bo) 354*456b32c9SJohn Harrison { 355*456b32c9SJohn Harrison struct xe_gt *root_gt, *gt; 356*456b32c9SJohn Harrison int i; 357*456b32c9SJohn Harrison 358*456b32c9SJohn Harrison root_gt = xe_device_get_gt(xe, 0); 359*456b32c9SJohn Harrison root_gt->uc.guc.g2g.bo = bo; 360*456b32c9SJohn Harrison root_gt->uc.guc.g2g.owned = true; 361*456b32c9SJohn Harrison kunit_info(test, "[%d.%d] Assigned 0x%p\n", gt_to_tile(root_gt)->id, root_gt->info.id, bo); 362*456b32c9SJohn Harrison 363*456b32c9SJohn Harrison for_each_gt(gt, xe, i) { 364*456b32c9SJohn Harrison if (gt->info.id != 0) { 365*456b32c9SJohn Harrison gt->uc.guc.g2g.owned = false; 366*456b32c9SJohn Harrison gt->uc.guc.g2g.bo = xe_bo_get(bo); 367*456b32c9SJohn Harrison kunit_info(test, "[%d.%d] Pinned 0x%p\n", 368*456b32c9SJohn Harrison gt_to_tile(gt)->id, gt->info.id, gt->uc.guc.g2g.bo); 369*456b32c9SJohn Harrison } 370*456b32c9SJohn Harrison 371*456b32c9SJohn Harrison KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gt->uc.guc.g2g.bo); 372*456b32c9SJohn Harrison } 373*456b32c9SJohn Harrison } 374*456b32c9SJohn Harrison 375*456b32c9SJohn Harrison /* 376*456b32c9SJohn Harrison * Allocate a single blob on the host and split between all G2G CTBs. 377*456b32c9SJohn Harrison */ 378*456b32c9SJohn Harrison static void g2g_alloc_host(struct kunit *test, struct xe_device *xe) 379*456b32c9SJohn Harrison { 380*456b32c9SJohn Harrison struct xe_bo *bo; 381*456b32c9SJohn Harrison u32 g2g_size; 382*456b32c9SJohn Harrison 383*456b32c9SJohn Harrison kunit_info(test, "Host [tiles = %d, GTs = %d]\n", xe->info.tile_count, xe->info.gt_count); 384*456b32c9SJohn Harrison 385*456b32c9SJohn Harrison g2g_size = g2g_ctb_size(test, xe); 386*456b32c9SJohn Harrison bo = xe_managed_bo_create_pin_map(xe, xe_device_get_root_tile(xe), g2g_size, 387*456b32c9SJohn Harrison XE_BO_FLAG_SYSTEM | 388*456b32c9SJohn Harrison XE_BO_FLAG_GGTT | 389*456b32c9SJohn Harrison XE_BO_FLAG_GGTT_ALL | 390*456b32c9SJohn Harrison XE_BO_FLAG_GGTT_INVALIDATE); 391*456b32c9SJohn Harrison KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo); 392*456b32c9SJohn Harrison kunit_info(test, "[HST] G2G buffer create: 0x%p\n", bo); 393*456b32c9SJohn Harrison 394*456b32c9SJohn Harrison xe_map_memset(xe, &bo->vmap, 0, 0, g2g_size); 395*456b32c9SJohn Harrison 396*456b32c9SJohn Harrison g2g_distribute(test, xe, bo); 397*456b32c9SJohn Harrison } 398*456b32c9SJohn Harrison 399*456b32c9SJohn Harrison /* 400*456b32c9SJohn Harrison * Allocate a single blob on the given tile and split between all G2G CTBs. 401*456b32c9SJohn Harrison */ 402*456b32c9SJohn Harrison static void g2g_alloc_tile(struct kunit *test, struct xe_device *xe, struct xe_tile *tile) 403*456b32c9SJohn Harrison { 404*456b32c9SJohn Harrison struct xe_bo *bo; 405*456b32c9SJohn Harrison u32 g2g_size; 406*456b32c9SJohn Harrison 407*456b32c9SJohn Harrison KUNIT_ASSERT_TRUE(test, IS_DGFX(xe)); 408*456b32c9SJohn Harrison KUNIT_ASSERT_NOT_ERR_OR_NULL(test, tile); 409*456b32c9SJohn Harrison 410*456b32c9SJohn Harrison kunit_info(test, "Tile %d [tiles = %d, GTs = %d]\n", 411*456b32c9SJohn Harrison tile->id, xe->info.tile_count, xe->info.gt_count); 412*456b32c9SJohn Harrison 413*456b32c9SJohn Harrison g2g_size = g2g_ctb_size(test, xe); 414*456b32c9SJohn Harrison bo = xe_managed_bo_create_pin_map(xe, tile, g2g_size, 415*456b32c9SJohn Harrison XE_BO_FLAG_VRAM_IF_DGFX(tile) | 416*456b32c9SJohn Harrison XE_BO_FLAG_GGTT | 417*456b32c9SJohn Harrison XE_BO_FLAG_GGTT_ALL | 418*456b32c9SJohn Harrison XE_BO_FLAG_GGTT_INVALIDATE); 419*456b32c9SJohn Harrison KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo); 420*456b32c9SJohn Harrison kunit_info(test, "[%d.*] G2G buffer create: 0x%p\n", tile->id, bo); 421*456b32c9SJohn Harrison 422*456b32c9SJohn Harrison xe_map_memset(xe, &bo->vmap, 0, 0, g2g_size); 423*456b32c9SJohn Harrison 424*456b32c9SJohn Harrison g2g_distribute(test, xe, bo); 425*456b32c9SJohn Harrison } 426*456b32c9SJohn Harrison 427*456b32c9SJohn Harrison static void g2g_free(struct kunit *test, struct xe_device *xe) 428*456b32c9SJohn Harrison { 429*456b32c9SJohn Harrison struct xe_gt *gt; 430*456b32c9SJohn Harrison struct xe_bo *bo; 431*456b32c9SJohn Harrison int i; 432*456b32c9SJohn Harrison 433*456b32c9SJohn Harrison for_each_gt(gt, xe, i) { 434*456b32c9SJohn Harrison bo = gt->uc.guc.g2g.bo; 435*456b32c9SJohn Harrison if (!bo) 436*456b32c9SJohn Harrison continue; 437*456b32c9SJohn Harrison 438*456b32c9SJohn Harrison if (gt->uc.guc.g2g.owned) { 439*456b32c9SJohn Harrison xe_managed_bo_unpin_map_no_vm(bo); 440*456b32c9SJohn Harrison kunit_info(test, "[%d.%d] Unmapped 0x%p\n", 441*456b32c9SJohn Harrison gt_to_tile(gt)->id, gt->info.id, bo); 442*456b32c9SJohn Harrison } else { 443*456b32c9SJohn Harrison xe_bo_put(bo); 444*456b32c9SJohn Harrison kunit_info(test, "[%d.%d] Unpinned 0x%p\n", 445*456b32c9SJohn Harrison gt_to_tile(gt)->id, gt->info.id, bo); 446*456b32c9SJohn Harrison } 447*456b32c9SJohn Harrison 448*456b32c9SJohn Harrison gt->uc.guc.g2g.bo = NULL; 449*456b32c9SJohn Harrison } 450*456b32c9SJohn Harrison } 451*456b32c9SJohn Harrison 452*456b32c9SJohn Harrison static void g2g_stop(struct kunit *test, struct xe_device *xe) 453*456b32c9SJohn Harrison { 454*456b32c9SJohn Harrison struct xe_gt *gt; 455*456b32c9SJohn Harrison int i; 456*456b32c9SJohn Harrison 457*456b32c9SJohn Harrison for_each_gt(gt, xe, i) { 458*456b32c9SJohn Harrison struct xe_guc *guc = >->uc.guc; 459*456b32c9SJohn Harrison 460*456b32c9SJohn Harrison if (!guc->g2g.bo) 461*456b32c9SJohn Harrison continue; 462*456b32c9SJohn Harrison 463*456b32c9SJohn Harrison g2g_ct_stop(guc); 464*456b32c9SJohn Harrison } 465*456b32c9SJohn Harrison 466*456b32c9SJohn Harrison g2g_free(test, xe); 467*456b32c9SJohn Harrison } 468*456b32c9SJohn Harrison 469*456b32c9SJohn Harrison /* 470*456b32c9SJohn Harrison * Generate a unique id for each bi-directional CTB for each pair of 471*456b32c9SJohn Harrison * near and far tiles/devices. The id can then be used as an index into 472*456b32c9SJohn Harrison * a single allocation that is sub-divided into multiple CTBs. 473*456b32c9SJohn Harrison * 474*456b32c9SJohn Harrison * For example, with two devices per tile and two tiles, the table should 475*456b32c9SJohn Harrison * look like: 476*456b32c9SJohn Harrison * Far <tile>.<dev> 477*456b32c9SJohn Harrison * 0.0 0.1 1.0 1.1 478*456b32c9SJohn Harrison * N 0.0 --/-- 00/01 02/03 04/05 479*456b32c9SJohn Harrison * e 0.1 01/00 --/-- 06/07 08/09 480*456b32c9SJohn Harrison * a 1.0 03/02 07/06 --/-- 10/11 481*456b32c9SJohn Harrison * r 1.1 05/04 09/08 11/10 --/-- 482*456b32c9SJohn Harrison * 483*456b32c9SJohn Harrison * Where each entry is Rx/Tx channel id. 484*456b32c9SJohn Harrison * 485*456b32c9SJohn Harrison * So GuC #3 (tile 1, dev 1) talking to GuC #2 (tile 1, dev 0) would 486*456b32c9SJohn Harrison * be reading from channel #11 and writing to channel #10. Whereas, 487*456b32c9SJohn Harrison * GuC #2 talking to GuC #3 would be read on #10 and write to #11. 488*456b32c9SJohn Harrison */ 489*456b32c9SJohn Harrison static int g2g_slot_flat(u32 near_tile, u32 near_dev, u32 far_tile, u32 far_dev, 490*456b32c9SJohn Harrison u32 type, u32 max_inst, bool have_dev) 491*456b32c9SJohn Harrison { 492*456b32c9SJohn Harrison u32 near = near_tile, far = far_tile; 493*456b32c9SJohn Harrison u32 idx = 0, x, y, direction; 494*456b32c9SJohn Harrison int i; 495*456b32c9SJohn Harrison 496*456b32c9SJohn Harrison if (have_dev) { 497*456b32c9SJohn Harrison near = (near << 1) | near_dev; 498*456b32c9SJohn Harrison far = (far << 1) | far_dev; 499*456b32c9SJohn Harrison } 500*456b32c9SJohn Harrison 501*456b32c9SJohn Harrison /* No need to send to one's self */ 502*456b32c9SJohn Harrison if (far == near) 503*456b32c9SJohn Harrison return -1; 504*456b32c9SJohn Harrison 505*456b32c9SJohn Harrison if (far > near) { 506*456b32c9SJohn Harrison /* Top right table half */ 507*456b32c9SJohn Harrison x = far; 508*456b32c9SJohn Harrison y = near; 509*456b32c9SJohn Harrison 510*456b32c9SJohn Harrison /* T/R is 'forwards' direction */ 511*456b32c9SJohn Harrison direction = type; 512*456b32c9SJohn Harrison } else { 513*456b32c9SJohn Harrison /* Bottom left table half */ 514*456b32c9SJohn Harrison x = near; 515*456b32c9SJohn Harrison y = far; 516*456b32c9SJohn Harrison 517*456b32c9SJohn Harrison /* B/L is 'backwards' direction */ 518*456b32c9SJohn Harrison direction = (1 - type); 519*456b32c9SJohn Harrison } 520*456b32c9SJohn Harrison 521*456b32c9SJohn Harrison /* Count the rows prior to the target */ 522*456b32c9SJohn Harrison for (i = y; i > 0; i--) 523*456b32c9SJohn Harrison idx += max_inst - i; 524*456b32c9SJohn Harrison 525*456b32c9SJohn Harrison /* Count this row up to the target */ 526*456b32c9SJohn Harrison idx += (x - 1 - y); 527*456b32c9SJohn Harrison 528*456b32c9SJohn Harrison /* Slots are in Rx/Tx pairs */ 529*456b32c9SJohn Harrison idx *= 2; 530*456b32c9SJohn Harrison 531*456b32c9SJohn Harrison /* Pick Rx/Tx direction */ 532*456b32c9SJohn Harrison idx += direction; 533*456b32c9SJohn Harrison 534*456b32c9SJohn Harrison return idx; 535*456b32c9SJohn Harrison } 536*456b32c9SJohn Harrison 537*456b32c9SJohn Harrison static int g2g_register_flat(struct xe_guc *guc, u32 far_tile, u32 far_dev, u32 type, bool have_dev) 538*456b32c9SJohn Harrison { 539*456b32c9SJohn Harrison struct xe_gt *gt = guc_to_gt(guc); 540*456b32c9SJohn Harrison struct xe_device *xe = gt_to_xe(gt); 541*456b32c9SJohn Harrison u32 near_tile = gt_to_tile(gt)->id; 542*456b32c9SJohn Harrison u32 near_dev = G2G_DEV(gt); 543*456b32c9SJohn Harrison u32 max = xe->info.gt_count; 544*456b32c9SJohn Harrison int idx; 545*456b32c9SJohn Harrison u32 base, desc, buf; 546*456b32c9SJohn Harrison 547*456b32c9SJohn Harrison if (!guc->g2g.bo) 548*456b32c9SJohn Harrison return -ENODEV; 549*456b32c9SJohn Harrison 550*456b32c9SJohn Harrison idx = g2g_slot_flat(near_tile, near_dev, far_tile, far_dev, type, max, have_dev); 551*456b32c9SJohn Harrison xe_assert(xe, idx >= 0); 552*456b32c9SJohn Harrison 553*456b32c9SJohn Harrison base = guc_bo_ggtt_addr(guc, guc->g2g.bo); 554*456b32c9SJohn Harrison desc = base + idx * G2G_DESC_SIZE; 555*456b32c9SJohn Harrison buf = base + idx * G2G_BUFFER_SIZE + G2G_DESC_AREA_SIZE; 556*456b32c9SJohn Harrison 557*456b32c9SJohn Harrison xe_assert(xe, (desc - base + G2G_DESC_SIZE) <= G2G_DESC_AREA_SIZE); 558*456b32c9SJohn Harrison xe_assert(xe, (buf - base + G2G_BUFFER_SIZE) <= xe_bo_size(guc->g2g.bo)); 559*456b32c9SJohn Harrison 560*456b32c9SJohn Harrison return guc_action_register_g2g_buffer(guc, type, far_tile, far_dev, 561*456b32c9SJohn Harrison desc, buf, G2G_BUFFER_SIZE); 562*456b32c9SJohn Harrison } 563*456b32c9SJohn Harrison 564*456b32c9SJohn Harrison static void g2g_start(struct kunit *test, struct xe_guc *guc) 565*456b32c9SJohn Harrison { 566*456b32c9SJohn Harrison struct xe_gt *remote_gt, *gt = guc_to_gt(guc); 567*456b32c9SJohn Harrison struct xe_device *xe = gt_to_xe(gt); 568*456b32c9SJohn Harrison unsigned int i; 569*456b32c9SJohn Harrison int t, ret; 570*456b32c9SJohn Harrison bool have_dev; 571*456b32c9SJohn Harrison 572*456b32c9SJohn Harrison KUNIT_ASSERT_NOT_ERR_OR_NULL(test, guc->g2g.bo); 573*456b32c9SJohn Harrison 574*456b32c9SJohn Harrison /* GuC interface will need extending if more GT device types are ever created. */ 575*456b32c9SJohn Harrison KUNIT_ASSERT_TRUE(test, 576*456b32c9SJohn Harrison (gt->info.type == XE_GT_TYPE_MAIN) || 577*456b32c9SJohn Harrison (gt->info.type == XE_GT_TYPE_MEDIA)); 578*456b32c9SJohn Harrison 579*456b32c9SJohn Harrison /* Channel numbering depends on whether there are multiple GTs per tile */ 580*456b32c9SJohn Harrison have_dev = xe->info.gt_count > xe->info.tile_count; 581*456b32c9SJohn Harrison 582*456b32c9SJohn Harrison for_each_gt(remote_gt, xe, i) { 583*456b32c9SJohn Harrison u32 tile, dev; 584*456b32c9SJohn Harrison 585*456b32c9SJohn Harrison if (remote_gt->info.id == gt->info.id) 586*456b32c9SJohn Harrison continue; 587*456b32c9SJohn Harrison 588*456b32c9SJohn Harrison tile = gt_to_tile(remote_gt)->id; 589*456b32c9SJohn Harrison dev = G2G_DEV(remote_gt); 590*456b32c9SJohn Harrison 591*456b32c9SJohn Harrison for (t = 0; t < XE_G2G_TYPE_LIMIT; t++) { 592*456b32c9SJohn Harrison ret = g2g_register_flat(guc, tile, dev, t, have_dev); 593*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, 0, ret, "G2G register failed: %pe", ERR_PTR(ret)); 594*456b32c9SJohn Harrison } 595*456b32c9SJohn Harrison } 596*456b32c9SJohn Harrison } 597*456b32c9SJohn Harrison 598*456b32c9SJohn Harrison static void g2g_reinit(struct kunit *test, struct xe_device *xe, int ctb_type, struct xe_tile *tile) 599*456b32c9SJohn Harrison { 600*456b32c9SJohn Harrison struct xe_gt *gt; 601*456b32c9SJohn Harrison int i, found = 0; 602*456b32c9SJohn Harrison 603*456b32c9SJohn Harrison g2g_stop(test, xe); 604*456b32c9SJohn Harrison 605*456b32c9SJohn Harrison for_each_gt(gt, xe, i) { 606*456b32c9SJohn Harrison struct xe_guc *guc = >->uc.guc; 607*456b32c9SJohn Harrison 608*456b32c9SJohn Harrison KUNIT_ASSERT_NULL(test, guc->g2g.bo); 609*456b32c9SJohn Harrison } 610*456b32c9SJohn Harrison 611*456b32c9SJohn Harrison switch (ctb_type) { 612*456b32c9SJohn Harrison case G2G_CTB_TYPE_DEFAULT: 613*456b32c9SJohn Harrison g2g_alloc_default(test, xe); 614*456b32c9SJohn Harrison break; 615*456b32c9SJohn Harrison 616*456b32c9SJohn Harrison case G2G_CTB_TYPE_HOST: 617*456b32c9SJohn Harrison g2g_alloc_host(test, xe); 618*456b32c9SJohn Harrison break; 619*456b32c9SJohn Harrison 620*456b32c9SJohn Harrison case G2G_CTB_TYPE_TILE: 621*456b32c9SJohn Harrison g2g_alloc_tile(test, xe, tile); 622*456b32c9SJohn Harrison break; 623*456b32c9SJohn Harrison 624*456b32c9SJohn Harrison default: 625*456b32c9SJohn Harrison KUNIT_ASSERT_TRUE(test, false); 626*456b32c9SJohn Harrison } 627*456b32c9SJohn Harrison 628*456b32c9SJohn Harrison for_each_gt(gt, xe, i) { 629*456b32c9SJohn Harrison struct xe_guc *guc = >->uc.guc; 630*456b32c9SJohn Harrison 631*456b32c9SJohn Harrison if (!guc->g2g.bo) 632*456b32c9SJohn Harrison continue; 633*456b32c9SJohn Harrison 634*456b32c9SJohn Harrison if (ctb_type == G2G_CTB_TYPE_DEFAULT) 635*456b32c9SJohn Harrison guc_g2g_start(guc); 636*456b32c9SJohn Harrison else 637*456b32c9SJohn Harrison g2g_start(test, guc); 638*456b32c9SJohn Harrison found++; 639*456b32c9SJohn Harrison } 640*456b32c9SJohn Harrison 641*456b32c9SJohn Harrison KUNIT_ASSERT_GT_MSG(test, found, 1, "insufficient G2G channels running: %d", found); 642*456b32c9SJohn Harrison 643*456b32c9SJohn Harrison kunit_info(test, "Testing across %d GTs\n", found); 644*456b32c9SJohn Harrison } 645*456b32c9SJohn Harrison 646*456b32c9SJohn Harrison static void g2g_recreate_ctb(void *_xe) 647*456b32c9SJohn Harrison { 648*456b32c9SJohn Harrison struct xe_device *xe = (struct xe_device *)_xe; 649*456b32c9SJohn Harrison struct kunit *test = kunit_get_current_test(); 650*456b32c9SJohn Harrison 651*456b32c9SJohn Harrison g2g_stop(test, xe); 652*456b32c9SJohn Harrison 653*456b32c9SJohn Harrison if (xe_guc_g2g_wanted(xe)) 654*456b32c9SJohn Harrison g2g_reinit(test, xe, G2G_CTB_TYPE_DEFAULT, NULL); 655*456b32c9SJohn Harrison } 656*456b32c9SJohn Harrison 657*456b32c9SJohn Harrison static void g2g_pm_runtime_put(void *_xe) 658*456b32c9SJohn Harrison { 659*456b32c9SJohn Harrison struct xe_device *xe = (struct xe_device *)_xe; 660*456b32c9SJohn Harrison 661*456b32c9SJohn Harrison xe_pm_runtime_put(xe); 662*456b32c9SJohn Harrison } 663*456b32c9SJohn Harrison 664*456b32c9SJohn Harrison static void g2g_pm_runtime_get(struct kunit *test) 665*456b32c9SJohn Harrison { 666*456b32c9SJohn Harrison struct xe_device *xe = test->priv; 667*456b32c9SJohn Harrison int ret; 668*456b32c9SJohn Harrison 669*456b32c9SJohn Harrison xe_pm_runtime_get(xe); 670*456b32c9SJohn Harrison ret = kunit_add_action_or_reset(test, g2g_pm_runtime_put, xe); 671*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, 0, ret, "Failed to register runtime PM action\n"); 672*456b32c9SJohn Harrison } 673*456b32c9SJohn Harrison 674*456b32c9SJohn Harrison static void g2g_check_skip(struct kunit *test) 675*456b32c9SJohn Harrison { 676*456b32c9SJohn Harrison struct xe_device *xe = test->priv; 677*456b32c9SJohn Harrison struct xe_gt *gt; 678*456b32c9SJohn Harrison int i; 679*456b32c9SJohn Harrison 680*456b32c9SJohn Harrison if (IS_SRIOV_VF(xe)) 681*456b32c9SJohn Harrison kunit_skip(test, "not supported from a VF"); 682*456b32c9SJohn Harrison 683*456b32c9SJohn Harrison if (xe->info.gt_count <= 1) 684*456b32c9SJohn Harrison kunit_skip(test, "not enough GTs"); 685*456b32c9SJohn Harrison 686*456b32c9SJohn Harrison for_each_gt(gt, xe, i) { 687*456b32c9SJohn Harrison struct xe_guc *guc = >->uc.guc; 688*456b32c9SJohn Harrison 689*456b32c9SJohn Harrison if (guc->fw.build_type == CSS_UKERNEL_INFO_BUILDTYPE_PROD) 690*456b32c9SJohn Harrison kunit_skip(test, 691*456b32c9SJohn Harrison "G2G test interface not available in production firmware builds\n"); 692*456b32c9SJohn Harrison } 693*456b32c9SJohn Harrison } 694*456b32c9SJohn Harrison 695*456b32c9SJohn Harrison /* 696*456b32c9SJohn Harrison * Simple test that does not try to recreate the CTBs. 697*456b32c9SJohn Harrison * Requires that the platform already enables G2G comms 698*456b32c9SJohn Harrison * but has no risk of leaving the system in a broken state 699*456b32c9SJohn Harrison * afterwards. 700*456b32c9SJohn Harrison */ 701*456b32c9SJohn Harrison static void xe_live_guc_g2g_kunit_default(struct kunit *test) 702*456b32c9SJohn Harrison { 703*456b32c9SJohn Harrison struct xe_device *xe = test->priv; 704*456b32c9SJohn Harrison 705*456b32c9SJohn Harrison if (!xe_guc_g2g_wanted(xe)) 706*456b32c9SJohn Harrison kunit_skip(test, "G2G not enabled"); 707*456b32c9SJohn Harrison 708*456b32c9SJohn Harrison g2g_check_skip(test); 709*456b32c9SJohn Harrison 710*456b32c9SJohn Harrison g2g_pm_runtime_get(test); 711*456b32c9SJohn Harrison 712*456b32c9SJohn Harrison kunit_info(test, "Testing default CTBs\n"); 713*456b32c9SJohn Harrison g2g_run_test(test, xe); 714*456b32c9SJohn Harrison 715*456b32c9SJohn Harrison kunit_release_action(test, &g2g_pm_runtime_put, xe); 716*456b32c9SJohn Harrison } 717*456b32c9SJohn Harrison 718*456b32c9SJohn Harrison /* 719*456b32c9SJohn Harrison * More complex test that re-creates the CTBs in various location to 720*456b32c9SJohn Harrison * test access to each location from each GuC. Can be run even on 721*456b32c9SJohn Harrison * systems that do not enable G2G by default. On the other hand, 722*456b32c9SJohn Harrison * because it recreates the CTBs, if something goes wrong it could 723*456b32c9SJohn Harrison * leave the system with broken G2G comms. 724*456b32c9SJohn Harrison */ 725*456b32c9SJohn Harrison static void xe_live_guc_g2g_kunit_allmem(struct kunit *test) 726*456b32c9SJohn Harrison { 727*456b32c9SJohn Harrison struct xe_device *xe = test->priv; 728*456b32c9SJohn Harrison int ret; 729*456b32c9SJohn Harrison 730*456b32c9SJohn Harrison g2g_check_skip(test); 731*456b32c9SJohn Harrison 732*456b32c9SJohn Harrison g2g_pm_runtime_get(test); 733*456b32c9SJohn Harrison 734*456b32c9SJohn Harrison /* Make sure to leave the system as we found it */ 735*456b32c9SJohn Harrison ret = kunit_add_action_or_reset(test, g2g_recreate_ctb, xe); 736*456b32c9SJohn Harrison KUNIT_ASSERT_EQ_MSG(test, 0, ret, "Failed to register CTB re-creation action\n"); 737*456b32c9SJohn Harrison 738*456b32c9SJohn Harrison kunit_info(test, "Testing CTB type 'default'...\n"); 739*456b32c9SJohn Harrison g2g_reinit(test, xe, G2G_CTB_TYPE_DEFAULT, NULL); 740*456b32c9SJohn Harrison g2g_run_test(test, xe); 741*456b32c9SJohn Harrison 742*456b32c9SJohn Harrison kunit_info(test, "Testing CTB type 'host'...\n"); 743*456b32c9SJohn Harrison g2g_reinit(test, xe, G2G_CTB_TYPE_HOST, NULL); 744*456b32c9SJohn Harrison g2g_run_test(test, xe); 745*456b32c9SJohn Harrison 746*456b32c9SJohn Harrison if (IS_DGFX(xe)) { 747*456b32c9SJohn Harrison struct xe_tile *tile; 748*456b32c9SJohn Harrison int id; 749*456b32c9SJohn Harrison 750*456b32c9SJohn Harrison for_each_tile(tile, xe, id) { 751*456b32c9SJohn Harrison kunit_info(test, "Testing CTB type 'tile: #%d'...\n", id); 752*456b32c9SJohn Harrison 753*456b32c9SJohn Harrison g2g_reinit(test, xe, G2G_CTB_TYPE_TILE, tile); 754*456b32c9SJohn Harrison g2g_run_test(test, xe); 755*456b32c9SJohn Harrison } 756*456b32c9SJohn Harrison } else { 757*456b32c9SJohn Harrison kunit_info(test, "Skipping local memory on integrated platform\n"); 758*456b32c9SJohn Harrison } 759*456b32c9SJohn Harrison 760*456b32c9SJohn Harrison kunit_release_action(test, g2g_recreate_ctb, xe); 761*456b32c9SJohn Harrison kunit_release_action(test, g2g_pm_runtime_put, xe); 762*456b32c9SJohn Harrison } 763*456b32c9SJohn Harrison 764*456b32c9SJohn Harrison static struct kunit_case xe_guc_g2g_tests[] = { 765*456b32c9SJohn Harrison KUNIT_CASE_PARAM(xe_live_guc_g2g_kunit_default, xe_pci_live_device_gen_param), 766*456b32c9SJohn Harrison KUNIT_CASE_PARAM(xe_live_guc_g2g_kunit_allmem, xe_pci_live_device_gen_param), 767*456b32c9SJohn Harrison {} 768*456b32c9SJohn Harrison }; 769*456b32c9SJohn Harrison 770*456b32c9SJohn Harrison VISIBLE_IF_KUNIT 771*456b32c9SJohn Harrison struct kunit_suite xe_guc_g2g_test_suite = { 772*456b32c9SJohn Harrison .name = "xe_guc_g2g", 773*456b32c9SJohn Harrison .test_cases = xe_guc_g2g_tests, 774*456b32c9SJohn Harrison .init = xe_kunit_helper_xe_device_live_test_init, 775*456b32c9SJohn Harrison }; 776*456b32c9SJohn Harrison EXPORT_SYMBOL_IF_KUNIT(xe_guc_g2g_test_suite); 777