Commit 958394d8 authored by Yazen Ghannam's avatar Yazen Ghannam Committed by PvsNarasimha
Browse files

EDAC/amd64: Drop dbam_to_cs() for Family 17h and later

mainline inclusion
from mainline-v6.4-rc1
commit a2e59ab8
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAU6ZD

Reference: https://github.com/torvalds/linux/commit/a2e59ab8e93301466cb3ff3f2b7b65eb1a4e8786



--------------------------------

commit a2e59ab8 upstream

The same function is used to calculate chip select size for all Zen-based
family/models. Therefore, a family/model function pointer is not necessary.

Drop the dbam_to_cs() function pointer for Family 17h and later systems.
Also, move the Family 17h function to avoid a forward declaration. Rename
it to indicate that the UMC Address Mask is used rather than the legacy
DBAM value.

Signed-off-by: default avatarYazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230127170419.1824692-9-yazen.ghannam@amd.com


Signed-off-by: default avatarPvsNarasimha <PVS.NarasimhaRao@amd.com>
parent 1a4ae6d6
Loading
Loading
Loading
Loading
+81 −108
Original line number Diff line number Diff line
@@ -1152,6 +1152,84 @@ static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
	return cs_mode;
}

static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
				    unsigned int cs_mode, int csrow_nr)
{
	u32 addr_mask_orig, addr_mask_deinterleaved;
	u32 msb, weight, num_zero_bits;
	int cs_mask_nr = csrow_nr;
	int dimm, size = 0;

	/* No Chip Selects are enabled. */
	if (!cs_mode)
		return size;

	/* Requested size of an even CS but none are enabled. */
	if (!(cs_mode & CS_EVEN) && !(csrow_nr & 1))
		return size;

	/* Requested size of an odd CS but none are enabled. */
	if (!(cs_mode & CS_ODD) && (csrow_nr & 1))
		return size;

	/*
	 * Family 17h introduced systems with one mask per DIMM,
	 * and two Chip Selects per DIMM.
	 *
	 *	CS0 and CS1 -> MASK0 / DIMM0
	 *	CS2 and CS3 -> MASK1 / DIMM1
	 *
	 * Family 19h Model 10h introduced systems with one mask per Chip Select,
	 * and two Chip Selects per DIMM.
	 *
	 *	CS0 -> MASK0 -> DIMM0
	 *	CS1 -> MASK1 -> DIMM0
	 *	CS2 -> MASK2 -> DIMM1
	 *	CS3 -> MASK3 -> DIMM1
	 *
	 * Keep the mask number equal to the Chip Select number for newer systems,
	 * and shift the mask number for older systems.
	 */
	dimm = csrow_nr >> 1;

	if (!fam_type->flags.zn_regs_v2)
		cs_mask_nr >>= 1;

	/* Asymmetric dual-rank DIMM support. */
	if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
		addr_mask_orig = pvt->csels[umc].csmasks_sec[cs_mask_nr];
	else
		addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr];

	/*
	 * The number of zero bits in the mask is equal to the number of bits
	 * in a full mask minus the number of bits in the current mask.
	 *
	 * The MSB is the number of bits in the full mask because BIT[0] is
	 * always 0.
	 *
	 * In the special 3 Rank interleaving case, a single bit is flipped
	 * without swapping with the most significant bit. This can be handled
	 * by keeping the MSB where it is and ignoring the single zero bit.
	 */
	msb = fls(addr_mask_orig) - 1;
	weight = hweight_long(addr_mask_orig);
	num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);

	/* Take the number of zero bits off from the top of the mask. */
	addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);

	edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
	edac_dbg(1, "  Original AddrMask: 0x%x\n", addr_mask_orig);
	edac_dbg(1, "  Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);

	/* Register [31:1] = Address [39:9]. Size is in kBs here. */
	size = (addr_mask_deinterleaved >> 2) + 1;

	/* Return size in MBs. */
	return size >> 10;
}

static void umc_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
{
	int dimm, size0, size1, cs0, cs1, cs_mode;
@@ -1164,8 +1242,8 @@ static void umc_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)

		cs_mode = f17_get_cs_mode(dimm, ctrl, pvt);

		size0 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs0);
		size1 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs1);
		size0 = umc_addr_mask_to_cs_size(pvt, ctrl, cs_mode, cs0);
		size1 = umc_addr_mask_to_cs_size(pvt, ctrl, cs_mode, cs1);

		amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
				cs0,	size0,
@@ -1877,84 +1955,6 @@ static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
		return ddr3_cs_size(cs_mode, false);
}

