From patchwork Sat Dec 8 01:55:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guedes, Andre" X-Patchwork-Id: 10719103 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 670DF13BF for ; Sat, 8 Dec 2018 02:02:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 48CAA2DB7B for ; Sat, 8 Dec 2018 02:02:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3C5D92DB9D; Sat, 8 Dec 2018 02:02:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 75D722DB7B for ; Sat, 8 Dec 2018 02:02:33 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 1CA99267D51; Sat, 8 Dec 2018 03:02:28 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id CA862267D51; Sat, 8 Dec 2018 03:02:25 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by alsa0.perex.cz (Postfix) with ESMTP id BEC41267D2F for ; Sat, 8 Dec 2018 03:02:22 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Dec 2018 18:02:20 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,328,1539673200"; d="scan'208";a="116977200" Received: from aguedesl-mac01.jf.intel.com ([10.24.12.59]) by FMSMGA003.fm.intel.com with ESMTP; 07 Dec 2018 18:02:19 -0800 From: Andre Guedes To: alsa-devel@alsa-project.org Date: Fri, 7 Dec 2018 17:55:44 -0800 Message-Id: <20181208015550.20268-2-andre.guedes@intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181208015550.20268-1-andre.guedes@intel.com> References: <20181208015550.20268-1-andre.guedes@intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, liam.r.girdwood@linux.intel.com, pierre-louis.bossart@linux.intel.com Subject: [alsa-devel] [PATCH - AAF PCM plugin 1/7] doc: Fix typo in AAF doc X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP This patch fixes a typo in aaf.txt documentation. Signed-off-by: Andre Guedes --- doc/aaf.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/aaf.txt b/doc/aaf.txt index 58d9c02..cae86d8 100644 --- a/doc/aaf.txt +++ b/doc/aaf.txt @@ -47,7 +47,7 @@ Enable TAI offset to be automatically set by phc2sys: clockClass 248 clockAccuracy 0xfe \ offsetScaledLogVariance 0xffff \ currentUtcOffset 37 leap61 0 leap59 0 \ - currentUtcOffsetValid 1 p pTimescale 1 \ + currentUtcOffsetValid 1 pTimescale 1 \ timeTraceable 1 frequencyTraceable 0 timeSource 0xa0' Synchronize system clock with PTP clock: From patchwork Sat Dec 8 01:55:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guedes, Andre" X-Patchwork-Id: 10719105 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4BB4313BF for ; Sat, 8 Dec 2018 02:02:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3B14E2DB9D for ; Sat, 8 Dec 2018 02:02:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2F72A2DBAA; Sat, 8 Dec 2018 02:02:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 764952DB9D for ; Sat, 8 Dec 2018 02:02:40 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id EEC7F267D3B; Sat, 8 Dec 2018 03:02:31 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id C7E0F267D53; Sat, 8 Dec 2018 03:02:26 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by alsa0.perex.cz (Postfix) with ESMTP id 48E0E267D3B for ; Sat, 8 Dec 2018 03:02:24 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Dec 2018 18:02:20 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,328,1539673200"; d="scan'208";a="116977201" Received: from aguedesl-mac01.jf.intel.com ([10.24.12.59]) by FMSMGA003.fm.intel.com with ESMTP; 07 Dec 2018 18:02:20 -0800 From: Andre Guedes To: alsa-devel@alsa-project.org Date: Fri, 7 Dec 2018 17:55:45 -0800 Message-Id: <20181208015550.20268-3-andre.guedes@intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181208015550.20268-1-andre.guedes@intel.com> References: <20181208015550.20268-1-andre.guedes@intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, liam.r.girdwood@linux.intel.com, pierre-louis.bossart@linux.intel.com Subject: [alsa-devel] [PATCH - AAF PCM plugin 2/7] aaf: Add presentation time tolerance X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Different AVTP applications have different presentation time tolerance. The current version of the plugin doesn't support any tolerance so this patch extends the AAF plugin in order to enable the user to configure that tolerance value. The presentation time tolerance is specified in microseconds and it is relevant only when the plugin is operating in capture mode. For more information see the 'Plugin Configuration' session in doc/aaf.txt This patch also does some code refactoring and encapsulates all presentation time validation code in the new is_ptime_valid() helper function. Signed-off-by: Andre Guedes --- aaf/pcm_aaf.c | 48 +++++++++++++++++++++++++++++++++++++----------- doc/aaf.txt | 6 ++++++ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/aaf/pcm_aaf.c b/aaf/pcm_aaf.c index b1c3d83..8410dcf 100644 --- a/aaf/pcm_aaf.c +++ b/aaf/pcm_aaf.c @@ -60,6 +60,7 @@ typedef struct { int mtt; int t_uncertainty; snd_pcm_uframes_t frames_per_pdu; + int ptime_tolerance; int sk_fd; int timer_fd; @@ -328,6 +329,17 @@ static int aaf_load_config(snd_pcm_aaf_t *aaf, snd_config_t *conf) goto err; aaf->frames_per_pdu = frames_per_pdu; + } else if (strcmp(id, "ptime_tolerance") == 0) { + long ptime_tolerance; + + if (snd_config_get_integer(entry, + &ptime_tolerance) < 0) + goto err; + + if (ptime_tolerance < 0) + goto err; + + aaf->ptime_tolerance = ptime_tolerance * NSEC_PER_USEC; } else { SNDERR("Invalid configuration: %s", id); goto err; @@ -699,6 +711,27 @@ static int aaf_tx_pdu(snd_pcm_aaf_t *aaf) return 0; } +static bool is_ptime_valid(snd_pcm_aaf_t *aaf, uint32_t avtp_time) +{ + const uint64_t exp_ptime = aaf->prev_ptime + aaf->timer_period; + const uint64_t lower_bound = exp_ptime - aaf->ptime_tolerance; + const uint64_t upper_bound = exp_ptime + aaf->ptime_tolerance; + const uint64_t ptime = (exp_ptime & 0xFFFFFFFF00000000ULL) | avtp_time; + + if (ptime < lower_bound || ptime > upper_bound) { + pr_debug("Presentation time not expected"); + return false; + } + + if (ptime < aaf_mclk_gettime(aaf)) { + pr_debug("Presentation time in the past"); + return false; + } + + aaf->prev_ptime = ptime; + return true; +} + static int aaf_rx_pdu(snd_pcm_aaf_t *aaf) { int res; @@ -753,19 +786,10 @@ static int aaf_rx_pdu(snd_pcm_aaf_t *aaf) if (res < 0) return res; } else { - uint64_t ptime = aaf->prev_ptime + aaf->timer_period; - - if (avtp_time != ptime % (1ULL << 32)) { - pr_debug("Packet dropped: PT not expected"); + if (!is_ptime_valid(aaf, avtp_time)) { + pr_debug("Packet dropped: PT not valid"); return 0; } - - if (ptime < aaf_mclk_gettime(aaf)) { - pr_debug("Packet dropped: PT in the past"); - return 0; - } - - aaf->prev_ptime = ptime; } hw_avail = snd_pcm_ioplug_hw_avail(io, aaf->hw_virt_ptr, io->appl_ptr); @@ -950,6 +974,8 @@ static void aaf_dump(snd_pcm_ioplug_t *io, snd_output_t *out) aaf->t_uncertainty / NSEC_PER_USEC); snd_output_printf(out, " frames per AVTPDU: %lu\n", aaf->frames_per_pdu); + snd_output_printf(out, " ptime tolerance: %d\n", + aaf->ptime_tolerance / NSEC_PER_USEC); } static int aaf_hw_params(snd_pcm_ioplug_t *io, diff --git a/doc/aaf.txt b/doc/aaf.txt index cae86d8..e72eba2 100644 --- a/doc/aaf.txt +++ b/doc/aaf.txt @@ -121,6 +121,11 @@ as follows: * frames_per_pdu: Number of audio frames transmitted in one AVTPDU. + * ptime_tolerance: Presentation time tolerance in microseconds. + AVTPDUs with presentation time off by +- ptime_tolerance are not + considered invalid. This option is relevant only when operating in + capture mode. + Plugin Usage ------------ @@ -138,6 +143,7 @@ below: mtt 2000 time_uncertainty 125 frames_per_pdu 6 + ptime_tolerance 100 } Put the above to ~/.asoundrc (or /etc/asound.conf), and use the AAF PCM virtual From patchwork Sat Dec 8 01:55:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guedes, Andre" X-Patchwork-Id: 10719109 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 276241731 for ; Sat, 8 Dec 2018 02:02:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 14EA72DC03 for ; Sat, 8 Dec 2018 02:02:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0826C2DC46; Sat, 8 Dec 2018 02:02:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4750F2DC03 for ; Sat, 8 Dec 2018 02:02:58 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id C9205267D65; Sat, 8 Dec 2018 03:02:40 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 8CC6D267D58; Sat, 8 Dec 2018 03:02:28 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by alsa0.perex.cz (Postfix) with ESMTP id 812A8267D44 for ; Sat, 8 Dec 2018 03:02:24 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Dec 2018 18:02:20 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,328,1539673200"; d="scan'208";a="116977203" Received: from aguedesl-mac01.jf.intel.com ([10.24.12.59]) by FMSMGA003.fm.intel.com with ESMTP; 07 Dec 2018 18:02:20 -0800 From: Andre Guedes To: alsa-devel@alsa-project.org Date: Fri, 7 Dec 2018 17:55:46 -0800 Message-Id: <20181208015550.20268-4-andre.guedes@intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181208015550.20268-1-andre.guedes@intel.com> References: <20181208015550.20268-1-andre.guedes@intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, liam.r.girdwood@linux.intel.com, pierre-louis.bossart@linux.intel.com Subject: [alsa-devel] [PATCH - AAF PCM plugin 3/7] aaf: Refactor AVTPDU transmission routines X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP This patch does some code refactoring in the AVTPDU transmission routines in order to prepare the code to support the transmission offload mechanism that will be added by upcoming patches. No functionality is added or removed by this patch. In summary, code from aaf_tx_pdu() is moved into aaf_mclk_timeout_ playback() and into a new function introduced by this patch called aaf_tx_pdus(). Below follows more details about the code refactoring. The function aaf_tx_pdu() is modified so it only takes care of setting the payload, sequence number and presentation time from the AVTPDU, and sending it to the kernel. The new function aaf_tx_pdus() calculates the presentation time from each AVTPDU and calls aaf_tx_pdu() multiple times, according to the pdu count argument. Finally, the function aaf_mclk_timeout_playback() now checks if there are frames available to the "hardware" and takes care of moving the hardware pointer forward. Signed-off-by: Andre Guedes --- aaf/pcm_aaf.c | 54 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/aaf/pcm_aaf.c b/aaf/pcm_aaf.c index 8410dcf..1ad1586 100644 --- a/aaf/pcm_aaf.c +++ b/aaf/pcm_aaf.c @@ -661,28 +661,18 @@ static uint64_t aaf_mclk_gettime(snd_pcm_aaf_t *aaf) (aaf->timer_expirations - 1); } -static int aaf_tx_pdu(snd_pcm_aaf_t *aaf) +static int aaf_tx_pdu(snd_pcm_aaf_t *aaf, snd_pcm_uframes_t ptr, + uint64_t ptime) { int res; - uint64_t ptime; ssize_t n; - snd_pcm_uframes_t hw_avail; snd_pcm_ioplug_t *io = &aaf->io; struct avtp_stream_pdu *pdu = aaf->pdu; - hw_avail = snd_pcm_ioplug_hw_avail(io, aaf->hw_ptr, io->appl_ptr); - if (hw_avail < aaf->frames_per_pdu) { - /* If the number of available frames is less than number of - * frames needed to fill an AVTPDU, we reached an underrun - * state. - */ - return -EPIPE; - } - res = snd_pcm_areas_copy_wrap(aaf->payload_areas, 0, aaf->frames_per_pdu, aaf->audiobuf_areas, - (aaf->hw_ptr % io->buffer_size), + (ptr % io->buffer_size), io->buffer_size, io->channels, aaf->frames_per_pdu, io->format); if (res < 0) { @@ -694,7 +684,6 @@ static int aaf_tx_pdu(snd_pcm_aaf_t *aaf) if (res < 0) return res; - ptime = aaf_mclk_gettime(aaf) + aaf->mtt + aaf->t_uncertainty; res = avtp_aaf_pdu_set(pdu, AVTP_AAF_FIELD_TIMESTAMP, ptime); if (res < 0) return res; @@ -707,7 +696,27 @@ static int aaf_tx_pdu(snd_pcm_aaf_t *aaf) return -EIO; } - aaf_inc_ptr(&aaf->hw_ptr, aaf->frames_per_pdu, aaf->boundary); + return 0; +} + +static int aaf_tx_pdus(snd_pcm_aaf_t *aaf, int pdu_count) +{ + int res; + uint64_t ptime; + snd_pcm_uframes_t ptr; + + ptime = aaf_mclk_gettime(aaf) + aaf->mtt + aaf->t_uncertainty; + ptr = aaf->hw_ptr; + + while (pdu_count--) { + res = aaf_tx_pdu(aaf, ptr, ptime); + if (res < 0) + return res; + + ptime += aaf->timer_period; + ptr += aaf->frames_per_pdu; + } + return 0; } @@ -845,6 +854,8 @@ static int aaf_mclk_timeout_playback(snd_pcm_aaf_t *aaf) int res; ssize_t n; uint64_t expirations; + snd_pcm_uframes_t hw_avail; + snd_pcm_ioplug_t *io = &aaf->io; n = read(aaf->timer_fd, &expirations, sizeof(uint64_t)); if (n < 0) { @@ -858,9 +869,20 @@ static int aaf_mclk_timeout_playback(snd_pcm_aaf_t *aaf) while (expirations--) { aaf->timer_expirations++; - res = aaf_tx_pdu(aaf); + hw_avail = snd_pcm_ioplug_hw_avail(io, aaf->hw_ptr, io->appl_ptr); + if (hw_avail < aaf->frames_per_pdu) { + /* If the number of available frames is less than + * number of frames needed to fill an AVTPDU, we + * reached an underrun state. + */ + return -EPIPE; + } + + res = aaf_tx_pdus(aaf, 1); if (res < 0) return res; + + aaf_inc_ptr(&aaf->hw_ptr, aaf->frames_per_pdu, aaf->boundary); } return 0; From patchwork Sat Dec 8 01:55:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guedes, Andre" X-Patchwork-Id: 10719115 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1FAD31731 for ; Sat, 8 Dec 2018 02:03:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C8FC2DC6A for ; Sat, 8 Dec 2018 02:03:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 009302DCC3; Sat, 8 Dec 2018 02:03:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E9A7D2DC6A for ; Sat, 8 Dec 2018 02:03:18 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 1FEEB267D6C; Sat, 8 Dec 2018 03:02:47 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id D1F87267D34; Sat, 8 Dec 2018 03:02:29 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by alsa0.perex.cz (Postfix) with ESMTP id F3CAF267D4E for ; Sat, 8 Dec 2018 03:02:24 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Dec 2018 18:02:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,328,1539673200"; d="scan'208";a="116977204" Received: from aguedesl-mac01.jf.intel.com ([10.24.12.59]) by FMSMGA003.fm.intel.com with ESMTP; 07 Dec 2018 18:02:20 -0800 From: Andre Guedes To: alsa-devel@alsa-project.org Date: Fri, 7 Dec 2018 17:55:47 -0800 Message-Id: <20181208015550.20268-5-andre.guedes@intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181208015550.20268-1-andre.guedes@intel.com> References: <20181208015550.20268-1-andre.guedes@intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, liam.r.girdwood@linux.intel.com, pierre-louis.bossart@linux.intel.com Subject: [alsa-devel] [PATCH - AAF PCM plugin 4/7] aaf: Refactor AVTPDU reception routines X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP This patch does some code refactoring in the AVTPDU reception routines in order to prepare the code to support the transmission offload mechanism that will be added by upcoming patches. No functionality is added or removed by this patch. In summary, the function aaf_rx_pdu() is broken down into smaller, new functions and some code is moved to is_pdu_valid(). Below follows more details about the code refactoring. The function aaf_rx_pdu() was renamed to aaf_socket_new_data() which reads the socket and dispatches the AVTPDU in case the PCM device isn't in DRAIN state. Function aaf_dispatch_pdu() simply reads the subtype field from the AVTPDU and dispatches it according. For now, only AAF PDUs are supported. Finally, the aaf_dispatch_pdu_aaf() handles AAF AVTPDUs which means to check if the AVTPDU is valid, copies the PCM samples from the payload to the audio buffer, and start the media clock in case it hasn't been started already. The function is_pdu_valid() is moved around to avoid forward declaration. Code to validate the sequence number and presentation time from the AVTPDU which used to be in aaf_rx_pdu() is moved into is_pdu_valid(). Signed-off-by: Andre Guedes --- aaf/pcm_aaf.c | 320 +++++++++++++++++++++++++++++--------------------- 1 file changed, 183 insertions(+), 137 deletions(-) diff --git a/aaf/pcm_aaf.c b/aaf/pcm_aaf.c index 1ad1586..49d5bed 100644 --- a/aaf/pcm_aaf.c +++ b/aaf/pcm_aaf.c @@ -129,106 +129,6 @@ static unsigned int alsa_to_avtp_rate(unsigned int rate) } } -static bool is_pdu_valid(struct avtp_stream_pdu *pdu, uint64_t streamid, - unsigned int data_len, unsigned int format, - unsigned int nsr, unsigned int channels, - unsigned int depth) -{ - int res; - uint64_t val64; - uint32_t val32; - struct avtp_common_pdu *common = (struct avtp_common_pdu *) pdu; - - res = avtp_pdu_get(common, AVTP_FIELD_SUBTYPE, &val32); - if (res < 0) - return false; - if (val32 != AVTP_SUBTYPE_AAF) { - pr_debug("Subtype mismatch: expected %u, got %u", - AVTP_SUBTYPE_AAF, val32); - return false; - } - - res = avtp_pdu_get(common, AVTP_FIELD_VERSION, &val32); - if (res < 0) - return false; - if (val32 != 0) { - pr_debug("Version mismatch: expected %u, got %u", 0, val32); - return false; - } - - res = avtp_aaf_pdu_get(pdu, AVTP_AAF_FIELD_STREAM_ID, &val64); - if (res < 0) - return false; - if (val64 != streamid) { - pr_debug("Streamid mismatch: expected %lu, got %lu", streamid, - val64); - return false; - } - - res = avtp_aaf_pdu_get(pdu, AVTP_AAF_FIELD_TV, &val64); - if (res < 0) - return false; - if (val64 != 1) { - pr_debug("TV mismatch: expected %u, got %lu", 1, val64); - return false; - } - - res = avtp_aaf_pdu_get(pdu, AVTP_AAF_FIELD_SP, &val64); - if (res < 0) - return false; - if (val64 != AVTP_AAF_PCM_SP_NORMAL) { - pr_debug("SP mismatch: expected %u, got %lu", - AVTP_AAF_PCM_SP_NORMAL, val64); - return false; - } - - res = avtp_aaf_pdu_get(pdu, AVTP_AAF_FIELD_FORMAT, &val64); - if (res < 0) - return false; - if (val64 != format) { - pr_debug("Format mismatch: expected %u, got %lu", format, - val64); - return false; - } - - res = avtp_aaf_pdu_get(pdu, AVTP_AAF_FIELD_NSR, &val64); - if (res < 0) - return false; - if (val64 != nsr) { - pr_debug("NSR mismatch: expected %u, got %lu", nsr, val64); - return false; - } - - res = avtp_aaf_pdu_get(pdu, AVTP_AAF_FIELD_CHAN_PER_FRAME, &val64); - if (res < 0) - return false; - if (val64 != channels) { - pr_debug("Channels mismatch: expected %u, got %lu", channels, - val64); - return false; - } - - res = avtp_aaf_pdu_get(pdu, AVTP_AAF_FIELD_BIT_DEPTH, &val64); - if (res < 0) - return false; - if (val64 != depth) { - pr_debug("Bit depth mismatch: expected %u, got %lu", depth, - val64); - return false; - } - - res = avtp_aaf_pdu_get(pdu, AVTP_AAF_FIELD_STREAM_DATA_LEN, &val64); - if (res < 0) - return false; - if (val64 != data_len) { - pr_debug("Data len mismatch: expected %u, got %lu", - data_len, val64); - return false; - } - - return true; -} - static int aaf_load_config(snd_pcm_aaf_t *aaf, snd_config_t *conf) { snd_config_iterator_t cur, next; @@ -741,66 +641,134 @@ static bool is_ptime_valid(snd_pcm_aaf_t *aaf, uint32_t avtp_time) return true; } -static int aaf_rx_pdu(snd_pcm_aaf_t *aaf) +static bool is_pdu_valid(snd_pcm_aaf_t *aaf) { int res; - ssize_t n; - uint64_t seq, avtp_time; - snd_pcm_uframes_t hw_avail; + uint64_t val64; + uint32_t val32; snd_pcm_ioplug_t *io = &aaf->io; snd_pcm_t *pcm = io->pcm; + const uint64_t data_len = snd_pcm_frames_to_bytes(pcm, aaf->frames_per_pdu); + const uint64_t format = alsa_to_avtp_format(io->format); + const uint64_t nsr = alsa_to_avtp_rate(io->rate); + const uint64_t depth = snd_pcm_format_width(io->format); + struct avtp_common_pdu *common = (struct avtp_common_pdu *) aaf->pdu; - n = recv(aaf->sk_fd, aaf->pdu, aaf->pdu_size, 0); - if (n < 0) { - SNDERR("Failed to receive data"); - return -errno; + res = avtp_pdu_get(common, AVTP_FIELD_VERSION, &val32); + if (res < 0) + return false; + if (val32 != 0) { + pr_debug("Version mismatch: expected %u, got %u", 0, val32); + return false; } - if (n != aaf->pdu_size) { - pr_debug("AVTPDU dropped: Invalid size"); - return 0; + + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_STREAM_ID, &val64); + if (res < 0) + return false; + if (val64 != aaf->streamid) { + pr_debug("Streamid mismatch: expected %lu, got %lu", + aaf->streamid, val64); + return false; } - if (io->state == SND_PCM_STATE_DRAINING) { - /* If device is in DRAIN state, we shouldn't copy any more data - * to audio buffer. So we are done here. - */ - return 0; + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_TV, &val64); + if (res < 0) + return false; + if (val64 != 1) { + pr_debug("TV mismatch: expected %u, got %lu", 1, val64); + return false; } - if (!is_pdu_valid(aaf->pdu, aaf->streamid, - snd_pcm_frames_to_bytes(pcm, aaf->frames_per_pdu), - alsa_to_avtp_format(io->format), - alsa_to_avtp_rate(io->rate), - io->channels, snd_pcm_format_width(io->format))) { - pr_debug("AVTPDU dropped: Bad field(s)"); - return 0; + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_SP, &val64); + if (res < 0) + return false; + if (val64 != AVTP_AAF_PCM_SP_NORMAL) { + pr_debug("SP mismatch: expected %u, got %lu", + AVTP_AAF_PCM_SP_NORMAL, val64); + return false; } - res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_SEQ_NUM, &seq); + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_FORMAT, &val64); if (res < 0) - return res; - if (seq != aaf->pdu_seq) { + return false; + if (val64 != format) { + pr_debug("Format mismatch: expected %u, got %lu", format, + val64); + return false; + } + + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_NSR, &val64); + if (res < 0) + return false; + if (val64 != nsr) { + pr_debug("NSR mismatch: expected %u, got %lu", nsr, val64); + return false; + } + + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_CHAN_PER_FRAME, &val64); + if (res < 0) + return false; + if (val64 != io->channels) { + pr_debug("Channels mismatch: expected %u, got %lu", + io->channels, val64); + return false; + } + + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_BIT_DEPTH, &val64); + if (res < 0) + return false; + if (val64 != depth) { + pr_debug("Bit depth mismatch: expected %u, got %lu", depth, + val64); + return false; + } + + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_STREAM_DATA_LEN, &val64); + if (res < 0) + return false; + if (val64 != data_len) { + pr_debug("Data len mismatch: expected %u, got %lu", + data_len, val64); + return false; + } + + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_SEQ_NUM, &val64); + if (res < 0) + return false; + if (val64 != aaf->pdu_seq) { pr_debug("Sequence mismatch: expected %u, got %lu", - aaf->pdu_seq, seq); - aaf->pdu_seq = seq; + aaf->pdu_seq, val64); + aaf->pdu_seq = val64; } aaf->pdu_seq++; - res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_TIMESTAMP, &avtp_time); - if (res < 0) - return res; + if (aaf->timer_starttime) { + /* If media clock has started, it means we have already + * received an AVTPDU, so we are able to check if the + * Presentation Time from this AVTPDU is valid. + */ + uint64_t avtp_time; - if (aaf->timer_starttime == 0) { - res = aaf_mclk_start_capture(aaf, avtp_time); + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_TIMESTAMP, + &avtp_time); if (res < 0) - return res; - } else { + return false; + if (!is_ptime_valid(aaf, avtp_time)) { pr_debug("Packet dropped: PT not valid"); - return 0; + return false; } } + return true; +} + +static int aaf_copy_pdu_payload(snd_pcm_aaf_t *aaf) +{ + int res; + snd_pcm_uframes_t hw_avail; + snd_pcm_ioplug_t *io = &aaf->io; + hw_avail = snd_pcm_ioplug_hw_avail(io, aaf->hw_virt_ptr, io->appl_ptr); if (hw_avail < aaf->frames_per_pdu) { /* If there isn't enough space available on buffer to copy the @@ -824,6 +792,84 @@ static int aaf_rx_pdu(snd_pcm_aaf_t *aaf) return 0; } +static int aaf_dispatch_pdu_aaf(snd_pcm_aaf_t *aaf) +{ + int res; + + if (!is_pdu_valid(aaf)) { + pr_debug("AAF PDU dropped: Bad field(s)"); + return 0; + } + + res = aaf_copy_pdu_payload(aaf); + if (res < 0) + return res; + + if (aaf->timer_starttime == 0) { + /* If the media clock has not been started yet (which means + * this is the first AAF PDU received by the plugin), we start + * it. + */ + uint64_t avtp_time; + + res = avtp_aaf_pdu_get(aaf->pdu, AVTP_AAF_FIELD_TIMESTAMP, + &avtp_time); + if (res < 0) + return res; + + res = aaf_mclk_start_capture(aaf, avtp_time); + if (res < 0) + return res; + } + + return 0; +} + +static int aaf_dispatch_pdu(snd_pcm_aaf_t *aaf) +{ + int res; + uint32_t subtype; + struct avtp_common_pdu *common = (struct avtp_common_pdu *) aaf->pdu; + + res = avtp_pdu_get(common, AVTP_FIELD_SUBTYPE, &subtype); + if (res < 0) + return res; + + switch (subtype) { + case AVTP_SUBTYPE_AAF: + return aaf_dispatch_pdu_aaf(aaf); + default: + pr_debug("AVTPDU dropped: subtype not supported"); + return 0; + } +} + +static int aaf_socket_new_data(snd_pcm_aaf_t *aaf) +{ + ssize_t n; + snd_pcm_ioplug_t *io = &aaf->io; + + n = recv(aaf->sk_fd, aaf->pdu, aaf->pdu_size, 0); + if (n < 0) { + SNDERR("Failed to receive data"); + return -errno; + } + if (n != aaf->pdu_size) { + pr_debug("AVTPDU dropped: Invalid size"); + return 0; + } + + if (io->state == SND_PCM_STATE_DRAINING) { + /* If device is in DRAIN state, there is no point in + * dispatching the AVTPDU just received so we are done + * here. + */ + return 0; + } + + return aaf_dispatch_pdu(aaf); +} + static int aaf_flush_rx_buf(snd_pcm_aaf_t *aaf) { char *tmp; @@ -1125,7 +1171,7 @@ static int aaf_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd, } if (pfd[1].revents & POLLIN) { - res = aaf_rx_pdu(aaf); + res = aaf_socket_new_data(aaf); if (res < 0) return res; } From patchwork Sat Dec 8 01:55:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guedes, Andre" X-Patchwork-Id: 10719111 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7161F13BF for ; Sat, 8 Dec 2018 02:03:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5F3C72DC43 for ; Sat, 8 Dec 2018 02:03:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 52BD02DC7D; Sat, 8 Dec 2018 02:03:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8FE472DC43 for ; Sat, 8 Dec 2018 02:03:05 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id D7221267D64; Sat, 8 Dec 2018 03:02:42 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id E6AAD267D57; Sat, 8 Dec 2018 03:02:28 +0100 (CET) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by alsa0.perex.cz (Postfix) with ESMTP id C5213267D34 for ; Sat, 8 Dec 2018 03:02:22 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Dec 2018 18:02:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,328,1539673200"; d="scan'208";a="116977207" Received: from aguedesl-mac01.jf.intel.com ([10.24.12.59]) by FMSMGA003.fm.intel.com with ESMTP; 07 Dec 2018 18:02:21 -0800 From: Andre Guedes To: alsa-devel@alsa-project.org Date: Fri, 7 Dec 2018 17:55:48 -0800 Message-Id: <20181208015550.20268-6-andre.guedes@intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181208015550.20268-1-andre.guedes@intel.com> References: <20181208015550.20268-1-andre.guedes@intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, liam.r.girdwood@linux.intel.com, pierre-louis.bossart@linux.intel.com Subject: [alsa-devel] [PATCH - AAF PCM plugin 5/7] aaf: Refactor timeout routines X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP The functions aaf_mclk_timeout_playback() and aaf_mclk_timeout_capture() have some common code so this patch does a code refactoring by moving the shared code into a new function called aaf_timer_timeout(). After the refactoring, aaf_mclk_timeout_playback() and aaf_mclk_timeout_ capture() ended up having no code related to timeout so they were renamed to better represent what they really do (send frames and present frames, respectively). Signed-off-by: Andre Guedes --- aaf/pcm_aaf.c | 87 ++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/aaf/pcm_aaf.c b/aaf/pcm_aaf.c index 49d5bed..1d7ebca 100644 --- a/aaf/pcm_aaf.c +++ b/aaf/pcm_aaf.c @@ -895,51 +895,64 @@ static int aaf_flush_rx_buf(snd_pcm_aaf_t *aaf) return 0; } -static int aaf_mclk_timeout_playback(snd_pcm_aaf_t *aaf) +static int aaf_tx_frames(snd_pcm_aaf_t *aaf) { int res; - ssize_t n; - uint64_t expirations; snd_pcm_uframes_t hw_avail; snd_pcm_ioplug_t *io = &aaf->io; - n = read(aaf->timer_fd, &expirations, sizeof(uint64_t)); - if (n < 0) { - SNDERR("Failed to read() timer"); - return -errno; + hw_avail = snd_pcm_ioplug_hw_avail(io, aaf->hw_ptr, io->appl_ptr); + if (hw_avail < aaf->frames_per_pdu) { + /* If the number of available frames is less than number of + * frames needed to fill an AVTPDU, we reached an underrun + * state. + */ + return -EPIPE; } - if (expirations != 1) - pr_debug("Missed %llu tx interval(s) ", expirations - 1); + res = aaf_tx_pdus(aaf, 1); + if (res < 0) + return res; - while (expirations--) { - aaf->timer_expirations++; + aaf_inc_ptr(&aaf->hw_ptr, aaf->frames_per_pdu, aaf->boundary); + return 0; +} - hw_avail = snd_pcm_ioplug_hw_avail(io, aaf->hw_ptr, io->appl_ptr); - if (hw_avail < aaf->frames_per_pdu) { - /* If the number of available frames is less than - * number of frames needed to fill an AVTPDU, we - * reached an underrun state. - */ - return -EPIPE; - } +static int aaf_present_frames(snd_pcm_aaf_t *aaf) +{ + snd_pcm_sframes_t len; + snd_pcm_ioplug_t *io = &aaf->io; - res = aaf_tx_pdus(aaf, 1); - if (res < 0) - return res; + len = aaf->hw_virt_ptr - aaf->hw_ptr; + if (len < 0) + len += aaf->boundary; - aaf_inc_ptr(&aaf->hw_ptr, aaf->frames_per_pdu, aaf->boundary); + if ((snd_pcm_uframes_t) len > io->buffer_size) { + /* If the distance between hw virtual pointer and hw + * pointer is greater than the buffer size, it means we + * had an overrun error so -EPIPE is returned. + */ + return -EPIPE; } + aaf_inc_ptr(&aaf->hw_ptr, aaf->frames_per_pdu, aaf->boundary); return 0; } -static int aaf_mclk_timeout_capture(snd_pcm_aaf_t *aaf) +static int aaf_process_frames(snd_pcm_aaf_t *aaf) { + snd_pcm_ioplug_t *io = &aaf->io; + + return (io->stream == SND_PCM_STREAM_PLAYBACK) ? + aaf_tx_frames(aaf) : + aaf_present_frames(aaf); +} + +static int aaf_timer_timeout(snd_pcm_aaf_t *aaf) +{ + int res; ssize_t n; uint64_t expirations; - snd_pcm_sframes_t len; - snd_pcm_ioplug_t *io = &aaf->io; n = read(aaf->timer_fd, &expirations, sizeof(uint64_t)); if (n < 0) { @@ -948,24 +961,14 @@ static int aaf_mclk_timeout_capture(snd_pcm_aaf_t *aaf) } if (expirations != 1) - pr_debug("Missed %llu presentation time(s) ", expirations - 1); + pr_debug("Missed %llu expirations ", expirations - 1); while (expirations--) { aaf->timer_expirations++; - len = aaf->hw_virt_ptr - aaf->hw_ptr; - if (len < 0) - len += aaf->boundary; - - if ((snd_pcm_uframes_t) len > io->buffer_size) { - /* If the distance between hw virtual pointer and hw - * pointer is greater than the buffer size, it means we - * had an overrun error so -EPIPE is returned. - */ - return -EPIPE; - } - - aaf_inc_ptr(&aaf->hw_ptr, aaf->frames_per_pdu, aaf->boundary); + res = aaf_process_frames(aaf); + if (res < 0) + return res; } return 0; @@ -1152,7 +1155,7 @@ static int aaf_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd, return -EINVAL; if (pfd[0].revents & POLLIN) { - res = aaf_mclk_timeout_playback(aaf); + res = aaf_timer_timeout(aaf); if (res < 0) return res; @@ -1163,7 +1166,7 @@ static int aaf_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd, return -EINVAL; if (pfd[0].revents & POLLIN) { - res = aaf_mclk_timeout_capture(aaf); + res = aaf_timer_timeout(aaf); if (res < 0) return res; From patchwork Sat Dec 8 01:55:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guedes, Andre" X-Patchwork-Id: 10719113 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 82D3D1731 for ; Sat, 8 Dec 2018 02:03:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 714D12DCC0 for ; Sat, 8 Dec 2018 02:03:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 596C62DC6A; Sat, 8 Dec 2018 02:03:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7E3692DC6A for ; Sat, 8 Dec 2018 02:03:12 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id DC6C3267D5C; Sat, 8 Dec 2018 03:02:44 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id C95CD267D5B; Sat, 8 Dec 2018 03:02:29 +0100 (CET) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by alsa0.perex.cz (Postfix) with ESMTP id D0BC6267D2F for ; Sat, 8 Dec 2018 03:02:24 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Dec 2018 18:02:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,328,1539673200"; d="scan'208";a="116977209" Received: from aguedesl-mac01.jf.intel.com ([10.24.12.59]) by FMSMGA003.fm.intel.com with ESMTP; 07 Dec 2018 18:02:21 -0800 From: Andre Guedes To: alsa-devel@alsa-project.org Date: Fri, 7 Dec 2018 17:55:49 -0800 Message-Id: <20181208015550.20268-7-andre.guedes@intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181208015550.20268-1-andre.guedes@intel.com> References: <20181208015550.20268-1-andre.guedes@intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, liam.r.girdwood@linux.intel.com, pierre-louis.bossart@linux.intel.com Subject: [alsa-devel] [PATCH - AAF PCM plugin 6/7] aaf: Tx multiple AVTPDUs per media clock tick X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP In order to implement the transmission offload mechanism, we need to change the way the plugin behaves so, instead of sending only one AVTPDU, it sends several AVTPDUs at every media clock tick. To achieve that, this patch changes the plugin so it consumes the audio buffer in chunks of period size instead of in frames_per_pdu. The number of AVTPDUs sent at every media clock tick is calculated by dividing the period size by the number of frames per AVTPDU. To ensure that number is not fractional, the plugin requires that the period size is multiple of the plugin configuration 'frames_per_pdu'. For the sake of consistency, the capture mode is also changed so the plugin presents audio frames to the alsa-lib layer in chunks of period size as well. Signed-off-by: Andre Guedes --- aaf/pcm_aaf.c | 44 +++++++++++++++++++++++++++++++------------- doc/aaf.txt | 7 ++++--- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/aaf/pcm_aaf.c b/aaf/pcm_aaf.c index 1d7ebca..284cbfd 100644 --- a/aaf/pcm_aaf.c +++ b/aaf/pcm_aaf.c @@ -83,6 +83,8 @@ typedef struct { snd_pcm_uframes_t boundary; uint64_t prev_ptime; + + int pdu_period; } snd_pcm_aaf_t; static unsigned int alsa_to_avtp_format(snd_pcm_format_t format) @@ -489,7 +491,7 @@ static int aaf_mclk_start_playback(snd_pcm_aaf_t *aaf) return -errno; } - period = (uint64_t)NSEC_PER_SEC * aaf->frames_per_pdu / io->rate; + period = (uint64_t)NSEC_PER_SEC * io->period_size / io->rate; time = now.tv_sec * NSEC_PER_SEC + now.tv_nsec + period; res = aaf_mclk_start(aaf, time, period); if (res < 0) @@ -502,7 +504,7 @@ static int aaf_mclk_start_capture(snd_pcm_aaf_t *aaf, uint32_t avtp_time) { int res; struct timespec tspec; - uint64_t now, ptime, period; + uint64_t now, ptime, time, period; snd_pcm_ioplug_t *io = &aaf->io; res = clock_gettime(CLOCK_TAI, &tspec); @@ -526,8 +528,9 @@ static int aaf_mclk_start_capture(snd_pcm_aaf_t *aaf, uint32_t avtp_time) if (ptime < now) ptime += (1ULL << 32); - period = (uint64_t)NSEC_PER_SEC * aaf->frames_per_pdu / io->rate; - res = aaf_mclk_start(aaf, ptime, period); + period = (uint64_t)NSEC_PER_SEC * io->period_size / io->rate; + time = ptime + period; + res = aaf_mclk_start(aaf, time, period); if (res < 0) return res; @@ -613,7 +616,7 @@ static int aaf_tx_pdus(snd_pcm_aaf_t *aaf, int pdu_count) if (res < 0) return res; - ptime += aaf->timer_period; + ptime += aaf->pdu_period; ptr += aaf->frames_per_pdu; } @@ -622,7 +625,7 @@ static int aaf_tx_pdus(snd_pcm_aaf_t *aaf, int pdu_count) static bool is_ptime_valid(snd_pcm_aaf_t *aaf, uint32_t avtp_time) { - const uint64_t exp_ptime = aaf->prev_ptime + aaf->timer_period; + const uint64_t exp_ptime = aaf->prev_ptime + aaf->pdu_period; const uint64_t lower_bound = exp_ptime - aaf->ptime_tolerance; const uint64_t upper_bound = exp_ptime + aaf->ptime_tolerance; const uint64_t ptime = (exp_ptime & 0xFFFFFFFF00000000ULL) | avtp_time; @@ -899,22 +902,23 @@ static int aaf_tx_frames(snd_pcm_aaf_t *aaf) { int res; snd_pcm_uframes_t hw_avail; + int pdu_count; snd_pcm_ioplug_t *io = &aaf->io; hw_avail = snd_pcm_ioplug_hw_avail(io, aaf->hw_ptr, io->appl_ptr); - if (hw_avail < aaf->frames_per_pdu) { - /* If the number of available frames is less than number of - * frames needed to fill an AVTPDU, we reached an underrun - * state. + if (hw_avail < io->period_size) { + /* If the number of available frames is less than the period + * size, we reached an underrun state. */ return -EPIPE; } - res = aaf_tx_pdus(aaf, 1); + pdu_count = io->period_size / aaf->frames_per_pdu; + res = aaf_tx_pdus(aaf, pdu_count); if (res < 0) return res; - aaf_inc_ptr(&aaf->hw_ptr, aaf->frames_per_pdu, aaf->boundary); + aaf_inc_ptr(&aaf->hw_ptr, io->period_size, aaf->boundary); return 0; } @@ -935,7 +939,7 @@ static int aaf_present_frames(snd_pcm_aaf_t *aaf) return -EPIPE; } - aaf_inc_ptr(&aaf->hw_ptr, aaf->frames_per_pdu, aaf->boundary); + aaf_inc_ptr(&aaf->hw_ptr, io->period_size, aaf->boundary); return 0; } @@ -1071,8 +1075,22 @@ static int aaf_hw_params(snd_pcm_ioplug_t *io, if (res < 0) goto err_free_pdu; + if (io->period_size % aaf->frames_per_pdu) { + /* The plugin requires that the period size is multiple of the + * configuration frames_per_pdu. Return error if this + * requirement isn't satisfied. + */ + SNDERR("Period size must be multiple of frames_per_pdu"); + res = -EINVAL; + goto err_free_areas; + } + + aaf->pdu_period = (uint64_t)NSEC_PER_SEC * aaf->frames_per_pdu / + io->rate; return 0; +err_free_areas: + free(aaf->payload_areas); err_free_pdu: free(aaf->pdu); err_close_timer: diff --git a/doc/aaf.txt b/doc/aaf.txt index e72eba2..e12a6f6 100644 --- a/doc/aaf.txt +++ b/doc/aaf.txt @@ -147,16 +147,17 @@ below: } Put the above to ~/.asoundrc (or /etc/asound.conf), and use the AAF PCM virtual -device 'aaf0' with your favorite alsa-utils tool. +device 'aaf0' with your favorite alsa-utils tool. Note that the plugin requires +the period size is multiple of the 'frames_per_pdu' configuration. For example, to stream the pink noise generated by 'speaker-test', run: - $ speaker-test -F S16_BE -c 2 -r 48000 -D aaf0 + $ speaker-test -F S16_BE -c 2 -r 48000 -D aaf0 -p 12500 To receive the AAF stream generated by the command above, run the following command in another host: - $ arecord -t raw -f S16_BE -c 2 -r 48000 -D aaf0 -vv /dev/null + $ arecord -t raw -f S16_BE -c 2 -r 48000 -D aaf0 -vv /dev/null -F 12500 If you want to playback the contents of the AAF stream, change the command-line above so the output from 'arecord' is redirected to 'aplay', or simply use the From patchwork Sat Dec 8 01:55:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guedes, Andre" X-Patchwork-Id: 10719117 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3AC5413BF for ; Sat, 8 Dec 2018 02:03:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 290BA2DCC3 for ; Sat, 8 Dec 2018 02:03:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1AA832DCD3; Sat, 8 Dec 2018 02:03:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D26A82DCC3 for ; Sat, 8 Dec 2018 02:03:25 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 2EE37267D75; Sat, 8 Dec 2018 03:02:49 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id D4DF2267D44; Sat, 8 Dec 2018 03:02:29 +0100 (CET) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by alsa0.perex.cz (Postfix) with ESMTP id B7C26267D3B for ; Sat, 8 Dec 2018 03:02:26 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Dec 2018 18:02:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,328,1539673200"; d="scan'208";a="116977211" Received: from aguedesl-mac01.jf.intel.com ([10.24.12.59]) by FMSMGA003.fm.intel.com with ESMTP; 07 Dec 2018 18:02:21 -0800 From: Andre Guedes To: alsa-devel@alsa-project.org Date: Fri, 7 Dec 2018 17:55:50 -0800 Message-Id: <20181208015550.20268-8-andre.guedes@intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181208015550.20268-1-andre.guedes@intel.com> References: <20181208015550.20268-1-andre.guedes@intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, liam.r.girdwood@linux.intel.com, pierre-louis.bossart@linux.intel.com Subject: [alsa-devel] [PATCH - AAF PCM plugin 7/7] aaf: AVTPDU transmission periodicity X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP When operating in playback mode (i.e. AVTP talker) the plugin is expected to transmit the AVTPDUs in a periodical manner. The AVTPDU period is defined by the number of audio frames per AVTPDU and the sampling rate (see section 7.7 from AVTP spec [1] for further information). To enforce the AVTPDU periodicity, this patch leverages the SO_TXTIME sockopt recently added to socket interface which enables the userspace to specify when a given packet should be transmitted. The plugin configures the transmission time from each AVTPDU so the expected transmission interval is maintained. The SO_TXTIME feature works in conjunction with the Earliest TxTime First (ETF) qdisc. The ETF qdisc sorts packets from multiple sockets by the earliest transmission time and sends them to the network controller. It also enables offloading packet transmission to hardware in case the NIC supports it, providing more time accuracy. For further information about ETF qdisc, see tc-etf(8). The qdisc can be configured many ways, in doc/aaf.txt we provide an example. Below follows some implementation highlights: The packet transmission time is configured through socket control message interface so we now use sendmsg() to transmit AVTPDUs, instead of sendto(). sendmsg() API requires a msghdr struct which is initialized during device setup time. Strictly speaking, that struct is only required when operating in playback mode but we initialize it always, no matter if running in playback or capture mode. This makes hw_params() and hw_free() callbacks implementation way more simpler, specially on handling error cases. [1] 1722-2016 - IEEE Standard for a Transport Protocol for Time-Sensitive Applications in Bridged Local Area Networks Signed-off-by: Andre Guedes --- aaf/pcm_aaf.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++---- configure.ac | 2 +- doc/aaf.txt | 25 +++++++++---- 3 files changed, 111 insertions(+), 17 deletions(-) diff --git a/aaf/pcm_aaf.c b/aaf/pcm_aaf.c index 284cbfd..cc7dbe3 100644 --- a/aaf/pcm_aaf.c +++ b/aaf/pcm_aaf.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,9 @@ typedef struct { int pdu_size; uint8_t pdu_seq; + struct msghdr *msg; + struct cmsghdr *cmsg; + uint64_t timer_starttime; uint64_t timer_period; uint64_t timer_expirations; @@ -282,6 +286,8 @@ static int aaf_init_socket(snd_pcm_aaf_t *aaf) memcpy(&aaf->sk_addr.sll_addr, aaf->addr, ETH_ALEN); if (io->stream == SND_PCM_STREAM_PLAYBACK) { + struct sock_txtime txtime_cfg; + res = setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &aaf->prio, sizeof(aaf->prio)); if (res < 0) { @@ -289,6 +295,16 @@ static int aaf_init_socket(snd_pcm_aaf_t *aaf) res = -errno; goto err; } + + txtime_cfg.clockid = CLOCK_TAI; + txtime_cfg.flags = 0; + res = setsockopt(fd, SOL_SOCKET, SO_TXTIME, &txtime_cfg, + sizeof(txtime_cfg)); + if (res < 0) { + SNDERR("Failed to configure txtime"); + res = -errno; + goto err; + } } else { struct packet_mreq mreq = { 0 }; @@ -447,6 +463,62 @@ err: return res; } +static int aaf_init_msghdr(snd_pcm_aaf_t *aaf) +{ + int res; + struct iovec *iov; + char *control; + size_t controllen; + struct msghdr *msg; + struct cmsghdr *cmsg; + + iov = malloc(sizeof(struct iovec)); + if (!iov) { + SNDERR("Failed to allocate iovec"); + return -ENOMEM; + } + + iov->iov_base = aaf->pdu; + iov->iov_len = aaf->pdu_size; + + controllen = CMSG_SPACE(sizeof(__u64)); + control = malloc(controllen); + if (!control) { + SNDERR("Failed to allocate control buffer"); + res = -ENOMEM; + goto err_free_iov; + } + + msg = malloc(sizeof(struct msghdr)); + if (!msg) { + SNDERR("Failed to allocate msghdr"); + res = -ENOMEM; + goto err_free_control; + } + + msg->msg_name = &aaf->sk_addr; + msg->msg_namelen = sizeof(aaf->sk_addr); + msg->msg_iov = iov; + msg->msg_iovlen = 1; + msg->msg_control = control; + msg->msg_controllen = controllen; + + cmsg = CMSG_FIRSTHDR(msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_TXTIME; + cmsg->cmsg_len = CMSG_LEN(sizeof(__u64)); + + aaf->msg = msg; + aaf->cmsg = cmsg; + return 0; + +err_free_control: + free(control); +err_free_iov: + free(iov); + return res; +} + static void aaf_inc_ptr(snd_pcm_uframes_t *ptr, snd_pcm_uframes_t val, snd_pcm_uframes_t boundary) { @@ -565,13 +637,15 @@ static uint64_t aaf_mclk_gettime(snd_pcm_aaf_t *aaf) } static int aaf_tx_pdu(snd_pcm_aaf_t *aaf, snd_pcm_uframes_t ptr, - uint64_t ptime) + uint64_t ptime, __u64 txtime) { int res; ssize_t n; snd_pcm_ioplug_t *io = &aaf->io; struct avtp_stream_pdu *pdu = aaf->pdu; + *(__u64 *)CMSG_DATA(aaf->cmsg) = txtime; + res = snd_pcm_areas_copy_wrap(aaf->payload_areas, 0, aaf->frames_per_pdu, aaf->audiobuf_areas, @@ -591,9 +665,7 @@ static int aaf_tx_pdu(snd_pcm_aaf_t *aaf, snd_pcm_uframes_t ptr, if (res < 0) return res; - n = sendto(aaf->sk_fd, aaf->pdu, aaf->pdu_size, 0, - (struct sockaddr *) &aaf->sk_addr, - sizeof(aaf->sk_addr)); + n = sendmsg(aaf->sk_fd, aaf->msg, 0); if (n < 0 || n != aaf->pdu_size) { SNDERR("Failed to send AAF PDU"); return -EIO; @@ -605,17 +677,19 @@ static int aaf_tx_pdu(snd_pcm_aaf_t *aaf, snd_pcm_uframes_t ptr, static int aaf_tx_pdus(snd_pcm_aaf_t *aaf, int pdu_count) { int res; - uint64_t ptime; + uint64_t ptime, txtime; snd_pcm_uframes_t ptr; - ptime = aaf_mclk_gettime(aaf) + aaf->mtt + aaf->t_uncertainty; + txtime = aaf_mclk_gettime(aaf) + aaf->t_uncertainty; + ptime = txtime + aaf->mtt; ptr = aaf->hw_ptr; while (pdu_count--) { - res = aaf_tx_pdu(aaf, ptr, ptime); + res = aaf_tx_pdu(aaf, ptr, ptime, txtime); if (res < 0) return res; + txtime += aaf->pdu_period; ptime += aaf->pdu_period; ptr += aaf->frames_per_pdu; } @@ -1075,6 +1149,10 @@ static int aaf_hw_params(snd_pcm_ioplug_t *io, if (res < 0) goto err_free_pdu; + res = aaf_init_msghdr(aaf); + if (res < 0) + goto err_free_areas; + if (io->period_size % aaf->frames_per_pdu) { /* The plugin requires that the period size is multiple of the * configuration frames_per_pdu. Return error if this @@ -1082,13 +1160,17 @@ static int aaf_hw_params(snd_pcm_ioplug_t *io, */ SNDERR("Period size must be multiple of frames_per_pdu"); res = -EINVAL; - goto err_free_areas; + goto err_free_msghdr; } aaf->pdu_period = (uint64_t)NSEC_PER_SEC * aaf->frames_per_pdu / io->rate; return 0; +err_free_msghdr: + free(aaf->msg->msg_iov); + free(aaf->msg->msg_control); + free(aaf->msg); err_free_areas: free(aaf->payload_areas); err_free_pdu: @@ -1108,6 +1190,9 @@ static int aaf_hw_free(snd_pcm_ioplug_t *io) close(aaf->timer_fd); free(aaf->pdu); free(aaf->payload_areas); + free(aaf->msg->msg_iov); + free(aaf->msg->msg_control); + free(aaf->msg); return 0; } diff --git a/configure.ac b/configure.ac index 1eb9d65..d300ef0 100644 --- a/configure.ac +++ b/configure.ac @@ -181,7 +181,7 @@ AC_ARG_ENABLE([aaf], if test "x$enable_aaf" != "xno"; then PKG_CHECK_MODULES(AVTP, avtp >= 0.1, [HAVE_AAF=yes], [HAVE_AAF=no]) - AC_CHECK_HEADERS([linux/if_ether.h linux/if_packet.h], [], [HAVE_AAF=no]) + AC_CHECK_HEADERS([linux/if_ether.h linux/if_packet.h linux/net_tstamp.h], [], [HAVE_AAF=no]) fi AM_CONDITIONAL(HAVE_AAF, test x$HAVE_AAF = xyes) diff --git a/doc/aaf.txt b/doc/aaf.txt index e12a6f6..7bf3671 100644 --- a/doc/aaf.txt +++ b/doc/aaf.txt @@ -56,8 +56,8 @@ Synchronize system clock with PTP clock: The commands above should be run on both AVTP Talker and Listener hosts. -FQTSS Setup ------------ +Traffic Control Setup +--------------------- The Linux Traffic Control system provides the mqprio and cbs qdiscs which enable FQTSS on Linux. Below we provide an example to configure those qdiscs in @@ -69,18 +69,27 @@ tc-cbs(8) man pages. On the host that will run as AVTP Talker (i.e. plugin in playback mode), run the following commands: -Configure mpqrio qdisc (replace $HANDLE_ID by an unused handle ID): +Configure mpqrio qdisc (replace $MQPRIO_HANDLE_ID by an unused handle ID): - $ tc qdisc add dev $IFNAME parent root handle $HANDLE_ID mqprio \ - num_tc 3 map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \ + $ tc qdisc add dev $IFNAME parent root handle $MQPRIO_HANDLE_ID \ + mqprio num_tc 3 map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \ queues 1@0 1@1 2@2 hw 0 -Configure cbs qdisc: +Configure cbs qdisc (replace $CBS_HANDLE_ID by an unused handle ID): - $ tc qdisc replace dev $IFNAME parent $HANDLE_ID:1 cbs idleslope 5760 \ + $ tc qdisc replace dev $IFNAME parent $MQPRIO_HANDLE_ID:1 \ + handle $CBS_HANDLE_ID cbs idleslope 5760 \ sendslope -994240 hicredit 9 locredit -89 offload 1 -No FQTSS configuration is required at the host running as AVTP Listener. +The plugin implements a transmission mechanism that relies on ETF qdisc so make +sure it is properly configured in the system. It could be configured many way, +below follows an example. + + $ tc qdisc add dev $IFNAME parent $CBS_HANDLE_ID:1 etf \ + clockid CLOCK_TAI delta 500000 offload + +No Traffic Control configuration is required at the host running as AVTP +Listener. Plugin Dependencies -------------------