]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/amdgpu/umc_v6_1.c
Merge tag 'mtd/fixes-for-5.7-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / drivers / gpu / drm / amd / amdgpu / umc_v6_1.c
1 /*
2  * Copyright 2019 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 #include "umc_v6_1.h"
24 #include "amdgpu_ras.h"
25 #include "amdgpu.h"
26
27 #include "rsmu/rsmu_0_0_2_offset.h"
28 #include "rsmu/rsmu_0_0_2_sh_mask.h"
29 #include "umc/umc_6_1_1_offset.h"
30 #include "umc/umc_6_1_1_sh_mask.h"
31 #include "umc/umc_6_1_2_offset.h"
32
33 #define UMC_6_INST_DIST                 0x40000
34
35 /*
36  * (addr / 256) * 8192, the higher 26 bits in ErrorAddr
37  * is the index of 8KB block
38  */
39 #define ADDR_OF_8KB_BLOCK(addr)                 (((addr) & ~0xffULL) << 5)
40 /* channel index is the index of 256B block */
41 #define ADDR_OF_256B_BLOCK(channel_index)       ((channel_index) << 8)
42 /* offset in 256B block */
43 #define OFFSET_IN_256B_BLOCK(addr)              ((addr) & 0xffULL)
44
45 #define LOOP_UMC_INST(umc_inst) for ((umc_inst) = 0; (umc_inst) < adev->umc.umc_inst_num; (umc_inst)++)
46 #define LOOP_UMC_CH_INST(ch_inst) for ((ch_inst) = 0; (ch_inst) < adev->umc.channel_inst_num; (ch_inst)++)
47 #define LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) LOOP_UMC_INST((umc_inst)) LOOP_UMC_CH_INST((ch_inst))
48
49 const uint32_t
50         umc_v6_1_channel_idx_tbl[UMC_V6_1_UMC_INSTANCE_NUM][UMC_V6_1_CHANNEL_INSTANCE_NUM] = {
51                 {2, 18, 11, 27},        {4, 20, 13, 29},
52                 {1, 17, 8, 24},         {7, 23, 14, 30},
53                 {10, 26, 3, 19},        {12, 28, 5, 21},
54                 {9, 25, 0, 16},         {15, 31, 6, 22}
55 };
56
57 static void umc_v6_1_enable_umc_index_mode(struct amdgpu_device *adev)
58 {
59         WREG32_FIELD15(RSMU, 0, RSMU_UMC_INDEX_REGISTER_NBIF_VG20_GPU,
60                         RSMU_UMC_INDEX_MODE_EN, 1);
61 }
62
63 static void umc_v6_1_disable_umc_index_mode(struct amdgpu_device *adev)
64 {
65         WREG32_FIELD15(RSMU, 0, RSMU_UMC_INDEX_REGISTER_NBIF_VG20_GPU,
66                         RSMU_UMC_INDEX_MODE_EN, 0);
67 }
68
69 static uint32_t umc_v6_1_get_umc_index_mode_state(struct amdgpu_device *adev)
70 {
71         uint32_t rsmu_umc_index;
72
73         rsmu_umc_index = RREG32_SOC15(RSMU, 0,
74                         mmRSMU_UMC_INDEX_REGISTER_NBIF_VG20_GPU);
75
76         return REG_GET_FIELD(rsmu_umc_index,
77                         RSMU_UMC_INDEX_REGISTER_NBIF_VG20_GPU,
78                         RSMU_UMC_INDEX_MODE_EN);
79 }
80
81 static inline uint32_t get_umc_6_reg_offset(struct amdgpu_device *adev,
82                                             uint32_t umc_inst,
83                                             uint32_t ch_inst)
84 {
85         return adev->umc.channel_offs*ch_inst + UMC_6_INST_DIST*umc_inst;
86 }
87
88 static void umc_v6_1_query_correctable_error_count(struct amdgpu_device *adev,
89                                                    uint32_t umc_reg_offset,
90                                                    unsigned long *error_count)
91 {
92         uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
93         uint32_t ecc_err_cnt, ecc_err_cnt_addr;
94         uint64_t mc_umc_status;
95         uint32_t mc_umc_status_addr;
96
97         if (adev->asic_type == CHIP_ARCTURUS) {
98                 /* UMC 6_1_2 registers */
99                 ecc_err_cnt_sel_addr =
100                         SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel_ARCT);
101                 ecc_err_cnt_addr =
102                         SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt_ARCT);
103                 mc_umc_status_addr =
104                         SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0_ARCT);
105         } else {
106                 /* UMC 6_1_1 registers */
107                 ecc_err_cnt_sel_addr =
108                         SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel);
109                 ecc_err_cnt_addr =
110                         SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt);
111                 mc_umc_status_addr =
112                         SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
113         }
114
115         /* select the lower chip and check the error count */
116         ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4);
117         ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_EccErrCntSel,
118                                         EccErrCntCsSel, 0);
119         WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
120         ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4);
121         *error_count +=
122                 (REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_EccErrCnt, EccErrCnt) -
123                  UMC_V6_1_CE_CNT_INIT);
124         /* clear the lower chip err count */
125         WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, UMC_V6_1_CE_CNT_INIT);
126
127         /* select the higher chip and check the err counter */
128         ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_EccErrCntSel,
129                                         EccErrCntCsSel, 1);
130         WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
131         ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4);
132         *error_count +=
133                 (REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_EccErrCnt, EccErrCnt) -
134                  UMC_V6_1_CE_CNT_INIT);
135         /* clear the higher chip err count */
136         WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, UMC_V6_1_CE_CNT_INIT);
137
138         /* check for SRAM correctable error
139           MCUMC_STATUS is a 64 bit register */
140         mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
141         if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, ErrorCodeExt) == 6 &&
142             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
143             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)
144                 *error_count += 1;
145 }
146
147 static void umc_v6_1_querry_uncorrectable_error_count(struct amdgpu_device *adev,
148                                                       uint32_t umc_reg_offset,
149                                                       unsigned long *error_count)
150 {
151         uint64_t mc_umc_status;
152         uint32_t mc_umc_status_addr;
153
154         if (adev->asic_type == CHIP_ARCTURUS) {
155                 /* UMC 6_1_2 registers */
156                 mc_umc_status_addr =
157                         SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0_ARCT);
158         } else {
159                 /* UMC 6_1_1 registers */
160                 mc_umc_status_addr =
161                         SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
162         }
163
164         /* check the MCUMC_STATUS */
165         mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
166         if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
167             (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
168             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
169             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
170             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
171             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1))
172                 *error_count += 1;
173 }
174
175 static void umc_v6_1_query_ras_error_count(struct amdgpu_device *adev,
176                                            void *ras_error_status)
177 {
178         struct ras_err_data* err_data = (struct ras_err_data*)ras_error_status;
179
180         uint32_t umc_inst        = 0;
181         uint32_t ch_inst         = 0;
182         uint32_t umc_reg_offset  = 0;
183
184         uint32_t rsmu_umc_index_state = umc_v6_1_get_umc_index_mode_state(adev);
185
186         if (rsmu_umc_index_state)
187                 umc_v6_1_disable_umc_index_mode(adev);
188
189         if ((adev->asic_type == CHIP_ARCTURUS) &&
190                 amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW))
191                 DRM_WARN("Fail to disable DF-Cstate.\n");
192
193         LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
194                 umc_reg_offset = get_umc_6_reg_offset(adev,
195                                                       umc_inst,
196                                                       ch_inst);
197
198                 umc_v6_1_query_correctable_error_count(adev,
199                                                        umc_reg_offset,
200                                                        &(err_data->ce_count));
201                 umc_v6_1_querry_uncorrectable_error_count(adev,
202                                                           umc_reg_offset,
203                                                           &(err_data->ue_count));
204         }
205
206         if ((adev->asic_type == CHIP_ARCTURUS) &&
207                 amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_ALLOW))
208                 DRM_WARN("Fail to enable DF-Cstate\n");
209
210         if (rsmu_umc_index_state)
211                 umc_v6_1_enable_umc_index_mode(adev);
212 }
213
214 static void umc_v6_1_query_error_address(struct amdgpu_device *adev,
215                                          struct ras_err_data *err_data,
216                                          uint32_t umc_reg_offset,
217                                          uint32_t ch_inst,
218                                          uint32_t umc_inst)
219 {
220         uint32_t lsb, mc_umc_status_addr;
221         uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0;
222         struct eeprom_table_record *err_rec;
223         uint32_t channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
224
225         if (adev->asic_type == CHIP_ARCTURUS) {
226                 /* UMC 6_1_2 registers */
227                 mc_umc_status_addr =
228                         SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0_ARCT);
229                 mc_umc_addrt0 =
230                         SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_ADDRT0_ARCT);
231         } else {
232                 /* UMC 6_1_1 registers */
233                 mc_umc_status_addr =
234                         SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
235                 mc_umc_addrt0 =
236                         SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_ADDRT0);
237         }
238
239         mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
240
241         if (mc_umc_status == 0)
242                 return;
243
244         if (!err_data->err_addr) {
245                 /* clear umc status */
246                 WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
247                 return;
248         }
249
250         err_rec = &err_data->err_addr[err_data->err_addr_cnt];
251
252         /* calculate error address if ue/ce error is detected */
253         if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
254             (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
255             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
256
257                 err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
258                 /* the lowest lsb bits should be ignored */
259                 lsb = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, LSB);
260                 err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
261                 err_addr &= ~((0x1ULL << lsb) - 1);
262
263                 /* translate umc channel address to soc pa, 3 parts are included */
264                 retired_page = ADDR_OF_8KB_BLOCK(err_addr) |
265                                 ADDR_OF_256B_BLOCK(channel_index) |
266                                 OFFSET_IN_256B_BLOCK(err_addr);
267
268                 /* we only save ue error information currently, ce is skipped */
269                 if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
270                                 == 1) {
271                         err_rec->address = err_addr;
272                         /* page frame address is saved */
273                         err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT;
274                         err_rec->ts = (uint64_t)ktime_get_real_seconds();
275                         err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
276                         err_rec->cu = 0;
277                         err_rec->mem_channel = channel_index;
278                         err_rec->mcumc_id = umc_inst;
279
280                         err_data->err_addr_cnt++;
281                 }
282         }
283
284         /* clear umc status */
285         WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
286 }
287
288 static void umc_v6_1_query_ras_error_address(struct amdgpu_device *adev,
289                                              void *ras_error_status)
290 {
291         struct ras_err_data* err_data = (struct ras_err_data*)ras_error_status;
292
293         uint32_t umc_inst        = 0;
294         uint32_t ch_inst         = 0;
295         uint32_t umc_reg_offset  = 0;
296
297         uint32_t rsmu_umc_index_state = umc_v6_1_get_umc_index_mode_state(adev);
298
299         if (rsmu_umc_index_state)
300                 umc_v6_1_disable_umc_index_mode(adev);
301
302         if ((adev->asic_type == CHIP_ARCTURUS) &&
303                 amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW))
304                 DRM_WARN("Fail to disable DF-Cstate.\n");
305
306         LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
307                 umc_reg_offset = get_umc_6_reg_offset(adev,
308                                                       umc_inst,
309                                                       ch_inst);
310
311                 umc_v6_1_query_error_address(adev,
312                                              err_data,
313                                              umc_reg_offset,
314                                              ch_inst,
315                                              umc_inst);
316         }
317
318         if ((adev->asic_type == CHIP_ARCTURUS) &&
319                 amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_ALLOW))
320                 DRM_WARN("Fail to enable DF-Cstate\n");
321
322         if (rsmu_umc_index_state)
323                 umc_v6_1_enable_umc_index_mode(adev);
324 }
325
326 static void umc_v6_1_err_cnt_init_per_channel(struct amdgpu_device *adev,
327                                               uint32_t umc_reg_offset)
328 {
329         uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
330         uint32_t ecc_err_cnt_addr;
331
332         if (adev->asic_type == CHIP_ARCTURUS) {
333                 /* UMC 6_1_2 registers */
334                 ecc_err_cnt_sel_addr =
335                         SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel_ARCT);
336                 ecc_err_cnt_addr =
337                         SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt_ARCT);
338         } else {
339                 /* UMC 6_1_1 registers */
340                 ecc_err_cnt_sel_addr =
341                         SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel);
342                 ecc_err_cnt_addr =
343                         SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt);
344         }
345
346         /* select the lower chip and check the error count */
347         ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4);
348         ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_EccErrCntSel,
349                                         EccErrCntCsSel, 0);
350         /* set ce error interrupt type to APIC based interrupt */
351         ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_EccErrCntSel,
352                                         EccErrInt, 0x1);
353         WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
354         /* set error count to initial value */
355         WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, UMC_V6_1_CE_CNT_INIT);
356
357         /* select the higher chip and check the err counter */
358         ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_EccErrCntSel,
359                                         EccErrCntCsSel, 1);
360         WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
361         WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, UMC_V6_1_CE_CNT_INIT);
362 }
363
364 static void umc_v6_1_err_cnt_init(struct amdgpu_device *adev)
365 {
366         uint32_t umc_inst        = 0;
367         uint32_t ch_inst         = 0;
368         uint32_t umc_reg_offset  = 0;
369
370         uint32_t rsmu_umc_index_state = umc_v6_1_get_umc_index_mode_state(adev);
371
372         if (rsmu_umc_index_state)
373                 umc_v6_1_disable_umc_index_mode(adev);
374
375         LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
376                 umc_reg_offset = get_umc_6_reg_offset(adev,
377                                                       umc_inst,
378                                                       ch_inst);
379
380                 umc_v6_1_err_cnt_init_per_channel(adev, umc_reg_offset);
381         }
382
383         if (rsmu_umc_index_state)
384                 umc_v6_1_enable_umc_index_mode(adev);
385 }
386
387 const struct amdgpu_umc_funcs umc_v6_1_funcs = {
388         .err_cnt_init = umc_v6_1_err_cnt_init,
389         .ras_late_init = amdgpu_umc_ras_late_init,
390         .query_ras_error_count = umc_v6_1_query_ras_error_count,
391         .query_ras_error_address = umc_v6_1_query_ras_error_address,
392 };
This page took 0.055456 seconds and 4 git commands to generate.