ALSA: firewire-lib: add cache for packet sequence to AMDTP domain structure
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Fri, 8 May 2020 04:36:33 +0000 (13:36 +0900)
committerTakashi Iwai <tiwai@suse.de>
Fri, 8 May 2020 07:46:18 +0000 (09:46 +0200)
For future extension, storage is required to store packet sequence in
incoming AMDTP stream to recover media clock for outgoing AMDTP stream.

This commit adds the storage to AMDTP domain for this purpose. The
packet sequence is represented by 'struct seq_desc' which has two
members; syt_offset and the number of data blocks. The size of storage
is decided according to the size of packet queue.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20200508043635.349339-9-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/firewire/amdtp-stream.c
sound/firewire/amdtp-stream.h

index efd1f2a40cf15398ea69daceae3366461d309b85..f1c8611cfc70ffaef3ed2622235117f34b21d86b 100644 (file)
@@ -1269,6 +1269,8 @@ int amdtp_domain_init(struct amdtp_domain *d)
 
        d->events_per_period = 0;
 
+       d->seq_descs = NULL;
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(amdtp_domain_init);
@@ -1370,12 +1372,18 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
        queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer,
                                  amdtp_rate_table[d->irq_target->sfc]);
 
+       d->seq_descs = kcalloc(queue_size, sizeof(*d->seq_descs), GFP_KERNEL);
+       if (!d->seq_descs)
+               return -ENOMEM;
+       d->seq_size = queue_size;
+       d->seq_tail = 0;
+
        if (ir_delay_cycle > 0) {
                struct fw_card *fw_card = fw_parent_device(s->unit)->card;
 
                err = get_current_cycle_time(fw_card, &cycle);
                if (err < 0)
-                       return err;
+                       goto error;
 
                // No need to care overflow in cycle field because of enough
                // width.
@@ -1431,6 +1439,8 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
 error:
        list_for_each_entry(s, &d->streams, list)
                amdtp_stream_stop(s);
+       kfree(d->seq_descs);
+       d->seq_descs = NULL;
        return err;
 }
 EXPORT_SYMBOL_GPL(amdtp_domain_start);
@@ -1455,5 +1465,8 @@ void amdtp_domain_stop(struct amdtp_domain *d)
 
        d->events_per_period = 0;
        d->irq_target = NULL;
+
+       kfree(d->seq_descs);
+       d->seq_descs = NULL;
 }
 EXPORT_SYMBOL_GPL(amdtp_domain_stop);
index 477fbfe713e585cb8f7c779efb98832d90697fbe..84a01efa5a8581bc4dbdf71230d2314d1cd54769 100644 (file)
@@ -276,6 +276,11 @@ static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s,
                                  msecs_to_jiffies(timeout)) > 0;
 }
 
+struct seq_desc {
+       unsigned int syt_offset;
+       unsigned int data_blocks;
+};
+
 struct amdtp_domain {
        struct list_head streams;
 
@@ -283,6 +288,10 @@ struct amdtp_domain {
        unsigned int events_per_buffer;
 
        struct amdtp_stream *irq_target;
+
+       struct seq_desc *seq_descs;
+       unsigned int seq_size;
+       unsigned int seq_tail;
 };
 
 int amdtp_domain_init(struct amdtp_domain *d);