Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: SOF: add error handling to snd_sof_ipc_msg_data()

If an invalid stream is passed to snd_sof_ipc_msg_data() it won't
fill the provided object with data. The caller has to be able to
recognise such cases to avoid handling invalid data. Make the
function return an error when failing.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Reviewed-by: Peter Ujfalusi <peter.ujfalusi@intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20210928103516.8066-1-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Guennadi Liakhovetski and committed by
Mark Brown
6a0ba071 b05cfb12

+71 -39
+4 -3
sound/soc/sof/imx/imx8.c
··· 369 369 return type; 370 370 } 371 371 372 - static void imx8_ipc_msg_data(struct snd_sof_dev *sdev, 373 - struct snd_pcm_substream *substream, 374 - void *p, size_t sz) 372 + static int imx8_ipc_msg_data(struct snd_sof_dev *sdev, 373 + struct snd_pcm_substream *substream, 374 + void *p, size_t sz) 375 375 { 376 376 sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); 377 + return 0; 377 378 } 378 379 379 380 static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev,
+4 -3
sound/soc/sof/imx/imx8m.c
··· 232 232 return type; 233 233 } 234 234 235 - static void imx8m_ipc_msg_data(struct snd_sof_dev *sdev, 236 - struct snd_pcm_substream *substream, 237 - void *p, size_t sz) 235 + static int imx8m_ipc_msg_data(struct snd_sof_dev *sdev, 236 + struct snd_pcm_substream *substream, 237 + void *p, size_t sz) 238 238 { 239 239 sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); 240 + return 0; 240 241 } 241 242 242 243 static int imx8m_ipc_pcm_params(struct snd_sof_dev *sdev,
+9 -6
sound/soc/sof/intel/hda-ipc.c
··· 253 253 return SRAM_WINDOW_OFFSET(id); 254 254 } 255 255 256 - void hda_ipc_msg_data(struct snd_sof_dev *sdev, 257 - struct snd_pcm_substream *substream, 258 - void *p, size_t sz) 256 + int hda_ipc_msg_data(struct snd_sof_dev *sdev, 257 + struct snd_pcm_substream *substream, 258 + void *p, size_t sz) 259 259 { 260 260 if (!substream || !sdev->stream_box.size) { 261 261 sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); ··· 268 268 hda_stream.hstream); 269 269 270 270 /* The stream might already be closed */ 271 - if (hstream) 272 - sof_mailbox_read(sdev, hda_stream->stream.posn_offset, 273 - p, sz); 271 + if (!hstream) 272 + return -ESTRPIPE; 273 + 274 + sof_mailbox_read(sdev, hda_stream->stream.posn_offset, p, sz); 274 275 } 276 + 277 + return 0; 275 278 } 276 279 277 280 int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
+3 -3
sound/soc/sof/intel/hda.h
··· 563 563 struct hdac_ext_stream *stream, 564 564 int enable, u32 size); 565 565 566 - void hda_ipc_msg_data(struct snd_sof_dev *sdev, 567 - struct snd_pcm_substream *substream, 568 - void *p, size_t sz); 566 + int hda_ipc_msg_data(struct snd_sof_dev *sdev, 567 + struct snd_pcm_substream *substream, 568 + void *p, size_t sz); 569 569 int hda_ipc_pcm_params(struct snd_sof_dev *sdev, 570 570 struct snd_pcm_substream *substream, 571 571 const struct sof_ipc_pcm_params_reply *reply);
+9 -5
sound/soc/sof/intel/intel-ipc.c
··· 25 25 }; 26 26 27 27 /* Mailbox-based Intel IPC implementation */ 28 - void intel_ipc_msg_data(struct snd_sof_dev *sdev, 29 - struct snd_pcm_substream *substream, 30 - void *p, size_t sz) 28 + int intel_ipc_msg_data(struct snd_sof_dev *sdev, 29 + struct snd_pcm_substream *substream, 30 + void *p, size_t sz) 31 31 { 32 32 if (!substream || !sdev->stream_box.size) { 33 33 sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); ··· 35 35 struct intel_stream *stream = substream->runtime->private_data; 36 36 37 37 /* The stream might already be closed */ 38 - if (stream) 39 - sof_mailbox_read(sdev, stream->posn_offset, p, sz); 38 + if (!stream) 39 + return -ESTRPIPE; 40 + 41 + sof_mailbox_read(sdev, stream->posn_offset, p, sz); 40 42 } 43 + 44 + return 0; 41 45 } 42 46 EXPORT_SYMBOL_NS(intel_ipc_msg_data, SND_SOC_SOF_INTEL_HIFI_EP_IPC); 43 47
+32 -9
sound/soc/sof/ipc.c
··· 394 394 { 395 395 u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK; 396 396 struct sof_ipc_ctrl_data *cdata; 397 + int ret; 397 398 398 399 switch (msg_type) { 399 400 case SOF_IPC_COMP_GET_VALUE: ··· 404 403 return; 405 404 406 405 /* read back full message */ 407 - snd_sof_ipc_msg_data(sdev, NULL, cdata, hdr->size); 406 + ret = snd_sof_ipc_msg_data(sdev, NULL, cdata, hdr->size); 407 + if (ret < 0) { 408 + dev_err(sdev->dev, 409 + "error: failed to read component event: %d\n", ret); 410 + goto err; 411 + } 408 412 break; 409 413 default: 410 414 dev_err(sdev->dev, "error: unhandled component message %#x\n", msg_type); ··· 418 412 419 413 snd_sof_control_notify(sdev, cdata); 420 414 415 + err: 421 416 kfree(cdata); 422 417 } 423 418 ··· 427 420 { 428 421 struct sof_ipc_cmd_hdr hdr; 429 422 u32 cmd, type; 430 - int err = 0; 423 + int err; 431 424 432 425 /* read back header */ 433 - snd_sof_ipc_msg_data(sdev, NULL, &hdr, sizeof(hdr)); 426 + err = snd_sof_ipc_msg_data(sdev, NULL, &hdr, sizeof(hdr)); 427 + if (err < 0) { 428 + dev_warn(sdev->dev, "failed to read IPC header: %d\n", err); 429 + return; 430 + } 434 431 ipc_log_header(sdev->dev, "ipc rx", hdr.cmd); 435 432 436 433 cmd = hdr.cmd & SOF_GLB_TYPE_MASK; ··· 488 477 static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_type) 489 478 { 490 479 struct sof_ipc_dma_trace_posn posn; 480 + int ret; 491 481 492 482 switch (msg_type) { 493 483 case SOF_IPC_TRACE_DMA_POSITION: 494 484 /* read back full message */ 495 - snd_sof_ipc_msg_data(sdev, NULL, &posn, sizeof(posn)); 496 - snd_sof_trace_update_pos(sdev, &posn); 485 + ret = snd_sof_ipc_msg_data(sdev, NULL, &posn, sizeof(posn)); 486 + if (ret < 0) 487 + dev_warn(sdev->dev, "failed to read trace position: %d\n", ret); 488 + else 489 + snd_sof_trace_update_pos(sdev, &posn); 497 490 break; 498 491 default: 499 492 dev_err(sdev->dev, "error: unhandled trace message %#x\n", msg_type); ··· 515 500 struct snd_sof_pcm_stream *stream; 516 501 struct sof_ipc_stream_posn posn; 517 502 struct snd_sof_pcm *spcm; 518 - int direction; 503 + int direction, ret; 519 504 520 505 spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction); 521 506 if (!spcm) { ··· 526 511 } 527 512 528 513 stream = &spcm->stream[direction]; 529 - snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn)); 514 + ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn)); 515 + if (ret < 0) { 516 + dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); 517 + return; 518 + } 530 519 531 520 dev_vdbg(sdev->dev, "posn : host 0x%llx dai 0x%llx wall 0x%llx\n", 532 521 posn.host_posn, posn.dai_posn, posn.wallclock); ··· 549 530 struct snd_sof_pcm_stream *stream; 550 531 struct sof_ipc_stream_posn posn; 551 532 struct snd_sof_pcm *spcm; 552 - int direction; 533 + int direction, ret; 553 534 554 535 spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction); 555 536 if (!spcm) { ··· 559 540 } 560 541 561 542 stream = &spcm->stream[direction]; 562 - snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn)); 543 + ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn)); 544 + if (ret < 0) { 545 + dev_warn(sdev->dev, "failed to read overrun position: %d\n", ret); 546 + return; 547 + } 563 548 564 549 dev_dbg(sdev->dev, "posn XRUN: host %llx comp %d size %d\n", 565 550 posn.host_posn, posn.xrun_comp_id, posn.xrun_size);
+4 -4
sound/soc/sof/ops.h
··· 422 422 } 423 423 424 424 /* host DSP message data */ 425 - static inline void snd_sof_ipc_msg_data(struct snd_sof_dev *sdev, 426 - struct snd_pcm_substream *substream, 427 - void *p, size_t sz) 425 + static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev, 426 + struct snd_pcm_substream *substream, 427 + void *p, size_t sz) 428 428 { 429 - sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz); 429 + return sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz); 430 430 } 431 431 432 432 /* host configure DSP HW parameters */
+6 -6
sound/soc/sof/sof-priv.h
··· 210 210 #endif 211 211 212 212 /* host read DSP stream data */ 213 - void (*ipc_msg_data)(struct snd_sof_dev *sdev, 214 - struct snd_pcm_substream *substream, 215 - void *p, size_t sz); /* mandatory */ 213 + int (*ipc_msg_data)(struct snd_sof_dev *sdev, 214 + struct snd_pcm_substream *substream, 215 + void *p, size_t sz); /* mandatory */ 216 216 217 217 /* host configure DSP HW parameters */ 218 218 int (*ipc_pcm_params)(struct snd_sof_dev *sdev, ··· 567 567 568 568 int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id); 569 569 570 - void intel_ipc_msg_data(struct snd_sof_dev *sdev, 571 - struct snd_pcm_substream *substream, 572 - void *p, size_t sz); 570 + int intel_ipc_msg_data(struct snd_sof_dev *sdev, 571 + struct snd_pcm_substream *substream, 572 + void *p, size_t sz); 573 573 int intel_ipc_pcm_params(struct snd_sof_dev *sdev, 574 574 struct snd_pcm_substream *substream, 575 575 const struct sof_ipc_pcm_params_reply *reply);