@@ -33,6 +33,20 @@ static const guid_t tpm_ppi_guid =
3333 GUID_INIT (0x3DDDFAA6 , 0x361B , 0x4EB4 ,
3434 0xA4 , 0x24 , 0x8D , 0x10 , 0x08 , 0x9D , 0x16 , 0x53 );
3535
36+ static const char * const tpm_ppi_info [] = {
37+ "Not implemented" ,
38+ "BIOS only" ,
39+ "Blocked for OS by system firmware" ,
40+ "User required" ,
41+ "User not required" ,
42+ };
43+
44+ /* A spinlock to protect access to the cache from concurrent reads */
45+ static DEFINE_MUTEX (tpm_ppi_lock );
46+
47+ static u32 ppi_operations_cache [PPI_VS_REQ_END + 1 ];
48+ static bool ppi_cache_populated ;
49+
3650static bool tpm_ppi_req_has_parameter (u64 req )
3751{
3852 return req == 23 ;
@@ -279,66 +293,95 @@ static ssize_t tpm_show_ppi_response(struct device *dev,
279293 return status ;
280294}
281295
282- static ssize_t show_ppi_operations (acpi_handle dev_handle , char * buf , u32 start ,
283- u32 end )
296+ static ssize_t cache_ppi_operations (acpi_handle dev_handle , char * buf )
284297{
285298 int i ;
286299 u32 ret ;
287- char * str = buf ;
300+ int len = 0 ;
288301 union acpi_object * obj , tmp ;
289302 union acpi_object argv = ACPI_INIT_DSM_ARGV4 (1 , & tmp );
290303
291- static char * info [] = {
292- "Not implemented" ,
293- "BIOS only" ,
294- "Blocked for OS by BIOS" ,
295- "User required" ,
296- "User not required" ,
297- };
298-
299304 if (!acpi_check_dsm (dev_handle , & tpm_ppi_guid , TPM_PPI_REVISION_ID_1 ,
300305 1 << TPM_PPI_FN_GETOPR ))
301306 return - EPERM ;
302307
303308 tmp .integer .type = ACPI_TYPE_INTEGER ;
304- for (i = start ; i <= end ; i ++ ) {
309+ for (i = 0 ; i <= PPI_VS_REQ_END ; i ++ ) {
305310 tmp .integer .value = i ;
306311 obj = tpm_eval_dsm (dev_handle , TPM_PPI_FN_GETOPR ,
307312 ACPI_TYPE_INTEGER , & argv ,
308313 TPM_PPI_REVISION_ID_1 );
309- if (!obj ) {
314+ if (!obj )
310315 return - ENOMEM ;
311- } else {
312- ret = obj -> integer .value ;
313- ACPI_FREE (obj );
314- }
315316
316- if ( ret > 0 && ret < ARRAY_SIZE ( info ))
317- str += scnprintf ( str , PAGE_SIZE , "%d %d: %s\n" ,
318- i , ret , info [ ret ] );
317+ ret = obj -> integer . value ;
318+ ppi_operations_cache [ i ] = ret ;
319+ ACPI_FREE ( obj );
319320 }
320321
321- return str - buf ;
322+ return len ;
322323}
323324
324325static ssize_t tpm_show_ppi_tcg_operations (struct device * dev ,
325326 struct device_attribute * attr ,
326327 char * buf )
327328{
328329 struct tpm_chip * chip = to_tpm_chip (dev );
330+ ssize_t len = 0 ;
331+ u32 ret ;
332+ int i ;
333+
334+ mutex_lock (& tpm_ppi_lock );
335+ if (!ppi_cache_populated ) {
336+ len = cache_ppi_operations (chip -> acpi_dev_handle , buf );
337+ if (len < 0 ) {
338+ mutex_unlock (& tpm_ppi_lock );
339+ return len ;
340+ }
341+
342+ ppi_cache_populated = true;
343+ }
329344
330- return show_ppi_operations (chip -> acpi_dev_handle , buf , 0 ,
331- PPI_TPM_REQ_MAX );
345+ for (i = 0 ; i <= PPI_TPM_REQ_MAX ; i ++ ) {
346+ ret = ppi_operations_cache [i ];
347+ if (ret >= 0 && ret < ARRAY_SIZE (tpm_ppi_info ))
348+ len += sysfs_emit_at (buf , len , "%d %d: %s\n" ,
349+ i , ret , tpm_ppi_info [ret ]);
350+ }
351+ mutex_unlock (& tpm_ppi_lock );
352+
353+ return len ;
332354}
333355
334356static ssize_t tpm_show_ppi_vs_operations (struct device * dev ,
335357 struct device_attribute * attr ,
336358 char * buf )
337359{
338360 struct tpm_chip * chip = to_tpm_chip (dev );
361+ ssize_t len = 0 ;
362+ u32 ret ;
363+ int i ;
364+
365+ mutex_lock (& tpm_ppi_lock );
366+ if (!ppi_cache_populated ) {
367+ len = cache_ppi_operations (chip -> acpi_dev_handle , buf );
368+ if (len < 0 ) {
369+ mutex_unlock (& tpm_ppi_lock );
370+ return len ;
371+ }
372+
373+ ppi_cache_populated = true;
374+ }
375+
376+ for (i = PPI_VS_REQ_START ; i <= PPI_VS_REQ_END ; i ++ ) {
377+ ret = ppi_operations_cache [i ];
378+ if (ret >= 0 && ret < ARRAY_SIZE (tpm_ppi_info ))
379+ len += sysfs_emit_at (buf , len , "%d %d: %s\n" ,
380+ i , ret , tpm_ppi_info [ret ]);
381+ }
382+ mutex_unlock (& tpm_ppi_lock );
339383
340- return show_ppi_operations (chip -> acpi_dev_handle , buf , PPI_VS_REQ_START ,
341- PPI_VS_REQ_END );
384+ return len ;
342385}
343386
344387static DEVICE_ATTR (version , S_IRUGO , tpm_show_ppi_version , NULL) ;
0 commit comments