Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: firewire-lib: use variable size of queue for isoc packets instead of fixed size

The number of packets in packet buffer has been fixed number (=48) since
first commit of ALSA IEC 61883-1/6 packet streaming engine.

This commit allows the engine to use variable number of packets in the
buffer. The size is calculated by a parameter in AMDTP domain structure
surely to store the number of events in the packets of buffer. Although
the value of parameter is expected to come from 'period size' parameter
of PCM substream, at present 48 is still used.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20191017155424.885-2-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Takashi Sakamoto and committed by
Takashi Iwai
a0e02331 3aac3263

+41 -26
+28 -17
sound/firewire/amdtp-stream.c
··· 54 54 55 55 /* TODO: make these configurable */ 56 56 #define INTERRUPT_INTERVAL 16 57 - #define QUEUE_LENGTH 48 58 57 59 58 // For iso header, tstamp and 2 CIP header. 60 59 #define IR_CTX_HEADER_SIZE_CIP 16 ··· 450 451 goto end; 451 452 } 452 453 453 - if (++s->packet_index >= QUEUE_LENGTH) 454 + if (++s->packet_index >= s->queue_size) 454 455 s->packet_index = 0; 455 456 end: 456 457 return err; ··· 668 669 } 669 670 670 671 // Align to actual cycle count for the packet which is going to be scheduled. 671 - // This module queued the same number of isochronous cycle as QUEUE_LENGTH to 672 - // skip isochronous cycle, therefore it's OK to just increment the cycle by 673 - // QUEUE_LENGTH for scheduled cycle. 674 - static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp) 672 + // This module queued the same number of isochronous cycle as the size of queue 673 + // to kip isochronous cycle, therefore it's OK to just increment the cycle by 674 + // the size of queue for scheduled cycle. 675 + static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp, 676 + unsigned int queue_size) 675 677 { 676 678 u32 cycle = compute_cycle_count(ctx_header_tstamp); 677 - return increment_cycle_count(cycle, QUEUE_LENGTH); 679 + return increment_cycle_count(cycle, queue_size); 678 680 } 679 681 680 682 static int generate_device_pkt_descs(struct amdtp_stream *s, ··· 689 689 690 690 for (i = 0; i < packets; ++i) { 691 691 struct pkt_desc *desc = descs + i; 692 - unsigned int index = (s->packet_index + i) % QUEUE_LENGTH; 692 + unsigned int index = (s->packet_index + i) % s->queue_size; 693 693 unsigned int cycle; 694 694 unsigned int payload_length; 695 695 unsigned int data_blocks; ··· 730 730 731 731 for (i = 0; i < packets; ++i) { 732 732 struct pkt_desc *desc = descs + i; 733 - unsigned int index = (s->packet_index + i) % QUEUE_LENGTH; 733 + unsigned int index = (s->packet_index + i) % s->queue_size; 734 734 735 - desc->cycle = compute_it_cycle(*ctx_header); 735 + desc->cycle = compute_it_cycle(*ctx_header, s->queue_size); 736 736 desc->syt = calculate_syt(s, desc->cycle); 737 737 desc->data_blocks = calculate_data_blocks(s, desc->syt); 738 738 ··· 779 779 { 780 780 struct amdtp_stream *s = private_data; 781 781 const __be32 *ctx_header = header; 782 - unsigned int packets = header_length / sizeof(*ctx_header); 782 + unsigned int packets; 783 783 int i; 784 784 785 785 if (s->packet_index < 0) 786 786 return; 787 + 788 + // Calculate the number of packets in buffer and check XRUN. 789 + packets = header_length / sizeof(*ctx_header); 787 790 788 791 generate_ideal_pkt_descs(s, s->pkt_descs, ctx_header, packets); 789 792 ··· 831 828 if (s->packet_index < 0) 832 829 return; 833 830 834 - // The number of packets in buffer. 831 + // Calculate the number of packets in buffer and check XRUN. 835 832 packets = header_length / s->ctx_data.tx.ctx_header_size; 836 833 837 834 err = generate_device_pkt_descs(s, s->pkt_descs, ctx_header, packets); ··· 877 874 878 875 context->callback.sc = in_stream_callback; 879 876 } else { 880 - cycle = compute_it_cycle(*ctx_header); 877 + cycle = compute_it_cycle(*ctx_header, s->queue_size); 881 878 882 879 context->callback.sc = out_stream_callback; 883 880 } ··· 897 894 * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI 898 895 * device can be started. 899 896 */ 900 - static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) 897 + static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, 898 + struct amdtp_domain *d) 901 899 { 902 900 static const struct { 903 901 unsigned int data_block; ··· 912 908 [CIP_SFC_88200] = { 0, 67 }, 913 909 [CIP_SFC_176400] = { 0, 67 }, 914 910 }; 911 + unsigned int events_per_buffer = d->events_per_buffer; 915 912 unsigned int ctx_header_size; 916 913 unsigned int max_ctx_payload_size; 917 914 enum dma_data_direction dir; ··· 958 953 max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP; 959 954 } 960 955 961 - err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, 956 + if (events_per_buffer == 0) 957 + events_per_buffer = INTERRUPT_INTERVAL * 3; 958 + 959 + s->queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer, 960 + amdtp_rate_table[s->sfc]); 961 + 962 + err = iso_packets_buffer_init(&s->buffer, s->unit, s->queue_size, 962 963 max_ctx_payload_size, dir); 963 964 if (err < 0) 964 965 goto err_unlock; ··· 992 981 else 993 982 s->tag = TAG_CIP; 994 983 995 - s->pkt_descs = kcalloc(INTERRUPT_INTERVAL, sizeof(*s->pkt_descs), 984 + s->pkt_descs = kcalloc(s->queue_size, sizeof(*s->pkt_descs), 996 985 GFP_KERNEL); 997 986 if (!s->pkt_descs) { 998 987 err = -ENOMEM; ··· 1207 1196 int err = 0; 1208 1197 1209 1198 list_for_each_entry(s, &d->streams, list) { 1210 - err = amdtp_stream_start(s, s->channel, s->speed); 1199 + err = amdtp_stream_start(s, s->channel, s->speed, d); 1211 1200 if (err < 0) 1212 1201 break; 1213 1202 }
+5 -1
sound/firewire/amdtp-stream.h
··· 117 117 /* For packet processing. */ 118 118 struct fw_iso_context *context; 119 119 struct iso_packets_buffer buffer; 120 + unsigned int queue_size; 120 121 int packet_index; 121 122 struct pkt_desc *pkt_descs; 122 123 int tag; ··· 275 274 struct list_head streams; 276 275 277 276 unsigned int events_per_period; 277 + unsigned int events_per_buffer; 278 278 }; 279 279 280 280 int amdtp_domain_init(struct amdtp_domain *d); ··· 288 286 void amdtp_domain_stop(struct amdtp_domain *d); 289 287 290 288 static inline int amdtp_domain_set_events_per_period(struct amdtp_domain *d, 291 - unsigned int events_per_period) 289 + unsigned int events_per_period, 290 + unsigned int events_per_buffer) 292 291 { 293 292 d->events_per_period = events_per_period; 293 + d->events_per_buffer = events_per_buffer; 294 294 295 295 return 0; 296 296 }
+1 -1
sound/firewire/bebob/bebob_stream.c
··· 610 610 } 611 611 612 612 err = amdtp_domain_set_events_per_period(&bebob->domain, 613 - frames_per_period); 613 + frames_per_period, 0); 614 614 if (err < 0) { 615 615 cmp_connection_release(&bebob->out_conn); 616 616 cmp_connection_release(&bebob->in_conn);
+1 -1
sound/firewire/dice/dice-stream.c
··· 327 327 goto error; 328 328 329 329 err = amdtp_domain_set_events_per_period(&dice->domain, 330 - events_per_period); 330 + events_per_period, 0); 331 331 if (err < 0) 332 332 goto error; 333 333 }
+1 -1
sound/firewire/digi00x/digi00x-stream.c
··· 318 318 } 319 319 320 320 err = amdtp_domain_set_events_per_period(&dg00x->domain, 321 - frames_per_period); 321 + frames_per_period, 0); 322 322 if (err < 0) { 323 323 fw_iso_resources_free(&dg00x->rx_resources); 324 324 fw_iso_resources_free(&dg00x->tx_resources);
+1 -1
sound/firewire/fireface/ff-stream.c
··· 153 153 return err; 154 154 155 155 err = amdtp_domain_set_events_per_period(&ff->domain, 156 - frames_per_period); 156 + frames_per_period, 0); 157 157 if (err < 0) { 158 158 fw_iso_resources_free(&ff->tx_resources); 159 159 fw_iso_resources_free(&ff->rx_resources);
+1 -1
sound/firewire/fireworks/fireworks_stream.c
··· 231 231 } 232 232 233 233 err = amdtp_domain_set_events_per_period(&efw->domain, 234 - frames_per_period); 234 + frames_per_period, 0); 235 235 if (err < 0) { 236 236 cmp_connection_release(&efw->in_conn); 237 237 cmp_connection_release(&efw->out_conn);
+1 -1
sound/firewire/motu/motu-stream.c
··· 174 174 } 175 175 176 176 err = amdtp_domain_set_events_per_period(&motu->domain, 177 - frames_per_period); 177 + frames_per_period, 0); 178 178 if (err < 0) { 179 179 fw_iso_resources_free(&motu->tx_resources); 180 180 fw_iso_resources_free(&motu->rx_resources);
+1 -1
sound/firewire/oxfw/oxfw-stream.c
··· 308 308 } 309 309 310 310 err = amdtp_domain_set_events_per_period(&oxfw->domain, 311 - frames_per_period); 311 + frames_per_period, 0); 312 312 if (err < 0) { 313 313 cmp_connection_release(&oxfw->in_conn); 314 314 if (oxfw->has_output)
+1 -1
sound/firewire/tascam/tascam-stream.c
··· 416 416 } 417 417 418 418 err = amdtp_domain_set_events_per_period(&tscm->domain, 419 - frames_per_period); 419 + frames_per_period, 0); 420 420 if (err < 0) { 421 421 fw_iso_resources_free(&tscm->tx_resources); 422 422 fw_iso_resources_free(&tscm->rx_resources);