@@ -4186,6 +4186,110 @@ const struct attribute_group amdgpu_flash_attr_group = {
4186
4186
.is_visible = amdgpu_flash_attr_is_visible ,
4187
4187
};
4188
4188
4189
+ #if defined(CONFIG_DEBUG_FS )
4190
+ static int psp_read_spirom_debugfs_open (struct inode * inode , struct file * filp )
4191
+ {
4192
+ struct amdgpu_device * adev = filp -> f_inode -> i_private ;
4193
+ struct spirom_bo * bo_triplet ;
4194
+ int ret ;
4195
+
4196
+ /* serialize the open() file calling */
4197
+ if (!mutex_trylock (& adev -> psp .mutex ))
4198
+ return - EBUSY ;
4199
+
4200
+ /*
4201
+ * make sure only one userpace process is alive for dumping so that
4202
+ * only one memory buffer of AMD_VBIOS_FILE_MAX_SIZE * 2 is consumed.
4203
+ * let's say the case where one process try opening the file while
4204
+ * another one has proceeded to read or release. In this way, eliminate
4205
+ * the use of mutex for read() or release() callback as well.
4206
+ */
4207
+ if (adev -> psp .spirom_dump_trip ) {
4208
+ mutex_unlock (& adev -> psp .mutex );
4209
+ return - EBUSY ;
4210
+ }
4211
+
4212
+ bo_triplet = kzalloc (sizeof (struct spirom_bo ), GFP_KERNEL );
4213
+ if (!bo_triplet ) {
4214
+ mutex_unlock (& adev -> psp .mutex );
4215
+ return - ENOMEM ;
4216
+ }
4217
+
4218
+ ret = amdgpu_bo_create_kernel (adev , AMD_VBIOS_FILE_MAX_SIZE_B * 2 ,
4219
+ AMDGPU_GPU_PAGE_SIZE ,
4220
+ AMDGPU_GEM_DOMAIN_GTT ,
4221
+ & bo_triplet -> bo ,
4222
+ & bo_triplet -> mc_addr ,
4223
+ & bo_triplet -> cpu_addr );
4224
+ if (ret )
4225
+ goto rel_trip ;
4226
+
4227
+ ret = psp_dump_spirom (& adev -> psp , bo_triplet -> mc_addr );
4228
+ if (ret )
4229
+ goto rel_bo ;
4230
+
4231
+ adev -> psp .spirom_dump_trip = bo_triplet ;
4232
+ mutex_unlock (& adev -> psp .mutex );
4233
+ return 0 ;
4234
+ rel_bo :
4235
+ amdgpu_bo_free_kernel (& bo_triplet -> bo , & bo_triplet -> mc_addr ,
4236
+ & bo_triplet -> cpu_addr );
4237
+ rel_trip :
4238
+ kfree (bo_triplet );
4239
+ mutex_unlock (& adev -> psp .mutex );
4240
+ dev_err (adev -> dev , "Trying IFWI dump fails, err = %d\n" , ret );
4241
+ return ret ;
4242
+ }
4243
+
4244
+ static ssize_t psp_read_spirom_debugfs_read (struct file * filp , char __user * buf , size_t size ,
4245
+ loff_t * pos )
4246
+ {
4247
+ struct amdgpu_device * adev = filp -> f_inode -> i_private ;
4248
+ struct spirom_bo * bo_triplet = adev -> psp .spirom_dump_trip ;
4249
+
4250
+ if (!bo_triplet )
4251
+ return - EINVAL ;
4252
+
4253
+ return simple_read_from_buffer (buf ,
4254
+ size ,
4255
+ pos , bo_triplet -> cpu_addr ,
4256
+ AMD_VBIOS_FILE_MAX_SIZE_B * 2 );
4257
+ }
4258
+
4259
+ static int psp_read_spirom_debugfs_release (struct inode * inode , struct file * filp )
4260
+ {
4261
+ struct amdgpu_device * adev = filp -> f_inode -> i_private ;
4262
+ struct spirom_bo * bo_triplet = adev -> psp .spirom_dump_trip ;
4263
+
4264
+ if (bo_triplet ) {
4265
+ amdgpu_bo_free_kernel (& bo_triplet -> bo , & bo_triplet -> mc_addr ,
4266
+ & bo_triplet -> cpu_addr );
4267
+ kfree (bo_triplet );
4268
+ }
4269
+
4270
+ adev -> psp .spirom_dump_trip = NULL ;
4271
+ return 0 ;
4272
+ }
4273
+
4274
+ static const struct file_operations psp_dump_spirom_debugfs_ops = {
4275
+ .owner = THIS_MODULE ,
4276
+ .open = psp_read_spirom_debugfs_open ,
4277
+ .read = psp_read_spirom_debugfs_read ,
4278
+ .release = psp_read_spirom_debugfs_release ,
4279
+ .llseek = default_llseek ,
4280
+ };
4281
+ #endif
4282
+
4283
+ void amdgpu_psp_debugfs_init (struct amdgpu_device * adev )
4284
+ {
4285
+ #if defined(CONFIG_DEBUG_FS )
4286
+ struct drm_minor * minor = adev_to_drm (adev )-> primary ;
4287
+
4288
+ debugfs_create_file_size ("psp_spirom_dump" , 0444 , minor -> debugfs_root ,
4289
+ adev , & psp_dump_spirom_debugfs_ops , AMD_VBIOS_FILE_MAX_SIZE_B * 2 );
4290
+ #endif
4291
+ }
4292
+
4189
4293
const struct amd_ip_funcs psp_ip_funcs = {
4190
4294
.name = "psp" ,
4191
4295
.early_init = psp_early_init ,
0 commit comments