~ubuntu-audio-dev/alsa-driver/tiwai-trunk2

« back to all changes in this revision

Viewing changes to firewire/amdtp-stream.c

  • Committer: Canonistack server
  • Date: 2016-05-11 19:04:35 UTC
  • Revision ID: david.henningsson@canonical.com-20160511190435-qjsjpn58d28aqlpu
Test run of 623 machines: 3 failing with 3 errors and 0 warnings.

Show diffs side-by-side

added added

removed removed

Lines of Context:
251
251
        tasklet_kill(&s->period_tasklet);
252
252
        s->pcm_buffer_pointer = 0;
253
253
        s->pcm_period_pointer = 0;
254
 
        s->pointer_flush = true;
255
254
}
256
255
EXPORT_SYMBOL(amdtp_stream_pcm_prepare);
257
256
 
356
355
        s->pcm_period_pointer += frames;
357
356
        if (s->pcm_period_pointer >= pcm->runtime->period_size) {
358
357
                s->pcm_period_pointer -= pcm->runtime->period_size;
359
 
                s->pointer_flush = false;
360
358
                tasklet_hi_schedule(&s->period_tasklet);
361
359
        }
362
360
}
370
368
                snd_pcm_period_elapsed(pcm);
371
369
}
372
370
 
373
 
static int queue_packet(struct amdtp_stream *s,
374
 
                        unsigned int header_length,
375
 
                        unsigned int payload_length, bool skip)
 
371
static int queue_packet(struct amdtp_stream *s, unsigned int header_length,
 
372
                        unsigned int payload_length)
376
373
{
377
374
        struct fw_iso_packet p = {0};
378
375
        int err = 0;
383
380
        p.interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL);
384
381
        p.tag = TAG_CIP;
385
382
        p.header_length = header_length;
386
 
        p.payload_length = (!skip) ? payload_length : 0;
387
 
        p.skip = skip;
 
383
        if (payload_length > 0)
 
384
                p.payload_length = payload_length;
 
385
        else
 
386
                p.skip = true;
388
387
        err = fw_iso_context_queue(s->context, &p, &s->buffer.iso_buffer,
389
388
                                   s->buffer.packets[s->packet_index].offset);
390
389
        if (err < 0) {
399
398
}
400
399
 
401
400
static inline int queue_out_packet(struct amdtp_stream *s,
402
 
                                   unsigned int payload_length, bool skip)
 
401
                                   unsigned int payload_length)
403
402
{
404
 
        return queue_packet(s, OUT_PACKET_HEADER_SIZE,
405
 
                            payload_length, skip);
 
403
        return queue_packet(s, OUT_PACKET_HEADER_SIZE, payload_length);
406
404
}
407
405
 
408
406
static inline int queue_in_packet(struct amdtp_stream *s)
409
407
{
410
408
        return queue_packet(s, IN_PACKET_HEADER_SIZE,
411
 
                            amdtp_stream_get_max_payload(s), false);
 
409
                            amdtp_stream_get_max_payload(s));
412
410
}
413
411
 
414
 
static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle)
 
412
static int handle_out_packet(struct amdtp_stream *s, unsigned int cycle,
 
413
                             unsigned int index)
415
414
{
416
415
        __be32 *buffer;
417
416
        unsigned int syt;
436
435
        s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff;
437
436
        payload_length = 8 + data_blocks * 4 * s->data_block_quadlets;
438
437
 
439
 
        trace_out_packet(s, cycle, buffer, payload_length);
 
438
        trace_out_packet(s, cycle, buffer, payload_length, index);
440
439
 
441
 
        if (queue_out_packet(s, payload_length, false) < 0)
 
440
        if (queue_out_packet(s, payload_length) < 0)
442
441
                return -EIO;
443
442
 
444
443
        pcm = ACCESS_ONCE(s->pcm);
450
449
}
451
450
 
452
451
static int handle_in_packet(struct amdtp_stream *s,
453
 
                            unsigned int payload_quadlets, unsigned int cycle)
 
452
                            unsigned int payload_quadlets, unsigned int cycle,
 
453
                            unsigned int index)
454
454
{
455
455
        __be32 *buffer;
456
456
        u32 cip_header[2];
465
465
        cip_header[0] = be32_to_cpu(buffer[0]);
466
466
        cip_header[1] = be32_to_cpu(buffer[1]);
467
467
 
468
 
        trace_in_packet(s, cycle, cip_header, payload_quadlets);
 
468
        trace_in_packet(s, cycle, cip_header, payload_quadlets, index);
469
469
 
470
470
        /*
471
471
         * This module supports 'Two-quadlet CIP header with SYT field'.
604
604
 
605
605
        for (i = 0; i < packets; ++i) {
606
606
                cycle = increment_cycle_count(cycle, 1);
607
 
                if (handle_out_packet(s, cycle) < 0) {
 
607
                if (handle_out_packet(s, cycle, i) < 0) {
608
608
                        s->packet_index = -1;
609
609
                        amdtp_stream_pcm_abort(s);
610
610
                        return;
651
651
                        break;
652
652
                }
653
653
 
654
 
                if (handle_in_packet(s, payload_quadlets, cycle) < 0)
 
654
                if (handle_in_packet(s, payload_quadlets, cycle, i) < 0)
655
655
                        break;
656
656
        }
657
657
 
764
764
                if (s->direction == AMDTP_IN_STREAM)
765
765
                        err = queue_in_packet(s);
766
766
                else
767
 
                        err = queue_out_packet(s, 0, true);
 
767
                        err = queue_out_packet(s, 0);
768
768
                if (err < 0)
769
769
                        goto err_context;
770
770
        } while (s->packet_index > 0);
803
803
 */
804
804
unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s)
805
805
{
806
 
        /* this optimization is allowed to be racy */
807
 
        if (s->pointer_flush && amdtp_stream_running(s))
 
806
        /*
 
807
         * This function is called in software IRQ context of period_tasklet or
 
808
         * process context.
 
809
         *
 
810
         * When the software IRQ context was scheduled by software IRQ context
 
811
         * of IR/IT contexts, queued packets were already handled. Therefore,
 
812
         * no need to flush the queue in buffer anymore.
 
813
         *
 
814
         * When the process context reach here, some packets will be already
 
815
         * queued in the buffer. These packets should be handled immediately
 
816
         * to keep better granularity of PCM pointer.
 
817
         *
 
818
         * Later, the process context will sometimes schedules software IRQ
 
819
         * context of the period_tasklet. Then, no need to flush the queue by
 
820
         * the same reason as described for IR/IT contexts.
 
821
         */
 
822
        if (!in_interrupt() && amdtp_stream_running(s))
808
823
                fw_iso_context_flush_completions(s->context);
809
 
        else
810
 
                s->pointer_flush = true;
811
824
 
812
825
        return ACCESS_ONCE(s->pcm_buffer_pointer);
813
826
}