20
20
#include <linux/semaphore.h>
21
21
22
22
#define DRIVER_NAME "amd_hsmp"
23
- #define DRIVER_VERSION "1 .0"
23
+ #define DRIVER_VERSION "2 .0"
24
24
25
25
/* HSMP Status / Error codes */
26
26
#define HSMP_STATUS_NOT_READY 0x00
49
49
50
50
#define HSMP_CDEV_NAME "hsmp_cdev"
51
51
#define HSMP_DEVNODE_NAME "hsmp"
52
+ #define HSMP_METRICS_TABLE_NAME "metrics_bin"
53
+
54
+ #define HSMP_ATTR_GRP_NAME_SIZE 10
52
55
53
56
struct hsmp_socket {
57
+ struct bin_attribute hsmp_attr ;
58
+ void __iomem * metric_tbl_addr ;
54
59
struct semaphore hsmp_sem ;
60
+ char name [HSMP_ATTR_GRP_NAME_SIZE ];
55
61
u16 sock_ind ;
56
62
};
57
63
58
64
struct hsmp_plat_device {
59
65
struct miscdevice hsmp_device ;
60
66
struct hsmp_socket * sock ;
61
67
struct device * dev ;
68
+ u32 proto_ver ;
62
69
u16 num_sockets ;
63
70
};
64
71
@@ -330,9 +337,162 @@ static const struct file_operations hsmp_fops = {
330
337
.compat_ioctl = hsmp_ioctl ,
331
338
};
332
339
340
+ static ssize_t hsmp_metric_tbl_read (struct file * filp , struct kobject * kobj ,
341
+ struct bin_attribute * bin_attr , char * buf ,
342
+ loff_t off , size_t count )
343
+ {
344
+ struct hsmp_socket * sock = bin_attr -> private ;
345
+ struct hsmp_message msg = { 0 };
346
+ int ret ;
347
+
348
+ /* Do not support lseek(), reads entire metric table */
349
+ if (count < bin_attr -> size ) {
350
+ dev_err (plat_dev .dev , "Wrong buffer size\n" );
351
+ return - EINVAL ;
352
+ }
353
+
354
+ if (!sock ) {
355
+ dev_err (plat_dev .dev , "Failed to read attribute private data\n" );
356
+ return - EINVAL ;
357
+ }
358
+
359
+ msg .msg_id = HSMP_GET_METRIC_TABLE ;
360
+ msg .sock_ind = sock -> sock_ind ;
361
+
362
+ ret = hsmp_send_message (& msg );
363
+ if (ret )
364
+ return ret ;
365
+ memcpy (buf , sock -> metric_tbl_addr , bin_attr -> size );
366
+
367
+ return bin_attr -> size ;
368
+ }
369
+
370
+ static int hsmp_get_tbl_dram_base (u16 sock_ind )
371
+ {
372
+ struct hsmp_socket * sock = & plat_dev .sock [sock_ind ];
373
+ struct hsmp_message msg = { 0 };
374
+ phys_addr_t dram_addr ;
375
+ int ret ;
376
+
377
+ msg .sock_ind = sock_ind ;
378
+ msg .response_sz = hsmp_msg_desc_table [HSMP_GET_METRIC_TABLE_DRAM_ADDR ].response_sz ;
379
+ msg .msg_id = HSMP_GET_METRIC_TABLE_DRAM_ADDR ;
380
+
381
+ ret = hsmp_send_message (& msg );
382
+ if (ret )
383
+ return ret ;
384
+
385
+ /*
386
+ * calculate the metric table DRAM address from lower and upper 32 bits
387
+ * sent from SMU and ioremap it to virtual address.
388
+ */
389
+ dram_addr = msg .args [0 ] | ((u64 )(msg .args [1 ]) << 32 );
390
+ if (!dram_addr ) {
391
+ dev_err (plat_dev .dev , "Invalid DRAM address for metric table\n" );
392
+ return - ENOMEM ;
393
+ }
394
+ sock -> metric_tbl_addr = devm_ioremap (plat_dev .dev , dram_addr ,
395
+ sizeof (struct hsmp_metric_table ));
396
+ if (!sock -> metric_tbl_addr ) {
397
+ dev_err (plat_dev .dev , "Failed to ioremap metric table addr\n" );
398
+ return - ENOMEM ;
399
+ }
400
+ return 0 ;
401
+ }
402
+
403
+ static umode_t hsmp_is_sock_attr_visible (struct kobject * kobj ,
404
+ struct bin_attribute * battr , int id )
405
+ {
406
+ if (plat_dev .proto_ver == HSMP_PROTO_VER6 )
407
+ return battr -> attr .mode ;
408
+ else
409
+ return 0 ;
410
+ }
411
+
412
+ static int hsmp_init_metric_tbl_bin_attr (struct bin_attribute * * hattrs , u16 sock_ind )
413
+ {
414
+ struct bin_attribute * hattr = & plat_dev .sock [sock_ind ].hsmp_attr ;
415
+
416
+ sysfs_bin_attr_init (hattr );
417
+ hattr -> attr .name = HSMP_METRICS_TABLE_NAME ;
418
+ hattr -> attr .mode = 0444 ;
419
+ hattr -> read = hsmp_metric_tbl_read ;
420
+ hattr -> size = sizeof (struct hsmp_metric_table );
421
+ hattr -> private = & plat_dev .sock [sock_ind ];
422
+ hattrs [0 ] = hattr ;
423
+
424
+ if (plat_dev .proto_ver == HSMP_PROTO_VER6 )
425
+ return (hsmp_get_tbl_dram_base (sock_ind ));
426
+ else
427
+ return 0 ;
428
+ }
429
+
430
+ /* One bin sysfs for metrics table*/
431
+ #define NUM_HSMP_ATTRS 1
432
+
433
+ static int hsmp_create_sysfs_interface (void )
434
+ {
435
+ const struct attribute_group * * hsmp_attr_grps ;
436
+ struct bin_attribute * * hsmp_bin_attrs ;
437
+ struct attribute_group * attr_grp ;
438
+ int ret ;
439
+ u16 i ;
440
+
441
+ /* String formatting is currently limited to u8 sockets */
442
+ if (WARN_ON (plat_dev .num_sockets > U8_MAX ))
443
+ return - ERANGE ;
444
+
445
+ hsmp_attr_grps = devm_kzalloc (plat_dev .dev , sizeof (struct attribute_group * ) *
446
+ (plat_dev .num_sockets + 1 ), GFP_KERNEL );
447
+ if (!hsmp_attr_grps )
448
+ return - ENOMEM ;
449
+
450
+ /* Create a sysfs directory for each socket */
451
+ for (i = 0 ; i < plat_dev .num_sockets ; i ++ ) {
452
+ attr_grp = devm_kzalloc (plat_dev .dev , sizeof (struct attribute_group ), GFP_KERNEL );
453
+ if (!attr_grp )
454
+ return - ENOMEM ;
455
+
456
+ snprintf (plat_dev .sock [i ].name , HSMP_ATTR_GRP_NAME_SIZE , "socket%u" , (u8 )i );
457
+ attr_grp -> name = plat_dev .sock [i ].name ;
458
+
459
+ /* Null terminated list of attributes */
460
+ hsmp_bin_attrs = devm_kzalloc (plat_dev .dev , sizeof (struct bin_attribute * ) *
461
+ (NUM_HSMP_ATTRS + 1 ), GFP_KERNEL );
462
+ if (!hsmp_bin_attrs )
463
+ return - ENOMEM ;
464
+
465
+ attr_grp -> bin_attrs = hsmp_bin_attrs ;
466
+ attr_grp -> is_bin_visible = hsmp_is_sock_attr_visible ;
467
+ hsmp_attr_grps [i ] = attr_grp ;
468
+
469
+ /* Now create the leaf nodes */
470
+ ret = hsmp_init_metric_tbl_bin_attr (hsmp_bin_attrs , i );
471
+ if (ret )
472
+ return ret ;
473
+ }
474
+ return devm_device_add_groups (plat_dev .dev , hsmp_attr_grps );
475
+ }
476
+
477
+ static int hsmp_cache_proto_ver (void )
478
+ {
479
+ struct hsmp_message msg = { 0 };
480
+ int ret ;
481
+
482
+ msg .msg_id = HSMP_GET_PROTO_VER ;
483
+ msg .sock_ind = 0 ;
484
+ msg .response_sz = hsmp_msg_desc_table [HSMP_GET_PROTO_VER ].response_sz ;
485
+
486
+ ret = hsmp_send_message (& msg );
487
+ if (!ret )
488
+ plat_dev .proto_ver = msg .args [0 ];
489
+
490
+ return ret ;
491
+ }
492
+
333
493
static int hsmp_pltdrv_probe (struct platform_device * pdev )
334
494
{
335
- int i ;
495
+ int ret , i ;
336
496
337
497
plat_dev .sock = devm_kzalloc (& pdev -> dev ,
338
498
(plat_dev .num_sockets * sizeof (struct hsmp_socket )),
@@ -353,6 +513,16 @@ static int hsmp_pltdrv_probe(struct platform_device *pdev)
353
513
plat_dev .hsmp_device .nodename = HSMP_DEVNODE_NAME ;
354
514
plat_dev .hsmp_device .mode = 0644 ;
355
515
516
+ ret = hsmp_cache_proto_ver ();
517
+ if (ret ) {
518
+ dev_err (plat_dev .dev , "Failed to read HSMP protocol version\n" );
519
+ return ret ;
520
+ }
521
+
522
+ ret = hsmp_create_sysfs_interface ();
523
+ if (ret )
524
+ dev_err (plat_dev .dev , "Failed to create HSMP sysfs interface\n" );
525
+
356
526
return misc_register (& plat_dev .hsmp_device );
357
527
}
358
528
0 commit comments