Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/i915/dram: Fix ICL DIMM_S decoding

Unfortunately the MAD_DIMM DIMM_S and DIMM_L bits on ICL are
not idential, so we are currently decoding DIMM_S incorrectly.

Fix the problem by defining the DIMM_S and DIMM_L bits separately.
And for consistency do that same for SKL, even though there the
bits do match between the two DIMMs. The result is rather
repetitive in places, but I didn't feel like obfuscatign things
with cpp macros/etc.

Broken decoding on Dell XPS 13 7390 2-in-1:
CH0 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no
CH0 DIMM S size: 32 Gb, width: X32, ranks: 3, 16Gb+ DIMMs: no
CH0 ranks: 2, 16Gb+ DIMMs: no
CH1 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no
CH1 DIMM S size: 32 Gb, width: X32, ranks: 3, 16Gb+ DIMMs: no
CH1 ranks: 2, 16Gb+ DIMMs: no
Memory configuration is symmetric? no

Fixed decoding on Dell XPS 13 7390 2-in-1:
CH0 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no
CH0 DIMM S size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no
CH0 ranks: 2, 16Gb+ DIMMs: no
CH1 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no
CH1 DIMM S size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no
CH1 ranks: 2, 16Gb+ DIMMs: no
Memory configuration is symmetric? yes

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patch.msgid.link/20251029204215.12292-4-ville.syrjala@linux.intel.com
Reviewed-by: Jani Nikula <jani.nikula@intel.com>

