[alsa-devel] [PATCH alsa-lib v2 0/6] pcm: hw: optimization for v2.0.14 of PCM protocol/interface
Hi,
This patchset is a revised version of my previous one:
[PATCH alsa-lib 00/12] pcm: hw: optimization for v2.0.14 of PCM protocol/interface http://mailman.alsa-project.org/pipermail/alsa-devel/2017-June/122392.html
Changes: - add a helper function, 'query_status_and_control_data()' to update appl_ptr in user space. - rename 'query_state()' to 'query_status_data()' - reduce two patches. - aggregate some patches for querying control data.
I did quick mesurement by execute aplay on x86 machine with.
1. With Intel HDA driver with usual configuration. ``` poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}]) ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0) = 0 read(3, "a\23IH\205\177z\257\276]\346\237\313\220L\5\337V\363\351\216\17\346s\22\245-yb\312\37D"..., 16384) = 16384 ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0) = 0 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}]) ```
2. With Intel HDA driver with 'sync_ptr_ioctl' option to hw PCM plugin. ``` poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}]) ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 read(3, "Rz\vB\v|A\275\356`\201)\335i3\r}\21Q^\30\324'\r'\375l\235&\3330\2"..., 16384) = 16384 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}]) ```
3. With Fireworks driver with a patch for snd-firewire-lib to add SNDRV_PCM_INFO_SYNC_APPLPTR support[1]. ``` poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}]) ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55b647ec9c00) = 0 read(3, "|\n*\336\322\252*&\377\312\372&\276\333.\207\21\343\362\3\5\363\201\266\3421lZ;\\22*"..., 24576) = 24576 ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0) = 0 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}]) ```
We can see this optimization reduces some ioctl calls in case 3. This is due to status data mapping.
[1] Below. diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index f8c2765..04fb3df 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -160,7 +160,8 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID; + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_APPLPTR;
/* SNDRV_PCM_INFO_BATCH */ hw->periods_min = 2;
Takashi Sakamoto (6): pcm: hw: add a helper function to query status/control data pcm: hw: add a helper function just to query status data pcm: hw: add a helper function to request hwsync without side-effects pcm: hw: add a helper function to issue appl_ptr without side-effects pcm: hw: add a helper function to issue avail_min without side-effects pcm: hw: remove superfluous code to call of SNDRV_PCM_IOCTL_SYNC_PTR in snd_pcm_hw_forward()
src/pcm/pcm_hw.c | 116 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 30 deletions(-)
When executing ioctl(2) with some commands, applications can request ALSA PCM core to change appl_ptr in kernel space. Below is a list of such operations: - SNDRV_PCM_IOCTL_PREPARE - SNDRV_PCM_IOCTL_RESET - SNDRV_PCM_IOCTL_REWIND - SNDRV_PCM_IOCTL_FORWARD - SNDRV_PCM_IOCTL_WRITEI_FRAMES - SNDRV_PCM_IOCTL_WRITEN_FRAMES - SNDRV_PCM_IOCTL_READI_FRAMES - SNDRV_PCM_IOCTL_READN_FRAMES
After these operations, the value of appl_ptr should be synchronized between kernel/user spaces.
This commit adds a helper function to query status and control data without issuing the control data just in fallback from failure of control mapping.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/pcm/pcm_hw.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-)
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index f03bc589..9963523c 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -151,6 +151,20 @@ static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) return 0; }
+static int query_status_and_control_data(snd_pcm_hw_t *hw) +{ + if (!hw->mmap_control_fallbacked) + return 0; + + /* + * Query both of control/status data to avoid unexpected change of + * control data in kernel space. + */ + return sync_ptr1(hw, + SNDRV_PCM_SYNC_PTR_APPL | + SNDRV_PCM_SYNC_PTR_AVAIL_MIN); +} + static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw) { if (hw->period_timer_need_poll) { @@ -601,7 +615,7 @@ static int snd_pcm_hw_prepare(snd_pcm_t *pcm) SYSMSG("SNDRV_PCM_IOCTL_PREPARE failed (%i)", err); return err; } - return sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL); + return query_status_and_control_data(hw); }
static int snd_pcm_hw_reset(snd_pcm_t *pcm) @@ -613,7 +627,7 @@ static int snd_pcm_hw_reset(snd_pcm_t *pcm) SYSMSG("SNDRV_PCM_IOCTL_RESET failed (%i)", err); return err; } - return sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL); + return query_status_and_control_data(hw); }
static int snd_pcm_hw_start(snd_pcm_t *pcm) @@ -688,7 +702,7 @@ static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fra SYSMSG("SNDRV_PCM_IOCTL_REWIND failed (%i)", err); return err; } - err = sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL); + err = query_status_and_control_data(hw); if (err < 0) return err; return frames; @@ -709,7 +723,7 @@ static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t fr SYSMSG("SNDRV_PCM_IOCTL_FORWARD failed (%i)", err); return err; } - err = sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL); + err = query_status_and_control_data(hw); if (err < 0) return err; return frames; @@ -805,8 +819,10 @@ static snd_pcm_sframes_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, s xferi.buf = (char*) buffer; xferi.frames = size; xferi.result = 0; /* make valgrind happy */ - err = ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi); - err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno; + if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi) < 0) + err = -errno; + else + err = query_status_and_control_data(hw); #ifdef DEBUG_RW fprintf(stderr, "hw_writei: frames = %li, xferi.result = %li, err = %i\n", size, xferi.result, err); #endif @@ -824,8 +840,10 @@ static snd_pcm_sframes_t snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_ memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */ xfern.bufs = bufs; xfern.frames = size; - err = ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, &xfern); - err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno; + if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, &xfern) < 0) + err = -errno; + else + err = query_status_and_control_data(hw); #ifdef DEBUG_RW fprintf(stderr, "hw_writen: frames = %li, result = %li, err = %i\n", size, xfern.result, err); #endif @@ -843,8 +861,10 @@ static snd_pcm_sframes_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_ xferi.buf = buffer; xferi.frames = size; xferi.result = 0; /* make valgrind happy */ - err = ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi); - err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno; + if (ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi) < 0) + err = -errno; + else + err = query_status_and_control_data(hw); #ifdef DEBUG_RW fprintf(stderr, "hw_readi: frames = %li, result = %li, err = %i\n", size, xferi.result, err); #endif @@ -862,8 +882,10 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */ xfern.bufs = bufs; xfern.frames = size; - err = ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern); - err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno; + if (ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern) < 0) + err = -errno; + else + err = query_status_and_control_data(hw); #ifdef DEBUG_RW fprintf(stderr, "hw_readn: frames = %li, result = %li, err = %i\n", size, xfern.result, err); #endif
When mapping status data successfully, mapped page includes status data for applications. In this case, applications have no need to call ioctl(2) with SNDRV_PCM_IOCTL_SYNC_PTR. However, in current implementation, when map of control data is unavailable, applications execute the ioctl(2). This is inconvenient for some cases that applications require to query status only.
This commit adds a helper function to query status data without issuing the control in fallback mode from failure of status mmap.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/pcm/pcm_hw.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 9963523c..38d975af 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -165,6 +165,20 @@ static int query_status_and_control_data(snd_pcm_hw_t *hw) SNDRV_PCM_SYNC_PTR_AVAIL_MIN); }
+static int query_status_data(snd_pcm_hw_t *hw) +{ + if (!hw->mmap_status_fallbacked) + return 0; + + /* + * Query both of control/status data to avoid unexpected change of + * control data in kernel space. + */ + return sync_ptr1(hw, + SNDRV_PCM_SYNC_PTR_APPL | + SNDRV_PCM_SYNC_PTR_AVAIL_MIN); +} + static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw) { if (hw->period_timer_need_poll) { @@ -349,7 +363,7 @@ static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) params->info &= ~0xf0000000; if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY) params->info |= SND_PCM_INFO_MONOTONIC; - return sync_ptr(hw, 0); + return query_status_data(hw); }
static void snd_pcm_hw_close_timer(snd_pcm_hw_t *hw) @@ -556,7 +570,7 @@ static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status) static snd_pcm_state_t snd_pcm_hw_state(snd_pcm_t *pcm) { snd_pcm_hw_t *hw = pcm->private_data; - int err = sync_ptr(hw, 0); + int err = query_status_data(hw); if (err < 0) return err; return (snd_pcm_state_t) hw->mmap_status->state; @@ -1064,7 +1078,7 @@ static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm) snd_pcm_hw_t *hw = pcm->private_data; snd_pcm_uframes_t avail;
- sync_ptr(hw, 0); + query_status_data(hw); avail = snd_pcm_mmap_avail(pcm); switch (FAST_PCM_STATE(hw)) { case SNDRV_PCM_STATE_RUNNING:
SNDRV_PCM_IOCTL_SYNC_PTR command for ioctl(2) with SNDRV_PCM_SYNC_PTR_HWSYNC flag has an effect to update hw_ptr. This is an alternative of SNDRV_PCM_IOCTL_HWSYNC but caller can get current status simultaneously.
This commit adds a helper function just to issue hwsync. To avoid side-effect to change appl_ptr and avail_min, this commit uses SNDRV_PCM_SYNC_PTR_APPL and SNDRV_PCM_SYNC_PTR_AVAIL_MIN flags.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/pcm/pcm_hw.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 38d975af..8455baaf 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -151,6 +151,21 @@ static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) return 0; }
+static int request_hwsync(snd_pcm_hw_t *hw) +{ + if (!hw->mmap_status_fallbacked) + return 0; + + /* + * Query both of control/status data to avoid unexpected change of + * control data in kernel space. + */ + return sync_ptr1(hw, + SNDRV_PCM_SYNC_PTR_HWSYNC | + SNDRV_PCM_SYNC_PTR_APPL | + SNDRV_PCM_SYNC_PTR_AVAIL_MIN); +} + static int query_status_and_control_data(snd_pcm_hw_t *hw) { if (!hw->mmap_control_fallbacked) @@ -593,8 +608,8 @@ static int snd_pcm_hw_hwsync(snd_pcm_t *pcm) snd_pcm_hw_t *hw = pcm->private_data; int fd = hw->fd, err; if (SNDRV_PROTOCOL_VERSION(2, 0, 3) <= hw->version) { - if (hw->sync_ptr) { - err = sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_HWSYNC); + if (hw->mmap_status_fallbacked) { + err = request_hwsync(hw); if (err < 0) return err; } else {
After starting, PCM substream shift its state to running and applications can move appl_ptr by several ways. When status and control data of runtime of the PCM substream is not mapped, the applications should issue appl_ptr to kernel land. In this case, when any PCM frames is handled by mmap operation, the applications should issue appl_ptr to update.
This commit adds a helper function for this purpose. To avoid unexpected change of avail_min, this commit uses a flag just to update appl_ptr.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/pcm/pcm_hw.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 8455baaf..51512306 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -151,6 +151,15 @@ static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) return 0; }
+static int issue_applptr(snd_pcm_hw_t *hw) +{ + if (!hw->mmap_control_fallbacked) + return 0; + + /* Avoid unexpected change of avail_min in kernel space. */ + return sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_AVAIL_MIN); +} + static int request_hwsync(snd_pcm_hw_t *hw) { if (!hw->mmap_status_fallbacked) @@ -667,7 +676,7 @@ static int snd_pcm_hw_start(snd_pcm_t *pcm) assert(pcm->stream != SND_PCM_STREAM_PLAYBACK || snd_pcm_mmap_playback_hw_avail(pcm) > 0); #endif - sync_ptr(hw, 0); + issue_applptr(hw); if (ioctl(hw->fd, SNDRV_PCM_IOCTL_START) < 0) { err = -errno; SYSMSG("SNDRV_PCM_IOCTL_START failed (%i)", err); @@ -1081,7 +1090,7 @@ static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm, snd_pcm_hw_t *hw = pcm->private_data;
snd_pcm_mmap_appl_forward(pcm, size); - sync_ptr(hw, 0); + issue_applptr(hw); #ifdef DEBUG_MMAP fprintf(stderr, "appl_forward: hw_ptr = %li, appl_ptr = %li, size = %li\n", *pcm->hw.ptr, *pcm->appl.ptr, size); #endif
At present, applications can change avail_min parameter of PCM substream by two ways; via mapped control data, and by executing ioctl(2) with SNDRV_PCM_IOCTL_SYNC_PTR. The former is available in a case that the applications map the data successfully.
When utilizing alsa-lib API, the above is done by a call of 'snd_pcm_sw_params()' to hw PCM plugin. In current implementation, this call has an side-effect to issue appl_ptr unexpectedly.
This commit adds a helper function to issue avail_min without the side-effect.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/pcm/pcm_hw.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 51512306..9c8fc3f6 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -151,6 +151,15 @@ static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) return 0; }
+static int issue_avail_min(snd_pcm_hw_t *hw) +{ + if (!hw->mmap_control_fallbacked) + return 0; + + /* Avoid unexpected change of applptr in kernel space. */ + return sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_APPL); +} + static int issue_applptr(snd_pcm_hw_t *hw) { if (!hw->mmap_control_fallbacked) @@ -506,7 +515,7 @@ static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) params->silence_size == pcm->silence_size && old_period_event == hw->period_event) { hw->mmap_control->avail_min = params->avail_min; - return sync_ptr(hw, 0); + return issue_avail_min(hw); } if (params->tstamp_type == SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW && hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 12)) {
SNDRV_PCM_IOCTL_SYNC_PTR command was introduced to PCM protocol/interface in its version 2.0.7, however this command is used in a branch for the newer version protocol/interface in snd_pcm_hw_forward().
This commit removes the superfluous code as a part of work for code refactoring.
Fixes: eafb4925124b ("- added SYNC_PTR ioctl support for pcm_hw plugin") Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/pcm/pcm_hw.c | 13 ------------- 1 file changed, 13 deletions(-)
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 9c8fc3f6..16d45e74 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -144,13 +144,6 @@ static int sync_ptr1(snd_pcm_hw_t *hw, unsigned int flags) return 0; }
-static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) -{ - if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked) - return sync_ptr1(hw, flags); - return 0; -} - static int issue_avail_min(snd_pcm_hw_t *hw) { if (!hw->mmap_control_fallbacked) @@ -777,9 +770,6 @@ static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t fr } else { snd_pcm_sframes_t avail;
- err = sync_ptr(hw, SNDRV_PCM_SYNC_PTR_HWSYNC); - if (err < 0) - return err; switch (FAST_PCM_STATE(hw)) { case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_DRAINING: @@ -797,9 +787,6 @@ static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t fr if (frames > (snd_pcm_uframes_t)avail) frames = avail; snd_pcm_mmap_appl_forward(pcm, frames); - err = sync_ptr(hw, 0); - if (err < 0) - return err; return frames; } }
On Fri, 30 Jun 2017 13:37:23 +0200, Takashi Sakamoto wrote:
Hi,
This patchset is a revised version of my previous one:
[PATCH alsa-lib 00/12] pcm: hw: optimization for v2.0.14 of PCM protocol/interface http://mailman.alsa-project.org/pipermail/alsa-devel/2017-June/122392.html
Changes:
- add a helper function, 'query_status_and_control_data()' to update appl_ptr in user space.
- rename 'query_state()' to 'query_status_data()'
- reduce two patches.
- aggregate some patches for querying control data.
I did quick mesurement by execute aplay on x86 machine with.
- With Intel HDA driver with usual configuration.
poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}]) ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0) = 0 read(3, "a\23IH\205\177z\257\276]\346\237\313\220L\5\337V\363\351\216\17\346s\22\245-yb\312\37D"..., 16384) = 16384 ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0) = 0 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
- With Intel HDA driver with 'sync_ptr_ioctl' option to hw PCM plugin.
poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}]) ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 read(3, "Rz\vB\v|A\275\356`\201)\335i3\r}\21Q^\30\324'\r'\375l\235&\3330\2"..., 16384) = 16384 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55fe03539f80) = 0 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
- With Fireworks driver with a patch for snd-firewire-lib to add SNDRV_PCM_INFO_SYNC_APPLPTR support[1].
poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}]) ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0) = 0 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x55b647ec9c00) = 0 read(3, "|\n*\336\322\252*&\377\312\372&\276\333.\207\21\343\362\3\5\363\201\266\3421lZ;\\\22*"..., 24576) = 24576 ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0) = 0 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
We can see this optimization reduces some ioctl calls in case 3. This is due to status data mapping.
[1] Below. diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index f8c2765..04fb3df 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -160,7 +160,8 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID;
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_SYNC_APPLPTR; /* SNDRV_PCM_INFO_BATCH */ hw->periods_min = 2;
Takashi Sakamoto (6): pcm: hw: add a helper function to query status/control data pcm: hw: add a helper function just to query status data pcm: hw: add a helper function to request hwsync without side-effects pcm: hw: add a helper function to issue appl_ptr without side-effects pcm: hw: add a helper function to issue avail_min without side-effects pcm: hw: remove superfluous code to call of SNDRV_PCM_IOCTL_SYNC_PTR in snd_pcm_hw_forward()
Applied all 6 patches now. Thanks.
Takashi
participants (2)
-
Takashi Iwai
-
Takashi Sakamoto