22/* Copyright 2022 Sven Peter <sven@svenpeter.dev> */
33
44#include <linux/bitfield.h>
5+ #include <linux/debugfs.h>
56#include <linux/dma-mapping.h>
7+ #include <linux/kconfig.h>
68#include <linux/of_platform.h>
79#include <linux/slab.h>
810#include <linux/workqueue.h>
@@ -181,6 +183,18 @@ static void afk_init_rxtx(struct apple_dcp_afkep *ep, u64 message,
181183 afk_send (ep , FIELD_PREP (RBEP_TYPE , RBEP_START ));
182184}
183185
186+ #if IS_ENABLED (CONFIG_DRM_APPLE_DEBUG )
187+ static void afk_populate_service_debugfs (struct apple_epic_service * srv );
188+ static void afk_remove_service_debugfs (struct apple_epic_service * srv );
189+ #else
190+ static void afk_populate_service_debugfs (struct apple_epic_service * srv )
191+ {
192+ }
193+ static void afk_remove_service_debugfs (struct apple_epic_service * srv )
194+ {
195+ }
196+ #endif
197+
184198static const struct apple_epic_service_ops *
185199afk_match_service (struct apple_dcp_afkep * ep , const char * name )
186200{
@@ -284,6 +298,9 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
284298 ops -> init (& ep -> services [ch_idx ], epic_name , epic_class , epic_unit );
285299 dev_info (ep -> dcp -> dev , "AFK[ep:%02x]: new service %s on channel %d\n" ,
286300 ep -> endpoint , service_name , channel );
301+
302+ afk_populate_service_debugfs (& ep -> services [ch_idx ]);
303+
287304free :
288305 kfree (epic_name );
289306 kfree (epic_class );
@@ -302,6 +319,8 @@ static void afk_recv_handle_teardown(struct apple_dcp_afkep *ep, u32 channel)
302319 return ;
303320 }
304321
322+ afk_remove_service_debugfs (service );
323+
305324 // TODO: think through what locking is necessary
306325 spin_lock_irqsave (& service -> lock , flags );
307326 service -> enabled = false;
@@ -989,3 +1008,145 @@ int afk_service_call(struct apple_epic_service *service, u16 group, u32 command,
9891008 kfree (bfr );
9901009 return ret ;
9911010}
1011+
1012+ #if IS_ENABLED (CONFIG_DRM_APPLE_DEBUG )
1013+
1014+ #define AFK_DEBUGFS_MAX_REPLY 8192
1015+
1016+ static ssize_t service_call_write_file (struct file * file , const char __user * user_buf ,
1017+ size_t count , loff_t * ppos )
1018+ {
1019+ struct apple_epic_service * srv = file -> private_data ;
1020+ void * buf ;
1021+ int ret ;
1022+ struct {
1023+ u32 group ;
1024+ u32 command ;
1025+ } call_info ;
1026+
1027+ if (count < sizeof (call_info ))
1028+ return - EINVAL ;
1029+ if (!srv -> debugfs .scratch ) {
1030+ srv -> debugfs .scratch = \
1031+ devm_kzalloc (srv -> ep -> dcp -> dev , AFK_DEBUGFS_MAX_REPLY , GFP_KERNEL );
1032+ if (!srv -> debugfs .scratch )
1033+ return - ENOMEM ;
1034+ }
1035+
1036+ ret = copy_from_user (& call_info , user_buf , sizeof (call_info ));
1037+ if (ret == sizeof (call_info ))
1038+ return - EFAULT ;
1039+ user_buf += sizeof (call_info );
1040+ count -= sizeof (call_info );
1041+
1042+ buf = kmalloc (count , GFP_KERNEL );
1043+ if (!buf )
1044+ return - ENOMEM ;
1045+ ret = copy_from_user (buf , user_buf , count );
1046+ if (ret == count ) {
1047+ kfree (buf );
1048+ return - EFAULT ;
1049+ }
1050+
1051+ memset (srv -> debugfs .scratch , 0 , AFK_DEBUGFS_MAX_REPLY );
1052+ dma_mb ();
1053+
1054+ ret = afk_service_call (srv , call_info .group , call_info .command , buf , count , 0 ,
1055+ srv -> debugfs .scratch , AFK_DEBUGFS_MAX_REPLY , 0 );
1056+ kfree (buf );
1057+
1058+ if (ret < 0 )
1059+ return ret ;
1060+
1061+ return count + sizeof (call_info );
1062+ }
1063+
1064+ static ssize_t service_call_read_file (struct file * file , char __user * user_buf ,
1065+ size_t count , loff_t * ppos )
1066+ {
1067+ struct apple_epic_service * srv = file -> private_data ;
1068+
1069+ if (!srv -> debugfs .scratch )
1070+ return - EINVAL ;
1071+
1072+ return simple_read_from_buffer (user_buf , count , ppos ,
1073+ srv -> debugfs .scratch , AFK_DEBUGFS_MAX_REPLY );
1074+ }
1075+
1076+ static const struct file_operations service_call_fops = {
1077+ .open = simple_open ,
1078+ .write = service_call_write_file ,
1079+ .read = service_call_read_file ,
1080+ };
1081+
1082+ static ssize_t service_raw_call_write_file (struct file * file , const char __user * user_buf ,
1083+ size_t count , loff_t * ppos )
1084+ {
1085+ struct apple_epic_service * srv = file -> private_data ;
1086+ u32 retcode ;
1087+ int ret ;
1088+
1089+ if (!srv -> debugfs .scratch ) {
1090+ srv -> debugfs .scratch = \
1091+ devm_kzalloc (srv -> ep -> dcp -> dev , AFK_DEBUGFS_MAX_REPLY , GFP_KERNEL );
1092+ if (!srv -> debugfs .scratch )
1093+ return - ENOMEM ;
1094+ }
1095+
1096+ memset (srv -> debugfs .scratch , 0 , AFK_DEBUGFS_MAX_REPLY );
1097+ ret = copy_from_user (srv -> debugfs .scratch , user_buf , count );
1098+ if (ret == count )
1099+ return - EFAULT ;
1100+
1101+ ret = afk_send_command (srv , EPIC_SUBTYPE_STD_SERVICE , srv -> debugfs .scratch , count ,
1102+ srv -> debugfs .scratch , AFK_DEBUGFS_MAX_REPLY , & retcode );
1103+ if (ret < 0 )
1104+ return ret ;
1105+ if (retcode )
1106+ return - EINVAL ;
1107+
1108+ return count ;
1109+ }
1110+
1111+ static ssize_t service_raw_call_read_file (struct file * file , char __user * user_buf ,
1112+ size_t count , loff_t * ppos )
1113+ {
1114+ struct apple_epic_service * srv = file -> private_data ;
1115+
1116+ if (!srv -> debugfs .scratch )
1117+ return - EINVAL ;
1118+
1119+ return simple_read_from_buffer (user_buf , count , ppos ,
1120+ srv -> debugfs .scratch , AFK_DEBUGFS_MAX_REPLY );
1121+ }
1122+
1123+ static const struct file_operations service_raw_call_fops = {
1124+ .open = simple_open ,
1125+ .write = service_raw_call_write_file ,
1126+ .read = service_raw_call_read_file ,
1127+ };
1128+
1129+ static void afk_populate_service_debugfs (struct apple_epic_service * srv )
1130+ {
1131+ if (!srv -> ep -> debugfs_entry || !srv -> ops )
1132+ return ;
1133+
1134+ if (strcmp (srv -> ops -> name , "DCPAVAudioInterface" ) == 0 ) {
1135+ srv -> debugfs .entry = debugfs_create_dir (srv -> ops -> name ,
1136+ srv -> ep -> debugfs_entry );
1137+ debugfs_create_file ("call" , 0600 , srv -> debugfs .entry , srv ,
1138+ & service_call_fops );
1139+ debugfs_create_file ("raw_call" , 0600 , srv -> debugfs .entry , srv ,
1140+ & service_raw_call_fops );
1141+ }
1142+ }
1143+
1144+ static void afk_remove_service_debugfs (struct apple_epic_service * srv )
1145+ {
1146+ if (srv -> debugfs .entry ) {
1147+ debugfs_remove_recursive (srv -> debugfs .entry );
1148+ srv -> debugfs .entry = NULL ;
1149+ }
1150+ }
1151+
1152+ #endif
0 commit comments