All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
To: tiwai@suse.de
Cc: alsa-devel@alsa-project.org, clemens@ladisch.de
Subject: [PATCH 5/6] ALSA: fireface: add local framework to message parser
Date: Thu, 12 Jan 2023 21:09:53 +0900	[thread overview]
Message-ID: <20230112120954.500692-6-o-takashi@sakamocchi.jp> (raw)
In-Reply-To: <20230112120954.500692-1-o-takashi@sakamocchi.jp>

This commit adds local framework to message parser. This is preparation
for future work to pass event of knob control for Fireface 400 to user
space.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/fireface/ff-hwdep.c       | 41 +++++++++++++++++-------
 sound/firewire/fireface/ff-transaction.c |  4 +++
 sound/firewire/fireface/ff.c             | 10 ++++++
 sound/firewire/fireface/ff.h             |  5 +++
 4 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/sound/firewire/fireface/ff-hwdep.c b/sound/firewire/fireface/ff-hwdep.c
index ea64a2a41eea..8a741b3b0436 100644
--- a/sound/firewire/fireface/ff-hwdep.c
+++ b/sound/firewire/fireface/ff-hwdep.c
@@ -15,16 +15,23 @@
 
 #include "ff.h"
 
+static bool has_msg(struct snd_ff *ff)
+{
+	if (ff->spec->protocol->has_msg)
+		return ff->spec->protocol->has_msg(ff);
+	else
+		return 0;
+}
+
 static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf,  long count,
 		       loff_t *offset)
 {
 	struct snd_ff *ff = hwdep->private_data;
 	DEFINE_WAIT(wait);
-	union snd_firewire_event event;
 
 	spin_lock_irq(&ff->lock);
 
-	while (!ff->dev_lock_changed) {
+	while (!ff->dev_lock_changed && !has_msg(ff)) {
 		prepare_to_wait(&ff->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
 		spin_unlock_irq(&ff->lock);
 		schedule();
@@ -34,17 +41,29 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf,  long count,
 		spin_lock_irq(&ff->lock);
 	}
 
-	memset(&event, 0, sizeof(event));
-	event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
-	event.lock_status.status = (ff->dev_lock_count > 0);
-	ff->dev_lock_changed = false;
+	if (ff->dev_lock_changed && count >= sizeof(struct snd_firewire_event_lock_status)) {
+		struct snd_firewire_event_lock_status ev = {
+			.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS,
+			.status = (ff->dev_lock_count > 0),
+		};
 
-	count = min_t(long, count, sizeof(event.lock_status));
+		ff->dev_lock_changed = false;
 
-	spin_unlock_irq(&ff->lock);
+		spin_unlock_irq(&ff->lock);
 
-	if (copy_to_user(buf, &event, count))
-		return -EFAULT;
+		if (copy_to_user(buf, &ev, sizeof(ev)))
+			return -EFAULT;
+		count = sizeof(ev);
+	} else if (has_msg(ff)) {
+		// NOTE: Acquired spin lock should be released before accessing to user space in the
+		// callback since the access can cause page fault.
+		count = ff->spec->protocol->copy_msg_to_user(ff, buf, count);
+		spin_unlock_irq(&ff->lock);
+	} else {
+		spin_unlock_irq(&ff->lock);
+
+		count = 0;
+	}
 
 	return count;
 }
@@ -58,7 +77,7 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
 	poll_wait(file, &ff->hwdep_wait, wait);
 
 	spin_lock_irq(&ff->lock);
-	if (ff->dev_lock_changed)
+	if (ff->dev_lock_changed || has_msg(ff))
 		events = EPOLLIN | EPOLLRDNORM;
 	else
 		events = 0;
diff --git a/sound/firewire/fireface/ff-transaction.c b/sound/firewire/fireface/ff-transaction.c
index 79f733d8c98b..6b89e39f4a43 100644
--- a/sound/firewire/fireface/ff-transaction.c
+++ b/sound/firewire/fireface/ff-transaction.c
@@ -132,11 +132,15 @@ static void handle_msg(struct fw_card *card, struct fw_request *request, int tco
 	struct snd_ff *ff = callback_data;
 	__le32 *buf = data;
 	u32 tstamp = fw_request_get_timestamp(request);
+	unsigned long flag;
 
 	fw_send_response(card, request, RCODE_COMPLETE);
 
 	offset -= ff->async_handler.offset;
+
+	spin_lock_irqsave(&ff->lock, flag);
 	ff->spec->protocol->handle_msg(ff, (unsigned int)offset, buf, length, tstamp);
+	spin_unlock_irqrestore(&ff->lock, flag);
 }
 
 static int allocate_own_address(struct snd_ff *ff, int i)
diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c
index 7bf51d062021..448e972028d9 100644
--- a/sound/firewire/fireface/ff.c
+++ b/sound/firewire/fireface/ff.c
@@ -43,6 +43,8 @@ static void ff_card_free(struct snd_card *card)
 	snd_ff_stream_destroy_duplex(ff);
 	snd_ff_transaction_unregister(ff);
 
+	kfree(ff->msg_parser);
+
 	mutex_destroy(&ff->mutex);
 	fw_unit_put(ff->unit);
 }
@@ -94,6 +96,14 @@ static int snd_ff_probe(struct fw_unit *unit, const struct ieee1394_device_id *e
 	if (err < 0)
 		goto error;
 
+	if (ff->spec->protocol->msg_parser_size > 0) {
+		ff->msg_parser = kzalloc(ff->spec->protocol->msg_parser_size, GFP_KERNEL);
+		if (!ff->msg_parser) {
+			err = -ENOMEM;
+			goto error;
+		}
+	}
+
 	err = snd_card_register(card);
 	if (err < 0)
 		goto error;
diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h
index f430ebe157b3..7e42f5778a8a 100644
--- a/sound/firewire/fireface/ff.h
+++ b/sound/firewire/fireface/ff.h
@@ -97,6 +97,8 @@ struct snd_ff {
 	wait_queue_head_t hwdep_wait;
 
 	struct amdtp_domain domain;
+
+	void *msg_parser;
 };
 
 enum snd_ff_clock_src {
@@ -110,6 +112,9 @@ enum snd_ff_clock_src {
 };
 
 struct snd_ff_protocol {
+	size_t msg_parser_size;
+	bool (*has_msg)(struct snd_ff *ff);
+	long (*copy_msg_to_user)(struct snd_ff *ff, char __user *buf, long count);
 	void (*handle_msg)(struct snd_ff *ff, unsigned int offset, const __le32 *buf,
 			   size_t length, u32 tstamp);
 	int (*fill_midi_msg)(struct snd_ff *ff,
-- 
2.37.2


  parent reply	other threads:[~2023-01-12 12:12 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-12 12:09 [PATCH 0/6] ALSA: fireface: support knob control event for Fireface 400 Takashi Sakamoto
2023-01-12 12:09 ` [PATCH 1/6] ALSA: fireface: rename callback functions Takashi Sakamoto
2023-01-12 12:09 ` [PATCH 2/6] ALSA: fireface: pick up time stamp for request subaction of asynchronous transaction Takashi Sakamoto
2023-01-12 12:09 ` [PATCH 3/6] ALSA: fireface: add helper function to parse MIDI messages transmitted by Fireface 400 Takashi Sakamoto
2023-01-12 12:09 ` [PATCH 4/6] ALSA: fireface: update UAPI for data of knob control Takashi Sakamoto
2023-01-12 12:09 ` Takashi Sakamoto [this message]
2023-01-12 12:09 ` [PATCH 6/6] ALSA: fireface: implement message parser for Fireface 400 Takashi Sakamoto
2023-01-13  8:57 ` [PATCH 0/6] ALSA: fireface: support knob control event " Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230112120954.500692-6-o-takashi@sakamocchi.jp \
    --to=o-takashi@sakamocchi.jp \
    --cc=alsa-devel@alsa-project.org \
    --cc=clemens@ladisch.de \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.