1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 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_pci_test.h" 19 #include "xe_reg_sr.h" 20 #include "xe_rtp.h" 21 22 #define REGULAR_REG1 XE_REG(1) 23 #define REGULAR_REG2 XE_REG(2) 24 #define REGULAR_REG3 XE_REG(3) 25 #define MCR_REG1 XE_REG_MCR(1) 26 #define MCR_REG2 XE_REG_MCR(2) 27 #define MCR_REG3 XE_REG_MCR(3) 28 #define MASKED_REG1 XE_REG(1, XE_REG_OPTION_MASKED) 29 30 #undef XE_REG_MCR 31 #define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1) 32 33 struct rtp_test_case { 34 const char *name; 35 struct xe_reg expected_reg; 36 u32 expected_set_bits; 37 u32 expected_clr_bits; 38 unsigned long expected_count; 39 unsigned int expected_sr_errors; 40 const struct xe_rtp_entry_sr *entries; 41 }; 42 43 static bool match_yes(const struct xe_gt *gt, const struct xe_hw_engine *hwe) 44 { 45 return true; 46 } 47 48 static bool match_no(const struct xe_gt *gt, const struct xe_hw_engine *hwe) 49 { 50 return false; 51 } 52 53 static const struct rtp_test_case cases[] = { 54 { 55 .name = "coalesce-same-reg", 56 .expected_reg = REGULAR_REG1, 57 .expected_set_bits = REG_BIT(0) | REG_BIT(1), 58 .expected_clr_bits = REG_BIT(0) | REG_BIT(1), 59 .expected_count = 1, 60 /* Different bits on the same register: create a single entry */ 61 .entries = (const struct xe_rtp_entry_sr[]) { 62 { XE_RTP_NAME("basic-1"), 63 XE_RTP_RULES(FUNC(match_yes)), 64 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 65 }, 66 { XE_RTP_NAME("basic-2"), 67 XE_RTP_RULES(FUNC(match_yes)), 68 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1))) 69 }, 70 {} 71 }, 72 }, 73 { 74 .name = "no-match-no-add", 75 .expected_reg = REGULAR_REG1, 76 .expected_set_bits = REG_BIT(0), 77 .expected_clr_bits = REG_BIT(0), 78 .expected_count = 1, 79 /* Don't coalesce second entry since rules don't match */ 80 .entries = (const struct xe_rtp_entry_sr[]) { 81 { XE_RTP_NAME("basic-1"), 82 XE_RTP_RULES(FUNC(match_yes)), 83 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 84 }, 85 { XE_RTP_NAME("basic-2"), 86 XE_RTP_RULES(FUNC(match_no)), 87 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1))) 88 }, 89 {} 90 }, 91 }, 92 { 93 .name = "no-match-no-add-multiple-rules", 94 .expected_reg = REGULAR_REG1, 95 .expected_set_bits = REG_BIT(0), 96 .expected_clr_bits = REG_BIT(0), 97 .expected_count = 1, 98 /* Don't coalesce second entry due to one of the rules */ 99 .entries = (const struct xe_rtp_entry_sr[]) { 100 { XE_RTP_NAME("basic-1"), 101 XE_RTP_RULES(FUNC(match_yes)), 102 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 103 }, 104 { XE_RTP_NAME("basic-2"), 105 XE_RTP_RULES(FUNC(match_yes), FUNC(match_no)), 106 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1))) 107 }, 108 {} 109 }, 110 }, 111 { 112 .name = "two-regs-two-entries", 113 .expected_reg = REGULAR_REG1, 114 .expected_set_bits = REG_BIT(0), 115 .expected_clr_bits = REG_BIT(0), 116 .expected_count = 2, 117 /* Same bits on different registers are not coalesced */ 118 .entries = (const struct xe_rtp_entry_sr[]) { 119 { XE_RTP_NAME("basic-1"), 120 XE_RTP_RULES(FUNC(match_yes)), 121 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 122 }, 123 { XE_RTP_NAME("basic-2"), 124 XE_RTP_RULES(FUNC(match_yes)), 125 XE_RTP_ACTIONS(SET(REGULAR_REG2, REG_BIT(0))) 126 }, 127 {} 128 }, 129 }, 130 { 131 .name = "clr-one-set-other", 132 .expected_reg = REGULAR_REG1, 133 .expected_set_bits = REG_BIT(0), 134 .expected_clr_bits = REG_BIT(1) | REG_BIT(0), 135 .expected_count = 1, 136 /* Check clr vs set actions on different bits */ 137 .entries = (const struct xe_rtp_entry_sr[]) { 138 { XE_RTP_NAME("basic-1"), 139 XE_RTP_RULES(FUNC(match_yes)), 140 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 141 }, 142 { XE_RTP_NAME("basic-2"), 143 XE_RTP_RULES(FUNC(match_yes)), 144 XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_BIT(1))) 145 }, 146 {} 147 }, 148 }, 149 { 150 #define TEMP_MASK REG_GENMASK(10, 8) 151 #define TEMP_FIELD REG_FIELD_PREP(TEMP_MASK, 2) 152 .name = "set-field", 153 .expected_reg = REGULAR_REG1, 154 .expected_set_bits = TEMP_FIELD, 155 .expected_clr_bits = TEMP_MASK, 156 .expected_count = 1, 157 /* Check FIELD_SET works */ 158 .entries = (const struct xe_rtp_entry_sr[]) { 159 { XE_RTP_NAME("basic-1"), 160 XE_RTP_RULES(FUNC(match_yes)), 161 XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1, 162 TEMP_MASK, TEMP_FIELD)) 163 }, 164 {} 165 }, 166 #undef TEMP_MASK 167 #undef TEMP_FIELD 168 }, 169 { 170 .name = "conflict-duplicate", 171 .expected_reg = REGULAR_REG1, 172 .expected_set_bits = REG_BIT(0), 173 .expected_clr_bits = REG_BIT(0), 174 .expected_count = 1, 175 .expected_sr_errors = 1, 176 .entries = (const struct xe_rtp_entry_sr[]) { 177 { XE_RTP_NAME("basic-1"), 178 XE_RTP_RULES(FUNC(match_yes)), 179 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 180 }, 181 /* drop: setting same values twice */ 182 { XE_RTP_NAME("basic-2"), 183 XE_RTP_RULES(FUNC(match_yes)), 184 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 185 }, 186 {} 187 }, 188 }, 189 { 190 .name = "conflict-not-disjoint", 191 .expected_reg = REGULAR_REG1, 192 .expected_set_bits = REG_BIT(0), 193 .expected_clr_bits = REG_BIT(0), 194 .expected_count = 1, 195 .expected_sr_errors = 1, 196 .entries = (const struct xe_rtp_entry_sr[]) { 197 { XE_RTP_NAME("basic-1"), 198 XE_RTP_RULES(FUNC(match_yes)), 199 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 200 }, 201 /* drop: bits are not disjoint with previous entries */ 202 { XE_RTP_NAME("basic-2"), 203 XE_RTP_RULES(FUNC(match_yes)), 204 XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_GENMASK(1, 0))) 205 }, 206 {} 207 }, 208 }, 209 { 210 .name = "conflict-reg-type", 211 .expected_reg = REGULAR_REG1, 212 .expected_set_bits = REG_BIT(0), 213 .expected_clr_bits = REG_BIT(0), 214 .expected_count = 1, 215 .expected_sr_errors = 2, 216 .entries = (const struct xe_rtp_entry_sr[]) { 217 { XE_RTP_NAME("basic-1"), 218 XE_RTP_RULES(FUNC(match_yes)), 219 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 220 }, 221 /* drop: regular vs MCR */ 222 { XE_RTP_NAME("basic-2"), 223 XE_RTP_RULES(FUNC(match_yes)), 224 XE_RTP_ACTIONS(SET(MCR_REG1, REG_BIT(1))) 225 }, 226 /* drop: regular vs masked */ 227 { XE_RTP_NAME("basic-3"), 228 XE_RTP_RULES(FUNC(match_yes)), 229 XE_RTP_ACTIONS(SET(MASKED_REG1, REG_BIT(0))) 230 }, 231 {} 232 }, 233 }, 234 }; 235 236 static void xe_rtp_process_tests(struct kunit *test) 237 { 238 const struct rtp_test_case *param = test->param_value; 239 struct xe_device *xe = test->priv; 240 struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt; 241 struct xe_reg_sr *reg_sr = >->reg_sr; 242 const struct xe_reg_sr_entry *sre, *sr_entry = NULL; 243 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt); 244 unsigned long idx, count = 0; 245 246 xe_reg_sr_init(reg_sr, "xe_rtp_tests", xe); 247 xe_rtp_process_to_sr(&ctx, param->entries, reg_sr); 248 249 xa_for_each(®_sr->xa, idx, sre) { 250 if (idx == param->expected_reg.addr) 251 sr_entry = sre; 252 253 count++; 254 } 255 256 KUNIT_EXPECT_EQ(test, count, param->expected_count); 257 KUNIT_EXPECT_EQ(test, sr_entry->clr_bits, param->expected_clr_bits); 258 KUNIT_EXPECT_EQ(test, sr_entry->set_bits, param->expected_set_bits); 259 KUNIT_EXPECT_EQ(test, sr_entry->reg.raw, param->expected_reg.raw); 260 KUNIT_EXPECT_EQ(test, reg_sr->errors, param->expected_sr_errors); 261 } 262 263 static void rtp_desc(const struct rtp_test_case *t, char *desc) 264 { 265 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); 266 } 267 268 KUNIT_ARRAY_PARAM(rtp, cases, rtp_desc); 269 270 static int xe_rtp_test_init(struct kunit *test) 271 { 272 struct xe_device *xe; 273 struct device *dev; 274 int ret; 275 276 dev = drm_kunit_helper_alloc_device(test); 277 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 278 279 xe = drm_kunit_helper_alloc_drm_device(test, dev, 280 struct xe_device, 281 drm, DRIVER_GEM); 282 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xe); 283 284 /* Initialize an empty device */ 285 test->priv = NULL; 286 ret = xe_pci_fake_device_init(xe); 287 KUNIT_ASSERT_EQ(test, ret, 0); 288 289 xe->drm.dev = dev; 290 test->priv = xe; 291 292 return 0; 293 } 294 295 static void xe_rtp_test_exit(struct kunit *test) 296 { 297 struct xe_device *xe = test->priv; 298 299 drm_kunit_helper_free_device(test, xe->drm.dev); 300 } 301 302 static struct kunit_case xe_rtp_tests[] = { 303 KUNIT_CASE_PARAM(xe_rtp_process_tests, rtp_gen_params), 304 {} 305 }; 306 307 static struct kunit_suite xe_rtp_test_suite = { 308 .name = "xe_rtp", 309 .init = xe_rtp_test_init, 310 .exit = xe_rtp_test_exit, 311 .test_cases = xe_rtp_tests, 312 }; 313 314 kunit_test_suite(xe_rtp_test_suite); 315 316 MODULE_AUTHOR("Intel Corporation"); 317 MODULE_LICENSE("GPL"); 318 MODULE_DESCRIPTION("xe_rtp kunit test"); 319 MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); 320