in pnd2_edac.c [511:607]
static int get_registers(void)
{
const int intlv[] = { 10, 11, 12, 12 };
if (RD_REG(&tolud, b_cr_tolud_pci) ||
RD_REG(&touud_lo, b_cr_touud_lo_pci) ||
RD_REG(&touud_hi, b_cr_touud_hi_pci) ||
RD_REG(&asym0, b_cr_asym_mem_region0_mchbar) ||
RD_REG(&asym1, b_cr_asym_mem_region1_mchbar) ||
RD_REG(&mot_base, b_cr_mot_out_base_mchbar) ||
RD_REG(&mot_mask, b_cr_mot_out_mask_mchbar) ||
RD_REG(&chash, b_cr_slice_channel_hash))
return -ENODEV;
if (ops->get_registers())
return -ENODEV;
if (ops->type == DNV) {
/* PMI channel idx (always 0) for asymmetric region */
asym0.slice0_asym_channel_select = 0;
asym1.slice1_asym_channel_select = 0;
/* PMI channel bitmap (always 1) for symmetric region */
chash.sym_slice0_channel_enabled = 0x1;
chash.sym_slice1_channel_enabled = 0x1;
}
if (asym0.slice0_asym_enable)
ops->mk_region("as0", &as0, &asym0);
if (asym1.slice1_asym_enable)
ops->mk_region("as1", &as1, &asym1);
if (asym_2way.asym_2way_interleave_enable) {
mk_region("as2way", &as2,
U64_LSHIFT(asym_2way.asym_2way_base, APL_ASYMSHIFT),
U64_LSHIFT(asym_2way.asym_2way_limit, APL_ASYMSHIFT) +
GENMASK_ULL(APL_ASYMSHIFT - 1, 0));
}
if (mot_base.imr_en) {
mk_region_mask("mot", &mot,
U64_LSHIFT(mot_base.mot_out_base, MOT_SHIFT),
U64_LSHIFT(mot_mask.mot_out_mask, MOT_SHIFT));
}
top_lm = U64_LSHIFT(tolud.tolud, 20);
top_hm = U64_LSHIFT(touud_hi.touud, 32) | U64_LSHIFT(touud_lo.touud, 20);
two_slices = !chash.slice_1_disabled &&
!chash.slice_0_mem_disabled &&
(chash.sym_slice0_channel_enabled != 0) &&
(chash.sym_slice1_channel_enabled != 0);
two_channels = !chash.ch_1_disabled &&
!chash.enable_pmi_dual_data_mode &&
((chash.sym_slice0_channel_enabled == 3) ||
(chash.sym_slice1_channel_enabled == 3));
sym_chan_mask = gen_sym_mask(&chash);
asym_chan_mask = gen_asym_mask(&chash, &asym0, &asym1, &asym_2way);
chan_mask = sym_chan_mask | asym_chan_mask;
if (two_slices && !two_channels) {
if (chash.hvm_mode)
slice_selector = 29;
else
slice_selector = intlv[chash.interleave_mode];
} else if (!two_slices && two_channels) {
if (chash.hvm_mode)
chan_selector = 29;
else
chan_selector = intlv[chash.interleave_mode];
} else if (two_slices && two_channels) {
if (chash.hvm_mode) {
slice_selector = 29;
chan_selector = 30;
} else {
slice_selector = intlv[chash.interleave_mode];
chan_selector = intlv[chash.interleave_mode] + 1;
}
}
if (two_slices) {
if (!chash.hvm_mode)
slice_hash_mask = chash.slice_hash_mask << SLICE_HASH_MASK_LSB;
if (!two_channels)
slice_hash_mask |= BIT_ULL(slice_selector);
}
if (two_channels) {
if (!chash.hvm_mode)
chan_hash_mask = chash.ch_hash_mask << CH_HASH_MASK_LSB;
if (!two_slices)
chan_hash_mask |= BIT_ULL(chan_selector);
}
return 0;
}