1818#include "sof-audio.h"
1919#include "ops.h"
2020
21- static void ipc_trace_message (struct snd_sof_dev * sdev , u32 msg_type );
22- static void ipc_stream_message (struct snd_sof_dev * sdev , u32 msg_cmd );
21+ typedef void (* ipc_rx_callback )(struct snd_sof_dev * sdev , void * msg_buf );
22+
23+ static void ipc_trace_message (struct snd_sof_dev * sdev , void * msg_buf );
24+ static void ipc_stream_message (struct snd_sof_dev * sdev , void * msg_buf );
2325
2426/*
2527 * IPC message Tx/Rx message handling.
@@ -461,44 +463,30 @@ void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
461463}
462464EXPORT_SYMBOL (snd_sof_ipc_reply );
463465
464- static void ipc_comp_notification (struct snd_sof_dev * sdev ,
465- struct sof_ipc_cmd_hdr * hdr )
466+ static void ipc_comp_notification (struct snd_sof_dev * sdev , void * msg_buf )
466467{
468+ struct sof_ipc_cmd_hdr * hdr = msg_buf ;
467469 u32 msg_type = hdr -> cmd & SOF_CMD_TYPE_MASK ;
468- struct sof_ipc_ctrl_data * cdata ;
469- int ret ;
470470
471471 switch (msg_type ) {
472472 case SOF_IPC_COMP_GET_VALUE :
473473 case SOF_IPC_COMP_GET_DATA :
474- cdata = kmalloc (hdr -> size , GFP_KERNEL );
475- if (!cdata )
476- return ;
477-
478- /* read back full message */
479- ret = snd_sof_ipc_msg_data (sdev , NULL , cdata , hdr -> size );
480- if (ret < 0 ) {
481- dev_err (sdev -> dev ,
482- "error: failed to read component event: %d\n" , ret );
483- goto err ;
484- }
485474 break ;
486475 default :
487476 dev_err (sdev -> dev , "error: unhandled component message %#x\n" , msg_type );
488477 return ;
489478 }
490479
491- snd_sof_control_notify (sdev , cdata );
492-
493- err :
494- kfree (cdata );
480+ snd_sof_control_notify (sdev , msg_buf );
495481}
496482
497483/* DSP firmware has sent host a message */
498484void snd_sof_ipc_msgs_rx (struct snd_sof_dev * sdev )
499485{
486+ ipc_rx_callback rx_callback = NULL ;
500487 struct sof_ipc_cmd_hdr hdr ;
501- u32 cmd , type ;
488+ void * msg_buf ;
489+ u32 cmd ;
502490 int err ;
503491
504492 /* read back header */
@@ -507,10 +495,15 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
507495 dev_warn (sdev -> dev , "failed to read IPC header: %d\n" , err );
508496 return ;
509497 }
498+
499+ if (hdr .size < sizeof (hdr )) {
500+ dev_err (sdev -> dev , "The received message size is invalid\n" );
501+ return ;
502+ }
503+
510504 ipc_log_header (sdev -> dev , "ipc rx" , hdr .cmd );
511505
512506 cmd = hdr .cmd & SOF_GLB_TYPE_MASK ;
513- type = hdr .cmd & SOF_CMD_TYPE_MASK ;
514507
515508 /* check message type */
516509 switch (cmd ) {
@@ -535,20 +528,35 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
535528 case SOF_IPC_GLB_PM_MSG :
536529 break ;
537530 case SOF_IPC_GLB_COMP_MSG :
538- ipc_comp_notification ( sdev , & hdr ) ;
531+ rx_callback = ipc_comp_notification ;
539532 break ;
540533 case SOF_IPC_GLB_STREAM_MSG :
541- /* need to pass msg id into the function */
542- ipc_stream_message (sdev , hdr .cmd );
534+ rx_callback = ipc_stream_message ;
543535 break ;
544536 case SOF_IPC_GLB_TRACE_MSG :
545- ipc_trace_message ( sdev , type ) ;
537+ rx_callback = ipc_trace_message ;
546538 break ;
547539 default :
548- dev_err (sdev -> dev , "error: unknown DSP message 0x%x\n" , cmd );
540+ dev_err (sdev -> dev , "%s: Unknown DSP message: 0x%x\n" , __func__ , cmd );
549541 break ;
550542 }
551543
544+ if (rx_callback ) {
545+ /* read the full message as we have rx handler for it */
546+ msg_buf = kmalloc (hdr .size , GFP_KERNEL );
547+ if (!msg_buf )
548+ return ;
549+
550+ err = snd_sof_ipc_msg_data (sdev , NULL , msg_buf , hdr .size );
551+ if (err < 0 )
552+ dev_err (sdev -> dev , "%s: Failed to read message: %d\n" ,
553+ __func__ , err );
554+ else
555+ rx_callback (sdev , msg_buf );
556+
557+ kfree (msg_buf );
558+ }
559+
552560 ipc_log_header (sdev -> dev , "ipc rx done" , hdr .cmd );
553561}
554562EXPORT_SYMBOL (snd_sof_ipc_msgs_rx );
@@ -557,19 +565,14 @@ EXPORT_SYMBOL(snd_sof_ipc_msgs_rx);
557565 * IPC trace mechanism.
558566 */
559567
560- static void ipc_trace_message (struct snd_sof_dev * sdev , u32 msg_type )
568+ static void ipc_trace_message (struct snd_sof_dev * sdev , void * msg_buf )
561569{
562- struct sof_ipc_dma_trace_posn posn ;
563- int ret ;
570+ struct sof_ipc_cmd_hdr * hdr = msg_buf ;
571+ u32 msg_type = hdr -> cmd & SOF_CMD_TYPE_MASK ;
564572
565573 switch (msg_type ) {
566574 case SOF_IPC_TRACE_DMA_POSITION :
567- /* read back full message */
568- ret = snd_sof_ipc_msg_data (sdev , NULL , & posn , sizeof (posn ));
569- if (ret < 0 )
570- dev_warn (sdev -> dev , "failed to read trace position: %d\n" , ret );
571- else
572- snd_sof_trace_update_pos (sdev , & posn );
575+ snd_sof_trace_update_pos (sdev , msg_buf );
573576 break ;
574577 default :
575578 dev_err (sdev -> dev , "error: unhandled trace message %#x\n" , msg_type );
@@ -651,11 +654,11 @@ static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id)
651654}
652655
653656/* stream notifications from DSP FW */
654- static void ipc_stream_message (struct snd_sof_dev * sdev , u32 msg_cmd )
657+ static void ipc_stream_message (struct snd_sof_dev * sdev , void * msg_buf )
655658{
656- /* get msg cmd type and msd id */
657- u32 msg_type = msg_cmd & SOF_CMD_TYPE_MASK ;
658- u32 msg_id = SOF_IPC_MESSAGE_ID (msg_cmd );
659+ struct sof_ipc_cmd_hdr * hdr = msg_buf ;
660+ u32 msg_type = hdr -> cmd & SOF_CMD_TYPE_MASK ;
661+ u32 msg_id = SOF_IPC_MESSAGE_ID (hdr -> cmd );
659662
660663 switch (msg_type ) {
661664 case SOF_IPC_STREAM_POSITION :
0 commit comments