[PATCH 2/2] staging: bcm2835-audio: Simplify callback structure for write data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux