Skip to content

Commit ba43790

Browse files
yghannambp3tk0v
authored andcommitted
RAS/AMD/ATL: Use system settings for MI300 DRAM to normalized address translation
The currently used normalized address format is not applicable to all MI300 systems. This leads to incorrect results during address translation. Drop the fixed layout and construct the normalized address from system settings. Fixes: 87a6123 ("RAS/AMD/ATL: Add MI300 DRAM to normalized address translation support") Signed-off-by: Yazen Ghannam <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Cc: <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent fe8a089 commit ba43790

File tree

3 files changed

+114
-41
lines changed

3 files changed

+114
-41
lines changed

drivers/ras/amd/atl/internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ int df_indirect_read_broadcast(u16 node, u8 func, u16 reg, u32 *lo);
224224

225225
int get_df_system_info(void);
226226
int determine_node_id(struct addr_ctx *ctx, u8 socket_num, u8 die_num);
227-
int get_addr_hash_mi300(void);
227+
int get_umc_info_mi300(void);
228228

229229
int get_address_map(struct addr_ctx *ctx);
230230

drivers/ras/amd/atl/system.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ static int df4_determine_df_rev(u32 reg)
127127
if (reg == DF_FUNC0_ID_MI300) {
128128
df_cfg.flags.heterogeneous = 1;
129129

130-
if (get_addr_hash_mi300())
130+
if (get_umc_info_mi300())
131131
return -EINVAL;
132132
}
133133

drivers/ras/amd/atl/umc.c

Lines changed: 112 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ struct xor_bits {
6868
};
6969

7070
#define NUM_BANK_BITS 4
71+
#define NUM_COL_BITS 5
72+
#define NUM_SID_BITS 2
7173

7274
static struct {
7375
/* UMC::CH::AddrHashBank */
@@ -80,7 +82,22 @@ static struct {
8082
u8 bank_xor;
8183
} addr_hash;
8284

85+
static struct {
86+
u8 bank[NUM_BANK_BITS];
87+
u8 col[NUM_COL_BITS];
88+
u8 sid[NUM_SID_BITS];
89+
u8 num_row_lo;
90+
u8 num_row_hi;
91+
u8 row_lo;
92+
u8 row_hi;
93+
u8 pc;
94+
} bit_shifts;
95+
8396
#define MI300_UMC_CH_BASE 0x90000
97+
#define MI300_ADDR_CFG (MI300_UMC_CH_BASE + 0x30)
98+
#define MI300_ADDR_SEL (MI300_UMC_CH_BASE + 0x40)
99+
#define MI300_COL_SEL_LO (MI300_UMC_CH_BASE + 0x50)
100+
#define MI300_ADDR_SEL_2 (MI300_UMC_CH_BASE + 0xA4)
84101
#define MI300_ADDR_HASH_BANK0 (MI300_UMC_CH_BASE + 0xC8)
85102
#define MI300_ADDR_HASH_PC (MI300_UMC_CH_BASE + 0xE0)
86103
#define MI300_ADDR_HASH_PC2 (MI300_UMC_CH_BASE + 0xE4)
@@ -90,17 +107,42 @@ static struct {
90107
#define ADDR_HASH_ROW_XOR GENMASK(31, 14)
91108
#define ADDR_HASH_BANK_XOR GENMASK(5, 0)
92109

110+
#define ADDR_CFG_NUM_ROW_LO GENMASK(11, 8)
111+
#define ADDR_CFG_NUM_ROW_HI GENMASK(15, 12)
112+
113+
#define ADDR_SEL_BANK0 GENMASK(3, 0)
114+
#define ADDR_SEL_BANK1 GENMASK(7, 4)
115+
#define ADDR_SEL_BANK2 GENMASK(11, 8)
116+
#define ADDR_SEL_BANK3 GENMASK(15, 12)
117+
#define ADDR_SEL_BANK4 GENMASK(20, 16)
118+
#define ADDR_SEL_ROW_LO GENMASK(27, 24)
119+
#define ADDR_SEL_ROW_HI GENMASK(31, 28)
120+
121+
#define COL_SEL_LO_COL0 GENMASK(3, 0)
122+
#define COL_SEL_LO_COL1 GENMASK(7, 4)
123+
#define COL_SEL_LO_COL2 GENMASK(11, 8)
124+
#define COL_SEL_LO_COL3 GENMASK(15, 12)
125+
#define COL_SEL_LO_COL4 GENMASK(19, 16)
126+
127+
#define ADDR_SEL_2_BANK5 GENMASK(4, 0)
128+
#define ADDR_SEL_2_CHAN GENMASK(15, 12)
129+
93130
/*
94131
* Read UMC::CH::AddrHash{Bank,PC,PC2} registers to get XOR bits used
95-
* for hashing. Do this during module init, since the values will not
96-
* change during run time.
132+
* for hashing.
133+
*
134+
* Also, read UMC::CH::Addr{Cfg,Sel,Sel2} and UMC::CH:ColSelLo registers to
135+
* get the values needed to reconstruct the normalized address. Apply additional
136+
* offsets to the raw register values, as needed.
137+
*
138+
* Do this during module init, since the values will not change during run time.
97139
*
98140
* These registers are instantiated for each UMC across each AMD Node.
99141
* However, they should be identically programmed due to the fixed hardware
100142
* design of MI300 systems. So read the values from Node 0 UMC 0 and keep a
101143
* single global structure for simplicity.
102144
*/
103-
int get_addr_hash_mi300(void)
145+
int get_umc_info_mi300(void)
104146
{
105147
u32 temp;
106148
int ret;
@@ -130,6 +172,44 @@ int get_addr_hash_mi300(void)
130172

131173
addr_hash.bank_xor = FIELD_GET(ADDR_HASH_BANK_XOR, temp);
132174

175+
ret = amd_smn_read(0, MI300_ADDR_CFG, &temp);
176+
if (ret)
177+
return ret;
178+
179+
bit_shifts.num_row_hi = FIELD_GET(ADDR_CFG_NUM_ROW_HI, temp);
180+
bit_shifts.num_row_lo = 10 + FIELD_GET(ADDR_CFG_NUM_ROW_LO, temp);
181+
182+
ret = amd_smn_read(0, MI300_ADDR_SEL, &temp);
183+
if (ret)
184+
return ret;
185+
186+
bit_shifts.bank[0] = 5 + FIELD_GET(ADDR_SEL_BANK0, temp);
187+
bit_shifts.bank[1] = 5 + FIELD_GET(ADDR_SEL_BANK1, temp);
188+
bit_shifts.bank[2] = 5 + FIELD_GET(ADDR_SEL_BANK2, temp);
189+
bit_shifts.bank[3] = 5 + FIELD_GET(ADDR_SEL_BANK3, temp);
190+
/* Use BankBit4 for the SID0 position. */
191+
bit_shifts.sid[0] = 5 + FIELD_GET(ADDR_SEL_BANK4, temp);
192+
bit_shifts.row_lo = 12 + FIELD_GET(ADDR_SEL_ROW_LO, temp);
193+
bit_shifts.row_hi = 24 + FIELD_GET(ADDR_SEL_ROW_HI, temp);
194+
195+
ret = amd_smn_read(0, MI300_COL_SEL_LO, &temp);
196+
if (ret)
197+
return ret;
198+
199+
bit_shifts.col[0] = 2 + FIELD_GET(COL_SEL_LO_COL0, temp);
200+
bit_shifts.col[1] = 2 + FIELD_GET(COL_SEL_LO_COL1, temp);
201+
bit_shifts.col[2] = 2 + FIELD_GET(COL_SEL_LO_COL2, temp);
202+
bit_shifts.col[3] = 2 + FIELD_GET(COL_SEL_LO_COL3, temp);
203+
bit_shifts.col[4] = 2 + FIELD_GET(COL_SEL_LO_COL4, temp);
204+
205+
ret = amd_smn_read(0, MI300_ADDR_SEL_2, &temp);
206+
if (ret)
207+
return ret;
208+
209+
/* Use BankBit5 for the SID1 position. */
210+
bit_shifts.sid[1] = 5 + FIELD_GET(ADDR_SEL_2_BANK5, temp);
211+
bit_shifts.pc = 5 + FIELD_GET(ADDR_SEL_2_CHAN, temp);
212+
133213
return 0;
134214
}
135215

@@ -146,9 +226,6 @@ int get_addr_hash_mi300(void)
146226
* The MCA address format is as follows:
147227
* MCA_ADDR[27:0] = {S[1:0], P[0], R[14:0], B[3:0], C[4:0], Z[0]}
148228
*
149-
* The normalized address format is fixed in hardware and is as follows:
150-
* NA[30:0] = {S[1:0], R[13:0], C4, B[1:0], B[3:2], C[3:2], P, C[1:0], Z[4:0]}
151-
*
152229
* Additionally, the PC and Bank bits may be hashed. This must be accounted for before
153230
* reconstructing the normalized address.
154231
*/
@@ -158,18 +235,10 @@ int get_addr_hash_mi300(void)
158235
#define MI300_UMC_MCA_PC BIT(25)
159236
#define MI300_UMC_MCA_SID GENMASK(27, 26)
160237

161-
#define MI300_NA_COL_1_0 GENMASK(6, 5)
162-
#define MI300_NA_PC BIT(7)
163-
#define MI300_NA_COL_3_2 GENMASK(9, 8)
164-
#define MI300_NA_BANK_3_2 GENMASK(11, 10)
165-
#define MI300_NA_BANK_1_0 GENMASK(13, 12)
166-
#define MI300_NA_COL_4 BIT(14)
167-
#define MI300_NA_ROW GENMASK(28, 15)
168-
#define MI300_NA_SID GENMASK(30, 29)
169-
170238
static unsigned long convert_dram_to_norm_addr_mi300(unsigned long addr)
171239
{
172-
u16 i, col, row, bank, pc, sid, temp;
240+
u16 i, col, row, bank, pc, sid;
241+
u32 temp;
173242

174243
col = FIELD_GET(MI300_UMC_MCA_COL, addr);
175244
bank = FIELD_GET(MI300_UMC_MCA_BANK, addr);
@@ -199,34 +268,38 @@ static unsigned long convert_dram_to_norm_addr_mi300(unsigned long addr)
199268
/* Reconstruct the normalized address starting with NA[4:0] = 0 */
200269
addr = 0;
201270

202-
/* NA[6:5] = Column[1:0] */
203-
temp = col & 0x3;
204-
addr |= FIELD_PREP(MI300_NA_COL_1_0, temp);
205-
206-
/* NA[7] = PC */
207-
addr |= FIELD_PREP(MI300_NA_PC, pc);
208-
209-
/* NA[9:8] = Column[3:2] */
210-
temp = (col >> 2) & 0x3;
211-
addr |= FIELD_PREP(MI300_NA_COL_3_2, temp);
271+
/* Column bits */
272+
for (i = 0; i < NUM_COL_BITS; i++) {
273+
temp = (col >> i) & 0x1;
274+
addr |= temp << bit_shifts.col[i];
275+
}
212276

213-
/* NA[11:10] = Bank[3:2] */
214-
temp = (bank >> 2) & 0x3;
215-
addr |= FIELD_PREP(MI300_NA_BANK_3_2, temp);
277+
/* Bank bits */
278+
for (i = 0; i < NUM_BANK_BITS; i++) {
279+
temp = (bank >> i) & 0x1;
280+
addr |= temp << bit_shifts.bank[i];
281+
}
216282

217-
/* NA[13:12] = Bank[1:0] */
218-
temp = bank & 0x3;
219-
addr |= FIELD_PREP(MI300_NA_BANK_1_0, temp);
283+
/* Row lo bits */
284+
for (i = 0; i < bit_shifts.num_row_lo; i++) {
285+
temp = (row >> i) & 0x1;
286+
addr |= temp << (i + bit_shifts.row_lo);
287+
}
220288

221-
/* NA[14] = Column[4] */
222-
temp = (col >> 4) & 0x1;
223-
addr |= FIELD_PREP(MI300_NA_COL_4, temp);
289+
/* Row hi bits */
290+
for (i = 0; i < bit_shifts.num_row_hi; i++) {
291+
temp = (row >> (i + bit_shifts.num_row_lo)) & 0x1;
292+
addr |= temp << (i + bit_shifts.row_hi);
293+
}
224294

225-
/* NA[28:15] = Row[13:0] */
226-
addr |= FIELD_PREP(MI300_NA_ROW, row);
295+
/* PC bit */
296+
addr |= pc << bit_shifts.pc;
227297

228-
/* NA[30:29] = SID[1:0] */
229-
addr |= FIELD_PREP(MI300_NA_SID, sid);
298+
/* SID bits */
299+
for (i = 0; i < NUM_SID_BITS; i++) {
300+
temp = (sid >> i) & 0x1;
301+
addr |= temp << bit_shifts.sid[i];
302+
}
230303

231304
pr_debug("Addr=0x%016lx", addr);
232305
pr_debug("Bank=%u Row=%u Column=%u PC=%u SID=%u", bank, row, col, pc, sid);

0 commit comments

Comments
 (0)