+155 -64
+34 -19
drivers/gpu/drm/i915/intel_mchbar_regs.h
··· 160 160 161 161 #define SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C) 162 162 #define SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5010) 163 - #define SKL_DRAM_S_SHIFT 16 164 - #define SKL_DRAM_RANK_MASK REG_GENMASK(10, 10) 165 - #define SKL_DRAM_RANK_1 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 0) 166 - #define SKL_DRAM_RANK_2 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 1) 167 - #define SKL_DRAM_WIDTH_MASK REG_GENMASK(9, 8) 168 - #define SKL_DRAM_WIDTH_X8 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 0) 169 - #define SKL_DRAM_WIDTH_X16 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 1) 170 - #define SKL_DRAM_WIDTH_X32 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 2) 171 - #define SKL_DRAM_SIZE_MASK REG_GENMASK(5, 0) 172 - #define ICL_DRAM_RANK_MASK REG_GENMASK(10, 9) 173 - #define ICL_DRAM_RANK_1 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 0) 174 - #define ICL_DRAM_RANK_2 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 1) 175 - #define ICL_DRAM_RANK_3 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 2) 176 - #define ICL_DRAM_RANK_4 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 3) 177 - #define ICL_DRAM_WIDTH_MASK REG_GENMASK(8, 7) 178 - #define ICL_DRAM_WIDTH_X8 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 0) 179 - #define ICL_DRAM_WIDTH_X16 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 1) 180 - #define ICL_DRAM_WIDTH_X32 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 2) 181 - #define ICL_DRAM_SIZE_MASK REG_GENMASK(6, 0) 163 + #define SKL_DIMM_S_RANK_MASK REG_GENMASK(26, 26) 164 + #define SKL_DIMM_S_RANK_1 REG_FIELD_PREP(SKL_DIMM_S_RANK_MASK, 0) 165 + #define SKL_DIMM_S_RANK_2 REG_FIELD_PREP(SKL_DIMM_S_RANK_MASK, 1) 166 + #define SKL_DIMM_S_WIDTH_MASK REG_GENMASK(25, 24) 167 + #define SKL_DIMM_S_WIDTH_X8 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 0) 168 + #define SKL_DIMM_S_WIDTH_X16 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 1) 169 + #define SKL_DIMM_S_WIDTH_X32 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 2) 170 + #define SKL_DIMM_S_SIZE_MASK REG_GENMASK(21, 16) 171 + #define SKL_DIMM_L_RANK_MASK REG_GENMASK(10, 10) 172 + #define SKL_DIMM_L_RANK_1 REG_FIELD_PREP(SKL_DIMM_L_RANK_MASK, 0) 173 + #define SKL_DIMM_L_RANK_2 REG_FIELD_PREP(SKL_DIMM_L_RANK_MASK, 1) 174 + #define SKL_DIMM_L_WIDTH_MASK REG_GENMASK(9, 8) 175 + #define SKL_DIMM_L_WIDTH_X8 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 0) 176 + #define SKL_DIMM_L_WIDTH_X16 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 1) 177 + #define SKL_DIMM_L_WIDTH_X32 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 2) 178 + #define SKL_DIMM_L_SIZE_MASK REG_GENMASK(5, 0) 179 + #define ICL_DIMM_S_RANK_MASK REG_GENMASK(27, 26) 180 + #define ICL_DIMM_S_RANK_1 REG_FIELD_PREP(ICL_DIMM_S_RANK_MASK, 0) 181 + #define ICL_DIMM_S_RANK_2 REG_FIELD_PREP(ICL_DIMM_S_RANK_MASK, 1) 182 + #define ICL_DIMM_S_WIDTH_MASK REG_GENMASK(25, 24) 183 + #define ICL_DIMM_S_WIDTH_X8 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 0) 184 + #define ICL_DIMM_S_WIDTH_X16 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 1) 185 + #define ICL_DIMM_S_WIDTH_X32 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 2) 186 + #define ICL_DIMM_S_SIZE_MASK REG_GENMASK(22, 16) 187 + #define ICL_DIMM_L_RANK_MASK REG_GENMASK(10, 9) 188 + #define ICL_DIMM_L_RANK_1 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 0) 189 + #define ICL_DIMM_L_RANK_2 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 1) 190 + #define ICL_DIMM_L_RANK_3 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 2) 191 + #define ICL_DIMM_L_RANK_4 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 3) 192 + #define ICL_DIMM_L_WIDTH_MASK REG_GENMASK(8, 7) 193 + #define ICL_DIMM_L_WIDTH_X8 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 0) 194 + #define ICL_DIMM_L_WIDTH_X16 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 1) 195 + #define ICL_DIMM_L_WIDTH_X32 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 2) 196 + #define ICL_DIMM_L_SIZE_MASK REG_GENMASK(6, 0) 182 197 183 198 #define SA_PERF_STATUS_0_0_0_MCHBAR_PC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5918) 184 199 #define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2)
+121 -45
drivers/gpu/drm/i915/soc/intel_dram.c
··· 267 267 } 268 268 269 269 /* Returns total Gb for the whole DIMM */ 270 - static int skl_get_dimm_size(u16 val) 270 + static int skl_get_dimm_s_size(u32 val) 271 271 { 272 - return REG_FIELD_GET(SKL_DRAM_SIZE_MASK, val) * 8; 272 + return REG_FIELD_GET(SKL_DIMM_S_SIZE_MASK, val) * 8; 273 273 } 274 274 275 - static int skl_get_dimm_width(u16 val) 275 + static int skl_get_dimm_l_size(u32 val) 276 276 { 277 - if (skl_get_dimm_size(val) == 0) 277 + return REG_FIELD_GET(SKL_DIMM_L_SIZE_MASK, val) * 8; 278 + } 279 + 280 + static int skl_get_dimm_s_width(u32 val) 281 + { 282 + if (skl_get_dimm_s_size(val) == 0) 278 283 return 0; 279 284 280 - switch (val & SKL_DRAM_WIDTH_MASK) { 281 - case SKL_DRAM_WIDTH_X8: 282 - case SKL_DRAM_WIDTH_X16: 283 - case SKL_DRAM_WIDTH_X32: 284 - val = REG_FIELD_GET(SKL_DRAM_WIDTH_MASK, val); 285 - return 8 << val; 285 + switch (val & SKL_DIMM_S_WIDTH_MASK) { 286 + case SKL_DIMM_S_WIDTH_X8: 287 + case SKL_DIMM_S_WIDTH_X16: 288 + case SKL_DIMM_S_WIDTH_X32: 289 + return 8 << REG_FIELD_GET(SKL_DIMM_S_WIDTH_MASK, val); 286 290 default: 287 291 MISSING_CASE(val); 288 292 return 0; 289 293 } 290 294 } 291 295 292 - static int skl_get_dimm_ranks(u16 val) 296 + static int skl_get_dimm_l_width(u32 val) 293 297 { 294 - if (skl_get_dimm_size(val) == 0) 298 + if (skl_get_dimm_l_size(val) == 0) 295 299 return 0; 296 300 297 - val = REG_FIELD_GET(SKL_DRAM_RANK_MASK, val); 301 + switch (val & SKL_DIMM_L_WIDTH_MASK) { 302 + case SKL_DIMM_L_WIDTH_X8: 303 + case SKL_DIMM_L_WIDTH_X16: 304 + case SKL_DIMM_L_WIDTH_X32: 305 + return 8 << REG_FIELD_GET(SKL_DIMM_L_WIDTH_MASK, val); 306 + default: 307 + MISSING_CASE(val); 308 + return 0; 309 + } 310 + } 298 311 299 - return val + 1; 312 + static int skl_get_dimm_s_ranks(u32 val) 313 + { 314 + if (skl_get_dimm_s_size(val) == 0) 315 + return 0; 316 + 317 + return REG_FIELD_GET(SKL_DIMM_S_RANK_MASK, val) + 1; 318 + } 319 + 320 + static int skl_get_dimm_l_ranks(u32 val) 321 + { 322 + if (skl_get_dimm_l_size(val) == 0) 323 + return 0; 324 + 325 + return REG_FIELD_GET(SKL_DIMM_L_RANK_MASK, val) + 1; 300 326 } 301 327 302 328 /* Returns total Gb for the whole DIMM */ 303 - static int icl_get_dimm_size(u16 val) 329 + static int icl_get_dimm_s_size(u32 val) 304 330 { 305 - return REG_FIELD_GET(ICL_DRAM_SIZE_MASK, val) * 8 / 2; 331 + return REG_FIELD_GET(ICL_DIMM_S_SIZE_MASK, val) * 8 / 2; 306 332 } 307 333 308 - static int icl_get_dimm_width(u16 val) 334 + static int icl_get_dimm_l_size(u32 val) 309 335 { 310 - if (icl_get_dimm_size(val) == 0) 336 + return REG_FIELD_GET(ICL_DIMM_L_SIZE_MASK, val) * 8 / 2; 337 + } 338 + 339 + static int icl_get_dimm_s_width(u32 val) 340 + { 341 + if (icl_get_dimm_s_size(val) == 0) 311 342 return 0; 312 343 313 - switch (val & ICL_DRAM_WIDTH_MASK) { 314 - case ICL_DRAM_WIDTH_X8: 315 - case ICL_DRAM_WIDTH_X16: 316 - case ICL_DRAM_WIDTH_X32: 317 - val = REG_FIELD_GET(ICL_DRAM_WIDTH_MASK, val); 318 - return 8 << val; 344 + switch (val & ICL_DIMM_S_WIDTH_MASK) { 345 + case ICL_DIMM_S_WIDTH_X8: 346 + case ICL_DIMM_S_WIDTH_X16: 347 + case ICL_DIMM_S_WIDTH_X32: 348 + return 8 << REG_FIELD_GET(ICL_DIMM_S_WIDTH_MASK, val); 319 349 default: 320 350 MISSING_CASE(val); 321 351 return 0; 322 352 } 323 353 } 324 354 325 - static int icl_get_dimm_ranks(u16 val) 355 + static int icl_get_dimm_l_width(u32 val) 326 356 { 327 - if (icl_get_dimm_size(val) == 0) 357 + if (icl_get_dimm_l_size(val) == 0) 328 358 return 0; 329 359 330 - val = REG_FIELD_GET(ICL_DRAM_RANK_MASK, val); 360 + switch (val & ICL_DIMM_L_WIDTH_MASK) { 361 + case ICL_DIMM_L_WIDTH_X8: 362 + case ICL_DIMM_L_WIDTH_X16: 363 + case ICL_DIMM_L_WIDTH_X32: 364 + return 8 << REG_FIELD_GET(ICL_DIMM_L_WIDTH_MASK, val); 365 + default: 366 + MISSING_CASE(val); 367 + return 0; 368 + } 369 + } 331 370 332 - return val + 1; 371 + static int icl_get_dimm_s_ranks(u32 val) 372 + { 373 + if (icl_get_dimm_s_size(val) == 0) 374 + return 0; 375 + 376 + return REG_FIELD_GET(ICL_DIMM_S_RANK_MASK, val) + 1; 377 + } 378 + 379 + static int icl_get_dimm_l_ranks(u32 val) 380 + { 381 + if (icl_get_dimm_l_size(val) == 0) 382 + return 0; 383 + 384 + return REG_FIELD_GET(ICL_DIMM_L_RANK_MASK, val) + 1; 333 385 } 334 386 335 387 static bool ··· 392 340 } 393 341 394 342 static void 395 - skl_dram_get_dimm_info(struct drm_i915_private *i915, 396 - struct dram_dimm_info *dimm, 397 - int channel, char dimm_name, u16 val) 343 + skl_dram_print_dimm_info(struct drm_i915_private *i915, 344 + struct dram_dimm_info *dimm, 345 + int channel, char dimm_name) 398 346 { 399 - if (GRAPHICS_VER(i915) >= 11) { 400 - dimm->size = icl_get_dimm_size(val); 401 - dimm->width = icl_get_dimm_width(val); 402 - dimm->ranks = icl_get_dimm_ranks(val); 403 - } else { 404 - dimm->size = skl_get_dimm_size(val); 405 - dimm->width = skl_get_dimm_width(val); 406 - dimm->ranks = skl_get_dimm_ranks(val); 407 - } 408 - 409 347 drm_dbg_kms(&i915->drm, 410 348 "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n", 411 349 channel, dimm_name, dimm->size, dimm->width, dimm->ranks, 412 350 str_yes_no(skl_is_16gb_dimm(dimm))); 351 + } 352 + 353 + static void 354 + skl_dram_get_dimm_l_info(struct drm_i915_private *i915, 355 + struct dram_dimm_info *dimm, 356 + int channel, u32 val) 357 + { 358 + if (GRAPHICS_VER(i915) >= 11) { 359 + dimm->size = icl_get_dimm_l_size(val); 360 + dimm->width = icl_get_dimm_l_width(val); 361 + dimm->ranks = icl_get_dimm_l_ranks(val); 362 + } else { 363 + dimm->size = skl_get_dimm_l_size(val); 364 + dimm->width = skl_get_dimm_l_width(val); 365 + dimm->ranks = skl_get_dimm_l_ranks(val); 366 + } 367 + 368 + skl_dram_print_dimm_info(i915, dimm, channel, 'L'); 369 + } 370 + 371 + static void 372 + skl_dram_get_dimm_s_info(struct drm_i915_private *i915, 373 + struct dram_dimm_info *dimm, 374 + int channel, u32 val) 375 + { 376 + if (GRAPHICS_VER(i915) >= 11) { 377 + dimm->size = icl_get_dimm_s_size(val); 378 + dimm->width = icl_get_dimm_s_width(val); 379 + dimm->ranks = icl_get_dimm_s_ranks(val); 380 + } else { 381 + dimm->size = skl_get_dimm_s_size(val); 382 + dimm->width = skl_get_dimm_s_width(val); 383 + dimm->ranks = skl_get_dimm_s_ranks(val); 384 + } 385 + 386 + skl_dram_print_dimm_info(i915, dimm, channel, 'S'); 413 387 } 414 388 415 389 static int ··· 443 365 struct dram_channel_info *ch, 444 366 int channel, u32 val) 445 367 { 446 - skl_dram_get_dimm_info(i915, &ch->dimm_l, 447 - channel, 'L', val & 0xffff); 448 - skl_dram_get_dimm_info(i915, &ch->dimm_s, 449 - channel, 'S', val >> 16); 368 + skl_dram_get_dimm_l_info(i915, &ch->dimm_l, channel, val); 369 + skl_dram_get_dimm_s_info(i915, &ch->dimm_s, channel, val); 450 370 451 371 if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) { 452 372 drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel);