From: Takashi Sakamoto Date: Thu, 20 May 2021 04:01:54 +0000 (+0900) Subject: ALSA: firewire-lib: change waking up timing to process packets X-Git-Tag: v5.15~819^2~9^2~235 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bdaedca74d6293b6ac643a8ebe8231b52bf1171b;p=platform%2Fkernel%2Flinux-starfive.git ALSA: firewire-lib: change waking up timing to process packets 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 Link: https://lore.kernel.org/r/20210520040154.80450-9-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index e9bdb60..a6a7a72 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -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; diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 7725d97..b362a64 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -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 diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 8053d02..df76417 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -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; } diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index c4dfe76..a9a0fe9 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -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; } } diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 405d690..f11aaff 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -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; } diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index 5452115..53a21fb 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -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; } diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 2206af0..858cd60 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -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; } diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 2028c54..925241a 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -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; } diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index e9b6a9f..4121d95 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -9,7 +9,7 @@ #include #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; diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index eb07e1d..296ecf5 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -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; }