static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
				    unsigned int cs_mode, int csrow_nr)
{
	u32 addr_mask_orig, addr_mask_deinterleaved;
	u32 msb, weight, num_zero_bits;
	int cs_mask_nr = csrow_nr;
	int dimm, size = 0;

	/* No Chip Selects are enabled. */
	if (!cs_mode)
		return size;

	/* Requested size of an even CS but none are enabled. */
	if (!(cs_mode & CS_EVEN) && !(csrow_nr & 1))
		return size;

	/* Requested size of an odd CS but none are enabled. */
	if (!(cs_mode & CS_ODD) && (csrow_nr & 1))
		return size;

	/*
	 * Family 17h introduced systems with one mask per DIMM,
	 * and two Chip Selects per DIMM.
	 *
	 *	CS0 and CS1 -> MASK0 / DIMM0
	 *	CS2 and CS3 -> MASK1 / DIMM1
	 *
	 * Family 19h Model 10h introduced systems with one mask per Chip Select,
	 * and two Chip Selects per DIMM.
	 *
	 *	CS0 -> MASK0 -> DIMM0
	 *	CS1 -> MASK1 -> DIMM0
	 *	CS2 -> MASK2 -> DIMM1
	 *	CS3 -> MASK3 -> DIMM1
	 *
	 * Keep the mask number equal to the Chip Select number for newer systems,
	 * and shift the mask number for older systems.
	 */
	dimm = csrow_nr >> 1;

	if (!fam_type->flags.zn_regs_v2)
		cs_mask_nr >>= 1;

	/* Asymmetric dual-rank DIMM support. */
	if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
		addr_mask_orig = pvt->csels[umc].csmasks_sec[cs_mask_nr];
	else
		addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr];

	/*
	 * The number of zero bits in the mask is equal to the number of bits
	 * in a full mask minus the number of bits in the current mask.
	 *
	 * The MSB is the number of bits in the full mask because BIT[0] is
	 * always 0.
	 *
	 * In the special 3 Rank interleaving case, a single bit is flipped
	 * without swapping with the most significant bit. This can be handled
	 * by keeping the MSB where it is and ignoring the single zero bit.
	 */
	msb = fls(addr_mask_orig) - 1;
	weight = hweight_long(addr_mask_orig);
	num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);

	/* Take the number of zero bits off from the top of the mask. */
	addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);

	edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
	edac_dbg(1, "  Original AddrMask: 0x%x\n", addr_mask_orig);
	edac_dbg(1, "  Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);

	/* Register [31:1] = Address [39:9]. Size is in kBs here. */
	size = (addr_mask_deinterleaved >> 2) + 1;

	/* Return size in MBs. */
	return size >> 10;
}

static void read_dram_ctl_register(struct amd64_pvt *pvt)
{

@@ -2551,66 +2551,39 @@ static struct amd64_family_type family_types[] = {
	[F17_CPUS] = {
		.ctl_name = "F17h",
		.max_mcs = 2,
		.ops = {
			.dbam_to_cs		= f17_addr_mask_to_cs_size,
		}
	},
	[F17_M10H_CPUS] = {
		.ctl_name = "F17h_M10h",
		.max_mcs = 2,
		.ops = {
			.dbam_to_cs		= f17_addr_mask_to_cs_size,
		}
	},
	[F17_M30H_CPUS] = {
		.ctl_name = "F17h_M30h",
		.max_mcs = 8,
		.ops = {
			.dbam_to_cs		= f17_addr_mask_to_cs_size,
		}
	},
	[F17_M60H_CPUS] = {
		.ctl_name = "F17h_M60h",
		.max_mcs = 2,
		.ops = {
			.dbam_to_cs		= f17_addr_mask_to_cs_size,
		}
	},
	[F17_M70H_CPUS] = {
		.ctl_name = "F17h_M70h",
		.max_mcs = 2,
		.ops = {
			.dbam_to_cs		= f17_addr_mask_to_cs_size,
		}
	},
	[F18_M06H_CPUS] = {
		.ctl_name = "F18h_M06h",
		.max_mcs = 2,
		.ops = {
			.dbam_to_cs		= f17_addr_mask_to_cs_size,
		}
	},
	[F18_M10H_CPUS] = {
		.ctl_name = "F18h_M10h",
		.max_mcs = 2,
		.ops = {
			.dbam_to_cs		= f17_addr_mask_to_cs_size,
		}
	},
	[F19_CPUS] = {
		.ctl_name = "F19h",
		.max_mcs = 8,
		.ops = {
			.dbam_to_cs		= f17_addr_mask_to_cs_size,
		}
	},
	[F19_M10H_CPUS] = {
		.ctl_name = "F19h_M10h",
		.max_mcs = 12,
		.flags.zn_regs_v2 = 1,
		.ops = {
			.dbam_to_cs		= f17_addr_mask_to_cs_size,
		}
	},
};

@@ -3184,7 +3157,7 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
		cs_mode = f17_get_cs_mode(csrow_nr >> 1, dct, pvt);
	}

	nr_pages   = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr);
	nr_pages   = umc_addr_mask_to_cs_size(pvt, dct, cs_mode, csrow_nr);
	nr_pages <<= 20 - PAGE_SHIFT;

	edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",