ALSA: firewire-lib: change waking up timing to process packets
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Thu, 20 May 2021 04:01:54 +0000 (13:01 +0900)
committerTakashi Iwai <tiwai@suse.de>
Thu, 20 May 2021 12:01:17 +0000 (14:01 +0200)
When starting AMDTP domain, tasks in process context yields running CPU
till all of isochronous context get callback, with an assumption that
it's OK to process content of packet.

However several isochronous cycles are skipped to transfer rx packets, or
the content of rx packets are dropped, to manage the timing to start
processing the packets.

This commit changes the timing for tasks in process context to wake up
when processing content of packet is actually ready.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20210520040154.80450-9-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/firewire/amdtp-stream.c
sound/firewire/amdtp-stream.h
sound/firewire/bebob/bebob_stream.c
sound/firewire/dice/dice-stream.c
sound/firewire/digi00x/digi00x-stream.c
sound/firewire/fireface/ff-stream.c
sound/firewire/fireworks/fireworks_stream.c
sound/firewire/motu/motu-stream.c
sound/firewire/oxfw/oxfw-stream.c
sound/firewire/tascam/tascam-stream.c

index e9bdb609f2ebbdd205f9cbae2ffa66ec75d7398e..a6a7a72a2452b9f20a1898c69dbf06f3e416f13d 100644 (file)
@@ -107,7 +107,7 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
        INIT_WORK(&s->period_work, pcm_period_work);
        s->packet_index = 0;
 
-       init_waitqueue_head(&s->callback_wait);
+       init_waitqueue_head(&s->ready_wait);
        s->callbacked = false;
 
        s->fmt = fmt;
