The device sends data to the audio devices by sending a message with the data through VC04_SERVICES/VCHIQ. This message contains a callback pointer that is always filled in with the same function. This is prone to corruption issues. Instead fill the callback fields with a fixed cookie value to perforam some validation on the message response and call the handler function directly instead of through the callback pointer. Signed-off-by: Michael Zoran <mzoran@xxxxxxxxxxxx> --- drivers/staging/bcm2835-audio/bcm2835-pcm.c | 9 +----- drivers/staging/bcm2835-audio/bcm2835-vchiq.c | 35 ++++++++++------------ drivers/staging/bcm2835-audio/bcm2835.h | 4 +-- .../staging/bcm2835-audio/vc_vchi_audioserv_defs.h | 18 +++-------- 4 files changed, 22 insertions(+), 44 deletions(-) diff --git a/drivers/staging/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/bcm2835-audio/bcm2835-pcm.c index 2c3bf63e3391..d2d9f9b6a09b 100644 --- a/drivers/staging/bcm2835-audio/bcm2835-pcm.c +++ b/drivers/staging/bcm2835-audio/bcm2835-pcm.c @@ -61,9 +61,8 @@ static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime) runtime->private_data = NULL; } -static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id) +void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream) { - struct bcm2835_alsa_stream *alsa_stream = dev_id; unsigned int consumed = 0; int new_period = 0; @@ -103,8 +102,6 @@ static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id) audio_warning(" unexpected NULL substream\n"); } audio_info(" .. OUT\n"); - - return IRQ_HANDLED; } /* open callback */ @@ -164,10 +161,6 @@ static int snd_bcm2835_playback_open_generic( sema_init(&alsa_stream->control_sem, 0); spin_lock_init(&alsa_stream->lock); - /* Enabled in start trigger, called on each "fifo irq" after that */ - alsa_stream->enable_fifo_irq = 0; - alsa_stream->fifo_irq_handler = bcm2835_playback_fifo_irq; - err = bcm2835_audio_open(alsa_stream); if (err) { kfree(alsa_stream); diff --git a/drivers/staging/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/bcm2835-audio/bcm2835-vchiq.c index af70c27004cc..e8fd9c79bcfc 100644 --- a/drivers/staging/bcm2835-audio/bcm2835-vchiq.c +++ b/drivers/staging/bcm2835-audio/bcm2835-vchiq.c @@ -100,6 +100,11 @@ bcm2835_vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, size); } +static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 || + 'M' << 8 | 'A'); +static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 || + 'T' << 8 | 'A'); + struct bcm2835_audio_work { struct work_struct my_work; struct bcm2835_alsa_stream *alsa_stream; @@ -248,21 +253,18 @@ static void audio_vchi_callback(void *param, complete(&instance->msg_avail_comp); } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) { struct bcm2835_alsa_stream *alsa_stream = instance->alsa_stream; -#if defined(CONFIG_64BIT) - irq_handler_t callback = - (irq_handler_t) (((unsigned long) m.u.complete.callbackl) | - ((unsigned long) m.u.complete.callbackh << 32)); -#else - irq_handler_t callback = (irq_handler_t) m.u.complete.callback; -#endif LOG_DBG(" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n", instance, m.u.complete.count); - if (alsa_stream && callback) { - atomic_add(m.u.complete.count, &alsa_stream->retrieved); - callback(0, alsa_stream); + if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 || + m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2) + LOG_ERR(" .. response is corrupt\n"); + else if (alsa_stream) { + atomic_add(m.u.complete.count, + &alsa_stream->retrieved); + bcm2835_playback_fifo(alsa_stream); } else { - LOG_ERR(" .. unexpected alsa_stream=%p, callback=%p\n", - alsa_stream, callback); + LOG_ERR(" .. unexpected alsa_stream=%p\n", + alsa_stream); } } else { LOG_ERR(" .. unexpected m.type=%d\n", m.type); @@ -815,13 +817,8 @@ int bcm2835_audio_write_worker(struct bcm2835_alsa_stream *alsa_stream, m.u.write.count = count; // old version uses bulk, new version uses control m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0 : 4000; -#if defined(CONFIG_64BIT) - m.u.write.callbackl = (u32) (((unsigned long) alsa_stream->fifo_irq_handler)&0xFFFFFFFF); - m.u.write.callbackh = (u32) ((((unsigned long) alsa_stream->fifo_irq_handler) >> 32)&0xFFFFFFFF); -#else - m.u.write.callback = alsa_stream->fifo_irq_handler; - m.u.write.cookie = alsa_stream; -#endif + m.u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1; + m.u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2; m.u.write.silence = src == NULL; /* Send the message to the videocore */ diff --git a/drivers/staging/bcm2835-audio/bcm2835.h b/drivers/staging/bcm2835-audio/bcm2835.h index d333629e93e5..36e3ef80e60c 100644 --- a/drivers/staging/bcm2835-audio/bcm2835.h +++ b/drivers/staging/bcm2835-audio/bcm2835.h @@ -137,9 +137,6 @@ struct bcm2835_alsa_stream { unsigned int buffer_size; unsigned int period_size; - unsigned int enable_fifo_irq; - irq_handler_t fifo_irq_handler; - atomic_t retrieved; struct bcm2835_audio_instance *instance; struct workqueue_struct *my_wq; @@ -162,6 +159,7 @@ int bcm2835_audio_set_ctls(struct bcm2835_chip *chip); int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream, unsigned int count, void *src); +void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream); unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream); void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream); void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream); diff --git a/drivers/staging/bcm2835-audio/vc_vchi_audioserv_defs.h b/drivers/staging/bcm2835-audio/vc_vchi_audioserv_defs.h index 2cc81f062274..09f07fd891bb 100644 --- a/drivers/staging/bcm2835-audio/vc_vchi_audioserv_defs.h +++ b/drivers/staging/bcm2835-audio/vc_vchi_audioserv_defs.h @@ -74,13 +74,8 @@ struct vc_audio_stop { /* configure the write audio samples */ struct vc_audio_write { u32 count; // in bytes -#if defined(CONFIG_64BIT) - u32 callbackl; - u32 callbackh; -#else - void *callback; - void *cookie; -#endif + u32 cookie1; + u32 cookie2; s16 silence; s16 max_packet; }; @@ -93,13 +88,8 @@ struct vc_audio_result { /* Generic result for a request (VC->HOST) */ struct vc_audio_complete { s32 count; // Success value -#if defined(CONFIG_64BIT) - u32 callbackl; - u32 callbackh; -#else - void *callback; - void *cookie; -#endif + u32 cookie1; + u32 cookie2; }; /* Message header for all messages in HOST->VC direction */ -- 2.11.0 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel