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 = "no-match-no-add-multiple-rules", 95 .expected_reg = REGULAR_REG1, 96 .expected_set_bits = REG_BIT(0), 97 .expected_clr_bits = REG_BIT(0), 98 .expected_count = 1, 99 /* Don't coalesce second entry due to one of the rules */ 100 .entries = (const struct xe_rtp_entry_sr[]) { 101 { XE_RTP_NAME("basic-1"), 102 XE_RTP_RULES(FUNC(match_yes)), 103 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 104 }, 105 { XE_RTP_NAME("basic-2"), 106 XE_RTP_RULES(FUNC(match_yes), FUNC(match_no)), 107 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1))) 108 }, 109 {} 110 }, 111 }, 112 { 113 .name = "two-regs-two-entries", 114 .expected_reg = REGULAR_REG1, 115 .expected_set_bits = REG_BIT(0), 116 .expected_clr_bits = REG_BIT(0), 117 .expected_count = 2, 118 /* Same bits on different registers are not coalesced */ 119 .entries = (const struct xe_rtp_entry_sr[]) { 120 { XE_RTP_NAME("basic-1"), 121 XE_RTP_RULES(FUNC(match_yes)), 122 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 123 }, 124 { XE_RTP_NAME("basic-2"), 125 XE_RTP_RULES(FUNC(match_yes)), 126 XE_RTP_ACTIONS(SET(REGULAR_REG2, REG_BIT(0))) 127 }, 128 {} 129 }, 130 }, 131 { 132 .name = "clr-one-set-other", 133 .expected_reg = REGULAR_REG1, 134 .expected_set_bits = REG_BIT(0), 135 .expected_clr_bits = REG_BIT(1) | REG_BIT(0), 136 .expected_count = 1, 137 /* Check clr vs set actions on different bits */ 138 .entries = (const struct xe_rtp_entry_sr[]) { 139 { XE_RTP_NAME("basic-1"), 140 XE_RTP_RULES(FUNC(match_yes)), 141 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 142 }, 143 { XE_RTP_NAME("basic-2"), 144 XE_RTP_RULES(FUNC(match_yes)), 145 XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_BIT(1))) 146 }, 147 {} 148 }, 149 }, 150 { 151 #define TEMP_MASK REG_GENMASK(10, 8) 152 #define TEMP_FIELD REG_FIELD_PREP(TEMP_MASK, 2) 153 .name = "set-field", 154 .expected_reg = REGULAR_REG1, 155 .expected_set_bits = TEMP_FIELD, 156 .expected_clr_bits = TEMP_MASK, 157 .expected_count = 1, 158 /* Check FIELD_SET works */ 159 .entries = (const struct xe_rtp_entry_sr[]) { 160 { XE_RTP_NAME("basic-1"), 161 XE_RTP_RULES(FUNC(match_yes)), 162 XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1, 163 TEMP_MASK, TEMP_FIELD)) 164 }, 165 {} 166 }, 167 #undef TEMP_MASK 168 #undef TEMP_FIELD 169 }, 170 { 171 .name = "conflict-duplicate", 172 .expected_reg = REGULAR_REG1, 173 .expected_set_bits = REG_BIT(0), 174 .expected_clr_bits = REG_BIT(0), 175 .expected_count = 1, 176 .expected_sr_errors = 1, 177 .entries = (const struct xe_rtp_entry_sr[]) { 178 { XE_RTP_NAME("basic-1"), 179 XE_RTP_RULES(FUNC(match_yes)), 180 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 181 }, 182 /* drop: setting same values twice */ 183 { XE_RTP_NAME("basic-2"), 184 XE_RTP_RULES(FUNC(match_yes)), 185 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 186 }, 187 {} 188 }, 189 }, 190 { 191 .name = "conflict-not-disjoint", 192 .expected_reg = REGULAR_REG1, 193 .expected_set_bits = REG_BIT(0), 194 .expected_clr_bits = REG_BIT(0), 195 .expected_count = 1, 196 .expected_sr_errors = 1, 197 .entries = (const struct xe_rtp_entry_sr[]) { 198 { XE_RTP_NAME("basic-1"), 199 XE_RTP_RULES(FUNC(match_yes)), 200 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 201 }, 202 /* drop: bits are not disjoint with previous entries */ 203 { XE_RTP_NAME("basic-2"), 204 XE_RTP_RULES(FUNC(match_yes)), 205 XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_GENMASK(1, 0))) 206 }, 207 {} 208 }, 209 }, 210 { 211 .name = "conflict-reg-type", 212 .expected_reg = REGULAR_REG1, 213 .expected_set_bits = REG_BIT(0), 214 .expected_clr_bits = REG_BIT(0), 215 .expected_count = 1, 216 .expected_sr_errors = 2, 217 .entries = (const struct xe_rtp_entry_sr[]) { 218 { XE_RTP_NAME("basic-1"), 219 XE_RTP_RULES(FUNC(match_yes)), 220 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 221 }, 222 /* drop: regular vs MCR */ 223 { XE_RTP_NAME("basic-2"), 224 XE_RTP_RULES(FUNC(match_yes)), 225 XE_RTP_ACTIONS(SET(MCR_REG1, REG_BIT(1))) 226 }, 227 /* drop: regular vs masked */ 228 { XE_RTP_NAME("basic-3"), 229 XE_RTP_RULES(FUNC(match_yes)), 230 XE_RTP_ACTIONS(SET(MASKED_REG1, REG_BIT(0))) 231 }, 232 {} 233 }, 234 }, 235 }; 236 237 static void xe_rtp_process_tests(struct kunit *test) 238 { 239 const struct rtp_test_case *param = test->param_value; 240 struct xe_device *xe = test->priv; 241 struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt; 242 struct xe_reg_sr *reg_sr = >->reg_sr; 243 const struct xe_reg_sr_entry *sre, *sr_entry = NULL; 244 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt); 245 unsigned long idx, count = 0; 246 247 xe_reg_sr_init(reg_sr, "xe_rtp_tests", xe); 248 xe_rtp_process_to_sr(&ctx, param->entries, reg_sr); 249 250 xa_for_each(®_sr->xa, idx, sre) { 251 if (idx == param->expected_reg.addr) 252 sr_entry = sre; 253 254 count++; 255 } 256 257 KUNIT_EXPECT_EQ(test, count, param->expected_count); 258 KUNIT_EXPECT_EQ(test, sr_entry->clr_bits, param->expected_clr_bits); 259 KUNIT_EXPECT_EQ(test, sr_entry->set_bits, param->expected_set_bits); 260 KUNIT_EXPECT_EQ(test, sr_entry->reg.raw, param->expected_reg.raw); 261 KUNIT_EXPECT_EQ(test, reg_sr->errors, param->expected_sr_errors); 262 } 263 264 static void rtp_desc(const struct rtp_test_case *t, char *desc) 265 { 266 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); 267 } 268 269 KUNIT_ARRAY_PARAM(rtp, cases, rtp_desc); 270 271 static int xe_rtp_test_init(struct kunit *test) 272 { 273 struct xe_device *xe; 274 struct device *dev; 275 int ret; 276 277 dev = drm_kunit_helper_alloc_device(test); 278 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 279 280 xe = xe_kunit_helper_alloc_xe_device(test, dev); 281 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xe); 282 283 /* Initialize an empty device */ 284 test->priv = NULL; 285 ret = xe_pci_fake_device_init(xe); 286 KUNIT_ASSERT_EQ(test, ret, 0); 287 288 xe->drm.dev = dev; 289 test->priv = xe; 290 291 return 0; 292 } 293 294 static void xe_rtp_test_exit(struct kunit *test) 295 { 296 struct xe_device *xe = test->priv; 297 298 drm_kunit_helper_free_device(test, xe->drm.dev); 299 } 300 301 static struct kunit_case xe_rtp_tests[] = { 302 KUNIT_CASE_PARAM(xe_rtp_process_tests, rtp_gen_params), 303 {} 304 }; 305 306 static struct kunit_suite xe_rtp_test_suite = { 307 .name = "xe_rtp", 308 .init = xe_rtp_test_init, 309 .exit = xe_rtp_test_exit, 310 .test_cases = xe_rtp_tests, 311 }; 312 313 kunit_test_suite(xe_rtp_test_suite); 314