@@ -99,6 +99,49 @@ static bool amdgpu_ras_get_error_query_ready(struct amdgpu_device *adev)
99
99
return false;
100
100
}
101
101
102
+ static int amdgpu_reserve_page_direct (struct amdgpu_device * adev , uint64_t address )
103
+ {
104
+ struct ras_err_data err_data = {0 , 0 , 0 , NULL };
105
+ struct eeprom_table_record err_rec ;
106
+
107
+ if ((address >= adev -> gmc .mc_vram_size ) ||
108
+ (address >= RAS_UMC_INJECT_ADDR_LIMIT )) {
109
+ dev_warn (adev -> dev ,
110
+ "RAS WARN: input address 0x%llx is invalid.\n" ,
111
+ address );
112
+ return - EINVAL ;
113
+ }
114
+
115
+ if (amdgpu_ras_check_bad_page (adev , address )) {
116
+ dev_warn (adev -> dev ,
117
+ "RAS WARN: 0x%llx has been marked as bad page!\n" ,
118
+ address );
119
+ return 0 ;
120
+ }
121
+
122
+ memset (& err_rec , 0x0 , sizeof (struct eeprom_table_record ));
123
+
124
+ err_rec .address = address ;
125
+ err_rec .retired_page = address >> AMDGPU_GPU_PAGE_SHIFT ;
126
+ err_rec .ts = (uint64_t )ktime_get_real_seconds ();
127
+ err_rec .err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE ;
128
+
129
+ err_data .err_addr = & err_rec ;
130
+ err_data .err_addr_cnt = 1 ;
131
+
132
+ if (amdgpu_bad_page_threshold != 0 ) {
133
+ amdgpu_ras_add_bad_pages (adev , err_data .err_addr ,
134
+ err_data .err_addr_cnt );
135
+ amdgpu_ras_save_bad_pages (adev );
136
+ }
137
+
138
+ dev_warn (adev -> dev , "WARNING: THIS IS ONLY FOR TEST PURPOSES AND WILL CORRUPT RAS EEPROM\n" );
139
+ dev_warn (adev -> dev , "Clear EEPROM:\n" );
140
+ dev_warn (adev -> dev , " echo 1 > /sys/kernel/debug/dri/0/ras/ras_eeprom_reset\n" );
141
+
142
+ return 0 ;
143
+ }
144
+
102
145
static ssize_t amdgpu_ras_debugfs_read (struct file * f , char __user * buf ,
103
146
size_t size , loff_t * pos )
104
147
{
@@ -178,11 +221,25 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
178
221
op = 1 ;
179
222
else if (sscanf (str , "inject %32s %8s" , block_name , err ) == 2 )
180
223
op = 2 ;
224
+ else if (sscanf (str , "retire_page" ) == 0 )
225
+ op = 3 ;
181
226
else if (str [0 ] && str [1 ] && str [2 ] && str [3 ])
182
227
/* ascii string, but commands are not matched. */
183
228
return - EINVAL ;
184
229
185
230
if (op != -1 ) {
231
+
232
+ if (op == 3 ) {
233
+ if (sscanf (str , "%*s %llu" , & address ) != 1 )
234
+ if (sscanf (str , "%*s 0x%llx" , & address ) != 1 )
235
+ return - EINVAL ;
236
+
237
+ data -> op = op ;
238
+ data -> inject .address = address ;
239
+
240
+ return 0 ;
241
+ }
242
+
186
243
if (amdgpu_ras_find_block_id_by_name (block_name , & block_id ))
187
244
return - EINVAL ;
188
245
@@ -310,6 +367,16 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
310
367
if (ret )
311
368
return - EINVAL ;
312
369
370
+ if (data .op == 3 )
371
+ {
372
+ ret = amdgpu_reserve_page_direct (adev , data .inject .address );
373
+
374
+ if (ret )
375
+ return size ;
376
+ else
377
+ return ret ;
378
+ }
379
+
313
380
if (!amdgpu_ras_is_supported (adev , data .head .block ))
314
381
return - EINVAL ;
315
382
0 commit comments