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