| 1 | // SPDX-License-Identifier: GPL-2.0 AND MIT |
| 2 | /* |
| 3 | * Copyright © 2022 Intel Corporation |
| 4 | */ |
| 5 | |
| 6 | #include <kunit/test.h> |
| 7 | #include <kunit/visibility.h> |
| 8 | |
| 9 | #include "tests/xe_kunit_helpers.h" |
| 10 | #include "tests/xe_pci_test.h" |
| 11 | #include "tests/xe_test.h" |
| 12 | |
| 13 | #include "xe_device.h" |
| 14 | #include "xe_gt.h" |
| 15 | #include "xe_mocs.h" |
| 16 | #include "xe_pci.h" |
| 17 | #include "xe_pm.h" |
| 18 | |
| 19 | struct live_mocs { |
| 20 | struct xe_mocs_info table; |
| 21 | }; |
| 22 | |
| 23 | static int live_mocs_init(struct live_mocs *arg, struct xe_gt *gt) |
| 24 | { |
| 25 | unsigned int flags; |
| 26 | struct kunit *test = kunit_get_current_test(); |
| 27 | |
| 28 | memset(arg, 0, sizeof(*arg)); |
| 29 | |
| 30 | flags = get_mocs_settings(gt_to_xe(gt), &arg->table); |
| 31 | |
| 32 | kunit_info(test, "gt %d" , gt->info.id); |
| 33 | kunit_info(test, "gt type %d" , gt->info.type); |
| 34 | kunit_info(test, "table size %d" , arg->table.table_size); |
| 35 | kunit_info(test, "table uc_index %d" , arg->table.uc_index); |
| 36 | kunit_info(test, "table num_mocs_regs %d" , arg->table.num_mocs_regs); |
| 37 | |
| 38 | return flags; |
| 39 | } |
| 40 | |
| 41 | static void read_l3cc_table(struct xe_gt *gt, |
| 42 | const struct xe_mocs_info *info) |
| 43 | { |
| 44 | struct kunit *test = kunit_get_current_test(); |
| 45 | u32 l3cc, l3cc_expected; |
| 46 | unsigned int fw_ref, i; |
| 47 | u32 reg_val; |
| 48 | |
| 49 | fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); |
| 50 | if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { |
| 51 | xe_force_wake_put(gt_to_fw(gt), fw_ref); |
| 52 | KUNIT_FAIL_AND_ABORT(test, "Forcewake Failed.\n" ); |
| 53 | } |
| 54 | |
| 55 | for (i = 0; i < info->num_mocs_regs; i++) { |
| 56 | if (!(i & 1)) { |
| 57 | if (regs_are_mcr(gt)) |
| 58 | reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i >> 1)); |
| 59 | else |
| 60 | reg_val = xe_mmio_read32(>->mmio, XELP_LNCFCMOCS(i >> 1)); |
| 61 | |
| 62 | mocs_dbg(gt, "reg_val=0x%x\n" , reg_val); |
| 63 | } else { |
| 64 | /* Just reuse value read on previous iteration */ |
| 65 | reg_val >>= 16; |
| 66 | } |
| 67 | |
| 68 | l3cc_expected = get_entry_l3cc(info, i); |
| 69 | l3cc = reg_val & 0xffff; |
| 70 | |
| 71 | mocs_dbg(gt, "[%u] expected=0x%x actual=0x%x\n" , |
| 72 | i, l3cc_expected, l3cc); |
| 73 | |
| 74 | KUNIT_EXPECT_EQ_MSG(test, l3cc_expected, l3cc, |
| 75 | "l3cc idx=%u has incorrect val.\n" , i); |
| 76 | } |
| 77 | xe_force_wake_put(gt_to_fw(gt), fw_ref); |
| 78 | } |
| 79 | |
| 80 | static void read_mocs_table(struct xe_gt *gt, |
| 81 | const struct xe_mocs_info *info) |
| 82 | { |
| 83 | struct kunit *test = kunit_get_current_test(); |
| 84 | u32 mocs, mocs_expected; |
| 85 | unsigned int fw_ref, i; |
| 86 | u32 reg_val; |
| 87 | |
| 88 | KUNIT_EXPECT_TRUE_MSG(test, info->unused_entries_index, |
| 89 | "Unused entries index should have been defined\n" ); |
| 90 | |
| 91 | fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); |
| 92 | KUNIT_ASSERT_NE_MSG(test, fw_ref, 0, "Forcewake Failed.\n" ); |
| 93 | |
| 94 | for (i = 0; i < info->num_mocs_regs; i++) { |
| 95 | if (regs_are_mcr(gt)) |
| 96 | reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i)); |
| 97 | else |
| 98 | reg_val = xe_mmio_read32(>->mmio, XELP_GLOBAL_MOCS(i)); |
| 99 | |
| 100 | mocs_expected = get_entry_control(info, i); |
| 101 | mocs = reg_val; |
| 102 | |
| 103 | mocs_dbg(gt, "[%u] expected=0x%x actual=0x%x\n" , |
| 104 | i, mocs_expected, mocs); |
| 105 | |
| 106 | KUNIT_EXPECT_EQ_MSG(test, mocs_expected, mocs, |
| 107 | "mocs reg 0x%x has incorrect val.\n" , i); |
| 108 | } |
| 109 | |
| 110 | xe_force_wake_put(gt_to_fw(gt), fw_ref); |
| 111 | } |
| 112 | |
| 113 | static int mocs_kernel_test_run_device(struct xe_device *xe) |
| 114 | { |
| 115 | /* Basic check the system is configured with the expected mocs table */ |
| 116 | |
| 117 | struct live_mocs mocs; |
| 118 | struct xe_gt *gt; |
| 119 | |
| 120 | unsigned int flags; |
| 121 | int id; |
| 122 | |
| 123 | xe_pm_runtime_get(xe); |
| 124 | |
| 125 | for_each_gt(gt, xe, id) { |
| 126 | flags = live_mocs_init(arg: &mocs, gt); |
| 127 | if (flags & HAS_GLOBAL_MOCS) |
| 128 | read_mocs_table(gt, info: &mocs.table); |
| 129 | if (flags & HAS_LNCF_MOCS) |
| 130 | read_l3cc_table(gt, info: &mocs.table); |
| 131 | } |
| 132 | |
| 133 | xe_pm_runtime_put(xe); |
| 134 | |
| 135 | return 0; |
| 136 | } |
| 137 | |
| 138 | static void xe_live_mocs_kernel_kunit(struct kunit *test) |
| 139 | { |
| 140 | struct xe_device *xe = test->priv; |
| 141 | |
| 142 | if (IS_SRIOV_VF(xe)) |
| 143 | kunit_skip(test, "this test is N/A for VF" ); |
| 144 | |
| 145 | mocs_kernel_test_run_device(xe); |
| 146 | } |
| 147 | |
| 148 | static int mocs_reset_test_run_device(struct xe_device *xe) |
| 149 | { |
| 150 | /* Check the mocs setup is retained over GT reset */ |
| 151 | |
| 152 | struct live_mocs mocs; |
| 153 | struct xe_gt *gt; |
| 154 | unsigned int flags; |
| 155 | int id; |
| 156 | struct kunit *test = kunit_get_current_test(); |
| 157 | |
| 158 | xe_pm_runtime_get(xe); |
| 159 | |
| 160 | for_each_gt(gt, xe, id) { |
| 161 | flags = live_mocs_init(arg: &mocs, gt); |
| 162 | kunit_info(test, "mocs_reset_test before reset\n" ); |
| 163 | if (flags & HAS_GLOBAL_MOCS) |
| 164 | read_mocs_table(gt, info: &mocs.table); |
| 165 | if (flags & HAS_LNCF_MOCS) |
| 166 | read_l3cc_table(gt, info: &mocs.table); |
| 167 | |
| 168 | xe_gt_reset(gt); |
| 169 | |
| 170 | kunit_info(test, "mocs_reset_test after reset\n" ); |
| 171 | if (flags & HAS_GLOBAL_MOCS) |
| 172 | read_mocs_table(gt, info: &mocs.table); |
| 173 | if (flags & HAS_LNCF_MOCS) |
| 174 | read_l3cc_table(gt, info: &mocs.table); |
| 175 | } |
| 176 | |
| 177 | xe_pm_runtime_put(xe); |
| 178 | |
| 179 | return 0; |
| 180 | } |
| 181 | |
| 182 | static void xe_live_mocs_reset_kunit(struct kunit *test) |
| 183 | { |
| 184 | struct xe_device *xe = test->priv; |
| 185 | |
| 186 | if (IS_SRIOV_VF(xe)) |
| 187 | kunit_skip(test, "this test is N/A for VF" ); |
| 188 | |
| 189 | mocs_reset_test_run_device(xe); |
| 190 | } |
| 191 | |
| 192 | static struct kunit_case xe_mocs_tests[] = { |
| 193 | KUNIT_CASE_PARAM(xe_live_mocs_kernel_kunit, xe_pci_live_device_gen_param), |
| 194 | KUNIT_CASE_PARAM(xe_live_mocs_reset_kunit, xe_pci_live_device_gen_param), |
| 195 | {} |
| 196 | }; |
| 197 | |
| 198 | VISIBLE_IF_KUNIT |
| 199 | struct kunit_suite xe_mocs_test_suite = { |
| 200 | .name = "xe_mocs" , |
| 201 | .test_cases = xe_mocs_tests, |
| 202 | .init = xe_kunit_helper_xe_device_live_test_init, |
| 203 | }; |
| 204 | EXPORT_SYMBOL_IF_KUNIT(xe_mocs_test_suite); |
| 205 | |