@@ -1029,6 +1029,9 @@ static void process_rx_packets_intermediately(struct fw_iso_context *context, u3
        }
 
        if (offset < packets) {
+               s->ready_processing = true;
+               wake_up(&s->ready_wait);
+
                process_rx_packets(context, tstamp, header_length, ctx_header, private_data);
                if (amdtp_streaming_error(s))
                        return;
@@ -1145,6 +1148,9 @@ static void process_tx_packets_intermediately(struct fw_iso_context *context, u3
        }
 
        if (offset < packets) {
+               s->ready_processing = true;
+               wake_up(&s->ready_wait);
+
                process_tx_packets(context, tstamp, header_length, ctx_header, s);
                if (amdtp_streaming_error(s))
                        return;
@@ -1286,12 +1292,9 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
        const __be32 *ctx_header = header;
        u32 cycle;
 
-       /*
-        * For in-stream, first packet has come.
-        * For out-stream, prepared to transmit first packet
-        */
+       // For in-stream, first packet has come.
+       // For out-stream, prepared to transmit first packet
        s->callbacked = true;
-       wake_up(&s->callback_wait);
 
        if (s->direction == AMDTP_IN_STREAM) {
                cycle = compute_ohci_cycle_count(ctx_header[1]);
@@ -1464,6 +1467,7 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
                tag |= FW_ISO_CONTEXT_MATCH_TAG0;
 
        s->callbacked = false;
+       s->ready_processing = false;
        err = fw_iso_context_start(s->context, -1, 0, tag);
        if (err < 0)
                goto err_pkt_descs;
index 7725d9793458416563fdbcd67044bdfaaca572b4..b362a649926553c6902c2ef202ae29132444867a 100644 (file)
@@ -167,9 +167,11 @@ struct amdtp_stream {
        snd_pcm_uframes_t pcm_buffer_pointer;
        unsigned int pcm_period_pointer;
 
-       /* To wait for first packet. */
-       bool callbacked;
-       wait_queue_head_t callback_wait;
+       // To start processing content of packets at the same cycle in several contexts for
+       // each direction.
+       bool callbacked:1;
+       bool ready_processing:1;
+       wait_queue_head_t ready_wait;
        unsigned int next_cycle;
 
        /* For backends to process data blocks. */
@@ -259,21 +261,6 @@ static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
        return sfc & 1;
 }
 
-/**
- * amdtp_stream_wait_callback - sleep till callbacked or timeout
- * @s: the AMDTP stream
- * @timeout: msec till timeout
- *
- * If this function return false, the AMDTP stream should be stopped.
- */
-static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s,
-                                             unsigned int timeout)
-{
-       return wait_event_timeout(s->callback_wait,
-                                 s->callbacked,
-                                 msecs_to_jiffies(timeout)) > 0;
-}
-
 struct seq_desc {
        unsigned int syt_offset;
        unsigned int data_blocks;
@@ -327,4 +314,25 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
                                              struct amdtp_stream *s);
 int amdtp_domain_stream_pcm_ack(struct amdtp_domain *d, struct amdtp_stream *s);
 
+/**
+ * amdtp_domain_wait_ready - sleep till being ready to process packets or timeout
+ * @d: the AMDTP domain
+ * @timeout_ms: msec till timeout
+ *
+ * If this function return false, the AMDTP domain should be stopped.
+ */
+static inline bool amdtp_domain_wait_ready(struct amdtp_domain *d, unsigned int timeout_ms)
+{
+       struct amdtp_stream *s;
+
+       list_for_each_entry(s, &d->streams, list) {
+               unsigned int j = msecs_to_jiffies(timeout_ms);
+
+               if (wait_event_interruptible_timeout(s->ready_wait, s->ready_processing, j) <= 0)
+                       return false;
+       }
+
+       return true;
+}
+
 #endif
index 8053d02b68f0d197a8be32885d857ea8b29d499b..df764171f84b43fdf2bc8bf992e86d070b83df1d 100644 (file)
@@ -7,8 +7,7 @@
 
 #include "./bebob.h"
 
-#define CALLBACK_TIMEOUT       2500
-#define FW_ISO_RESOURCE_DELAY  1000
+#define READY_TIMEOUT_MS       2500
 
 /*
  * NOTE;
@@ -679,10 +678,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob)
 
                // Some devices postpone start of transmission mostly for 1 sec after receives
                // packets firstly.
-               if (!amdtp_stream_wait_callback(&bebob->rx_stream,
-                                               CALLBACK_TIMEOUT) ||
-                   !amdtp_stream_wait_callback(&bebob->tx_stream,
-                                               CALLBACK_TIMEOUT)) {
+               if (!amdtp_domain_wait_ready(&bebob->domain, READY_TIMEOUT_MS)) {
                        err = -ETIMEDOUT;
                        goto error;
                }
index c4dfe76500c29038a8cbcbddd12ae7694c4d23d7..a9a0fe9635ddb93c2aebcdaa4b9e7ef82a6881f9 100644 (file)
@@ -8,7 +8,7 @@
 
 #include "dice.h"
 
-#define        CALLBACK_TIMEOUT        200
+#define        READY_TIMEOUT_MS        200
 #define NOTIFICATION_TIMEOUT_MS        (2 * MSEC_PER_SEC)
 
 struct reg_params {
@@ -463,16 +463,9 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice)
                if (err < 0)
                        goto error;
 
-               for (i = 0; i < MAX_STREAMS; i++) {
-                       if ((i < tx_params.count &&
-                           !amdtp_stream_wait_callback(&dice->tx_stream[i],
-                                                       CALLBACK_TIMEOUT)) ||
-                           (i < rx_params.count &&
-                            !amdtp_stream_wait_callback(&dice->rx_stream[i],
-                                                        CALLBACK_TIMEOUT))) {
-                               err = -ETIMEDOUT;
-                               goto error;
-                       }
+               if (!amdtp_domain_wait_ready(&dice->domain, READY_TIMEOUT_MS)) {
+                       err = -ETIMEDOUT;
+                       goto error;
                }
        }
 
index 405d6903bfbc3d0eb1e5ba3c52aa1ef4afac6b5b..f11aaff2e24806a8c98f500f8cab181686182a29 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "digi00x.h"
 
-#define CALLBACK_TIMEOUT 500
+#define READY_TIMEOUT_MS       500
 
 const unsigned int snd_dg00x_stream_rates[SND_DG00X_RATE_COUNT] = {
        [SND_DG00X_RATE_44100] = 44100,
@@ -379,10 +379,7 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
                if (err < 0)
                        goto error;
 
-               if (!amdtp_stream_wait_callback(&dg00x->rx_stream,
-                                               CALLBACK_TIMEOUT) ||
-                   !amdtp_stream_wait_callback(&dg00x->tx_stream,
-                                               CALLBACK_TIMEOUT)) {
+               if (!amdtp_domain_wait_ready(&dg00x->domain, READY_TIMEOUT_MS)) {
                        err = -ETIMEDOUT;
                        goto error;
                }
index 5452115c0ef93e52a3e0da00f65c26e9fca73648..53a21fb95add98d8344336678e4af4c996be6c4c 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "ff.h"
 
-#define CALLBACK_TIMEOUT_MS    200
+#define READY_TIMEOUT_MS       200
 
 int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
                                      enum snd_ff_stream_mode *mode)
@@ -203,10 +203,7 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
                if (err < 0)
                        goto error;
 
-               if (!amdtp_stream_wait_callback(&ff->rx_stream,
-                                               CALLBACK_TIMEOUT_MS) ||
-                   !amdtp_stream_wait_callback(&ff->tx_stream,
-                                               CALLBACK_TIMEOUT_MS)) {
+               if (!amdtp_domain_wait_ready(&ff->domain, READY_TIMEOUT_MS)) {
                        err = -ETIMEDOUT;
                        goto error;
                }
index 2206af0fef4224aaff49d7963719d087be3d74e6..858cd6085c1fa451c3435e17d724dd7c538f10c6 100644 (file)
@@ -6,7 +6,7 @@
  */
 #include "./fireworks.h"
 
-#define CALLBACK_TIMEOUT       100
+#define READY_TIMEOUT_MS       100
 
 static int init_stream(struct snd_efw *efw, struct amdtp_stream *stream)
 {
@@ -276,11 +276,7 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw)
                if (err < 0)
                        goto error;
 
-               // Wait first callback.
-               if (!amdtp_stream_wait_callback(&efw->rx_stream,
-                                               CALLBACK_TIMEOUT) ||
-                   !amdtp_stream_wait_callback(&efw->tx_stream,
-                                               CALLBACK_TIMEOUT)) {
+               if (!amdtp_domain_wait_ready(&efw->domain, READY_TIMEOUT_MS)) {
                        err = -ETIMEDOUT;
                        goto error;
                }
index 2028c5419f6ffb546e5f0792fc9acdf46066db24..925241ae2551248d33a761cfe3e1dc072f893015 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "motu.h"
 
-#define        CALLBACK_TIMEOUT        200
+#define        READY_TIMEOUT_MS        200
 
 #define ISOC_COMM_CONTROL_OFFSET               0x0b00
 #define  ISOC_COMM_CONTROL_MASK                        0xffff0000
@@ -264,10 +264,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu)
                if (err < 0)
                        goto stop_streams;
 
-               if (!amdtp_stream_wait_callback(&motu->tx_stream,
-                                               CALLBACK_TIMEOUT) ||
-                   !amdtp_stream_wait_callback(&motu->rx_stream,
-                                               CALLBACK_TIMEOUT)) {
+               if (!amdtp_domain_wait_ready(&motu->domain, READY_TIMEOUT_MS)) {
                        err = -ETIMEDOUT;
                        goto stop_streams;
                }
index e9b6a9f171bfec1b4c741d5102d1543ae0fb4628..4121d95e161f54604a64a7c8c52c70957ed223b0 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/delay.h>
 
 #define AVC_GENERIC_FRAME_MAXIMUM_BYTES        512
-#define CALLBACK_TIMEOUT       200
+#define READY_TIMEOUT_MS       200
 
 /*
  * According to datasheet of Oxford Semiconductor:
@@ -358,20 +358,10 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw)
                if (err < 0)
                        goto error;
 
-               // Wait first packet.
-               if (!amdtp_stream_wait_callback(&oxfw->rx_stream,
-                                               CALLBACK_TIMEOUT)) {
+               if (!amdtp_domain_wait_ready(&oxfw->domain, READY_TIMEOUT_MS)) {
                        err = -ETIMEDOUT;
                        goto error;
                }
-
-               if (oxfw->has_output) {
-                       if (!amdtp_stream_wait_callback(&oxfw->tx_stream,
-                                                       CALLBACK_TIMEOUT)) {
-                               err = -ETIMEDOUT;
-                               goto error;
-                       }
-               }
        }
 
        return 0;
index eb07e1decf9bad3770548e19b8ed2dee14793e17..296ecf5f6ddc5b54d1af03d08c91f8aabe8ead06 100644 (file)
@@ -11,7 +11,7 @@
 #define CLOCK_STATUS_MASK      0xffff0000
 #define CLOCK_CONFIG_MASK      0x0000ffff
 
-#define CALLBACK_TIMEOUT 500
+#define READY_TIMEOUT_MS       500
 
 static int get_clock(struct snd_tscm *tscm, u32 *data)
 {
@@ -477,10 +477,7 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
                if (err < 0)
                        return err;
 
-               if (!amdtp_stream_wait_callback(&tscm->rx_stream,
-                                               CALLBACK_TIMEOUT) ||
-                   !amdtp_stream_wait_callback(&tscm->tx_stream,
-                                               CALLBACK_TIMEOUT)) {
+               if (!amdtp_domain_wait_ready(&tscm->domain, READY_TIMEOUT_MS)) {
                        err = -ETIMEDOUT;
                        goto error;
                }