[alsa-devel] [PATCH 0/6] ALSA: firewire-lib: split allocation of isochronous resources from establishment of connection
Hi,
This patchset is a part of patches to reserve/release isochronous resources in pcm.hw_params/hw_free callbacks, like posted patchsets below: https://mailman.alsa-project.org/pipermail/alsa-devel/2019-June/150118.html https://mailman.alsa-project.org/pipermail/alsa-devel/2019-June/150863.html
In IEC 61883-1/6, CMP is depicted with operations of isochronous resources. The ALSA firewire-lib module implements some kernel API for CMP according to it. However, once the isochronous resources are allocated, several packet streaming can run consecutively. Deallocation of isochronous resources for each of packet streaming is not needless.
In this patchset, allocation of isochronous resources is split from establishment of connection so that CMP runs with allocated isochronous resources.
Takashi Sakamoto (6): ALSA: bebob: code rafactoring for callback functions to PCM interface ALSA: bebob: code refactoring for callback function to rawmidi interface ALSA: bebob: change the range of critical section for stream data in PCM.hw_free callback ALSA: bebob: code refactoring for error path to start duplex stream ALSA: fireworks: change the range of critical section for stream data in PCM.hw_free callback ALSA: firewire-lib: split allocation of isochronous resources from establishment of connection
sound/firewire/bebob/bebob_midi.c | 47 ++----------- sound/firewire/bebob/bebob_pcm.c | 62 +++-------------- sound/firewire/bebob/bebob_stream.c | 32 ++++++--- sound/firewire/cmp.c | 74 ++++++++++++--------- sound/firewire/cmp.h | 7 +- sound/firewire/fireworks/fireworks_pcm.c | 9 +-- sound/firewire/fireworks/fireworks_stream.c | 22 ++++-- sound/firewire/oxfw/oxfw-stream.c | 18 +++-- 8 files changed, 122 insertions(+), 149 deletions(-)
The pairs of pcm.hw_params callback functions and .hw_free callback functions for both direction have no differences.
This commit unifies the pairs.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_pcm.c | 55 ++++---------------------------- 1 file changed, 7 insertions(+), 48 deletions(-)
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 71b6ede31bb2..530db7a7844c 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -185,33 +185,8 @@ pcm_close(struct snd_pcm_substream *substream) return 0; }
-static int -pcm_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_bebob *bebob = substream->private_data; - int err; - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { - unsigned int rate = params_rate(hw_params); - - mutex_lock(&bebob->mutex); - err = snd_bebob_stream_reserve_duplex(bebob, rate); - if (err >= 0) - ++bebob->substreams_counter; - mutex_unlock(&bebob->mutex); - } - - return err; -} -static int -pcm_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) +static int pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { struct snd_bebob *bebob = substream->private_data; int err; @@ -234,23 +209,7 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream, return err; }
-static int -pcm_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_bebob *bebob = substream->private_data; - - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { - mutex_lock(&bebob->mutex); - bebob->substreams_counter--; - mutex_unlock(&bebob->mutex); - } - - snd_bebob_stream_stop_duplex(bebob); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} -static int -pcm_playback_hw_free(struct snd_pcm_substream *substream) +static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data;
@@ -360,8 +319,8 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_capture_hw_params, - .hw_free = pcm_capture_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, @@ -372,8 +331,8 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_playback_hw_params, - .hw_free = pcm_playback_hw_free, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer,
The pairs of rawmidi.hw_params callback functions and .hw_free callback functions for both direction have no differences.
This commit unifies the pairs.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_midi.c | 47 ++++--------------------------- 1 file changed, 6 insertions(+), 41 deletions(-)
diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index e2d3cad39d28..f7db1f7bce86 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c @@ -8,7 +8,7 @@
#include "bebob.h"
-static int midi_capture_open(struct snd_rawmidi_substream *substream) +static int midi_open(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data; int err; @@ -30,42 +30,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) return err; }
-static int midi_playback_open(struct snd_rawmidi_substream *substream) -{ - struct snd_bebob *bebob = substream->rmidi->private_data; - int err; - - err = snd_bebob_stream_lock_try(bebob); - if (err < 0) - return err; - - mutex_lock(&bebob->mutex); - err = snd_bebob_stream_reserve_duplex(bebob, 0); - if (err >= 0) { - ++bebob->substreams_counter; - err = snd_bebob_stream_start_duplex(bebob); - } - mutex_unlock(&bebob->mutex); - if (err < 0) - snd_bebob_stream_lock_release(bebob); - - return err; -} - -static int midi_capture_close(struct snd_rawmidi_substream *substream) -{ - struct snd_bebob *bebob = substream->rmidi->private_data; - - mutex_lock(&bebob->mutex); - bebob->substreams_counter--; - snd_bebob_stream_stop_duplex(bebob); - mutex_unlock(&bebob->mutex); - - snd_bebob_stream_lock_release(bebob); - return 0; -} - -static int midi_playback_close(struct snd_rawmidi_substream *substream) +static int midi_close(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data;
@@ -127,13 +92,13 @@ static void set_midi_substream_names(struct snd_bebob *bebob, int snd_bebob_create_midi_devices(struct snd_bebob *bebob) { static const struct snd_rawmidi_ops capture_ops = { - .open = midi_capture_open, - .close = midi_capture_close, + .open = midi_open, + .close = midi_close, .trigger = midi_capture_trigger, }; static const struct snd_rawmidi_ops playback_ops = { - .open = midi_playback_open, - .close = midi_playback_close, + .open = midi_open, + .close = midi_close, .trigger = midi_playback_trigger, }; struct snd_rawmidi *rmidi;
The operation of duplex streams should be in critical section.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_pcm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 530db7a7844c..e21de44deaa9 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -213,14 +213,15 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data;
- if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { - mutex_lock(&bebob->mutex); + mutex_lock(&bebob->mutex); + + if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) bebob->substreams_counter--; - mutex_unlock(&bebob->mutex); - }
snd_bebob_stream_stop_duplex(bebob);
+ mutex_unlock(&bebob->mutex); + return snd_pcm_lib_free_vmalloc_buffer(substream); }
This commit removes useless procedures to stop packet streaming.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_stream.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 6aab3dc99bef..9ef4663d13e5 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -650,8 +650,6 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob)
if (!amdtp_stream_wait_callback(&bebob->rx_stream, CALLBACK_TIMEOUT)) { - amdtp_stream_stop(&bebob->rx_stream); - break_both_connections(bebob); err = -ETIMEDOUT; goto error; }
The operation of duplex streams should be in critical section.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/fireworks/fireworks_pcm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index 287fc05d5917..8dc34249a1b0 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -247,14 +247,15 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data;
- if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { - mutex_lock(&efw->mutex); + mutex_lock(&efw->mutex); + + if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) --efw->substreams_counter; - mutex_unlock(&efw->mutex); - }
snd_efw_stream_stop_duplex(efw);
+ mutex_unlock(&efw->mutex); + return snd_pcm_lib_free_vmalloc_buffer(substream); }
In current implementation, establishment connection corresponds to allocation of isochronous resources. Although this is an ideal implementation of CMP described in IEC 61883-1, it's not enough efficient to recover PCM substream multiplexed in packet streaming. The packet streaming can always restart on the same allocated isochronous resources even if the previous packet streaming corrupted.
This commit splits allocation of isochronous resources from establishment of connection so that CMP runs with allocated isochronous resources.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_stream.c | 30 ++++++--- sound/firewire/cmp.c | 74 ++++++++++++--------- sound/firewire/cmp.h | 7 +- sound/firewire/fireworks/fireworks_stream.c | 22 ++++-- sound/firewire/oxfw/oxfw-stream.c | 18 +++-- 5 files changed, 100 insertions(+), 51 deletions(-)
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 9ef4663d13e5..1070a675179d 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -404,13 +404,11 @@ static int make_both_connections(struct snd_bebob *bebob) { int err = 0;
- err = cmp_connection_establish(&bebob->out_conn, - amdtp_stream_get_max_payload(&bebob->tx_stream)); + err = cmp_connection_establish(&bebob->out_conn); if (err < 0) return err;
- err = cmp_connection_establish(&bebob->in_conn, - amdtp_stream_get_max_payload(&bebob->rx_stream)); + err = cmp_connection_establish(&bebob->in_conn); if (err < 0) { cmp_connection_break(&bebob->out_conn); return err; @@ -533,14 +531,23 @@ static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, unsigned int rate, unsigned int index) { struct snd_bebob_stream_formation *formation; + struct cmp_connection *conn; + int err;
- if (stream == &bebob->tx_stream) + if (stream == &bebob->tx_stream) { formation = bebob->tx_stream_formations + index; - else + conn = &bebob->out_conn; + } else { formation = bebob->rx_stream_formations + index; + conn = &bebob->in_conn; + } + + err = amdtp_am824_set_parameters(stream, rate, formation->pcm, + formation->midi, false); + if (err < 0) + return err;
- return amdtp_am824_set_parameters(stream, rate, formation->pcm, - formation->midi, false); + return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); }
int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) @@ -591,8 +598,10 @@ int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) return err;
err = keep_resources(bebob, &bebob->rx_stream, rate, index); - if (err < 0) + if (err < 0) { + cmp_connection_release(&bebob->out_conn); return err; + } }
return 0; @@ -685,6 +694,9 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) amdtp_stream_stop(&bebob->tx_stream);
break_both_connections(bebob); + + cmp_connection_release(&bebob->out_conn); + cmp_connection_release(&bebob->in_conn); } }
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index ae3bc1940efa..5dedc4f31842 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c @@ -185,6 +185,37 @@ void cmp_connection_destroy(struct cmp_connection *c) } EXPORT_SYMBOL(cmp_connection_destroy);
+int cmp_connection_reserve(struct cmp_connection *c, + unsigned int max_payload_bytes) +{ + int err; + + mutex_lock(&c->mutex); + + if (WARN_ON(c->resources.allocated)) { + err = -EBUSY; + goto end; + } + + c->speed = min(c->max_speed, + fw_parent_device(c->resources.unit)->max_speed); + + err = fw_iso_resources_allocate(&c->resources, max_payload_bytes, + c->speed); +end: + mutex_unlock(&c->mutex); + + return err; +} +EXPORT_SYMBOL(cmp_connection_reserve); + +void cmp_connection_release(struct cmp_connection *c) +{ + mutex_lock(&c->mutex); + fw_iso_resources_free(&c->resources); + mutex_unlock(&c->mutex); +} +EXPORT_SYMBOL(cmp_connection_release);
static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) { @@ -270,25 +301,18 @@ static int pcr_set_check(struct cmp_connection *c, __be32 pcr) * When this function succeeds, the caller is responsible for starting * transmitting packets. */ -int cmp_connection_establish(struct cmp_connection *c, - unsigned int max_payload_bytes) +int cmp_connection_establish(struct cmp_connection *c) { int err;
- if (WARN_ON(c->connected)) - return -EISCONN; - - c->speed = min(c->max_speed, - fw_parent_device(c->resources.unit)->max_speed); - mutex_lock(&c->mutex);
-retry_after_bus_reset: - err = fw_iso_resources_allocate(&c->resources, - max_payload_bytes, c->speed); - if (err < 0) - goto err_mutex; + if (WARN_ON(c->connected)) { + mutex_unlock(&c->mutex); + return -EISCONN; + }
+retry_after_bus_reset: if (c->direction == CMP_OUTPUT) err = pcr_modify(c, opcr_set_modify, pcr_set_check, ABORT_ON_BUS_RESET); @@ -297,21 +321,13 @@ int cmp_connection_establish(struct cmp_connection *c, ABORT_ON_BUS_RESET);
if (err == -EAGAIN) { - fw_iso_resources_free(&c->resources); - goto retry_after_bus_reset; + err = fw_iso_resources_update(&c->resources); + if (err >= 0) + goto retry_after_bus_reset; } - if (err < 0) - goto err_resources; - - c->connected = true; - - mutex_unlock(&c->mutex); - - return 0; + if (err >= 0) + c->connected = true;
-err_resources: - fw_iso_resources_free(&c->resources); -err_mutex: mutex_unlock(&c->mutex);
return err; @@ -351,14 +367,12 @@ int cmp_connection_update(struct cmp_connection *c) SUCCEED_ON_BUS_RESET);
if (err < 0) - goto err_resources; + goto err_unconnect;
mutex_unlock(&c->mutex);
return 0;
-err_resources: - fw_iso_resources_free(&c->resources); err_unconnect: c->connected = false; mutex_unlock(&c->mutex); @@ -395,8 +409,6 @@ void cmp_connection_break(struct cmp_connection *c) if (err < 0) cmp_error(c, "plug is still connected\n");
- fw_iso_resources_free(&c->resources); - c->connected = false;
mutex_unlock(&c->mutex); diff --git a/sound/firewire/cmp.h b/sound/firewire/cmp.h index b60b415caa8f..26ab88000e34 100644 --- a/sound/firewire/cmp.h +++ b/sound/firewire/cmp.h @@ -42,8 +42,11 @@ int cmp_connection_init(struct cmp_connection *connection, int cmp_connection_check_used(struct cmp_connection *connection, bool *used); void cmp_connection_destroy(struct cmp_connection *connection);
-int cmp_connection_establish(struct cmp_connection *connection, - unsigned int max_payload); +int cmp_connection_reserve(struct cmp_connection *connection, + unsigned int max_payload); +void cmp_connection_release(struct cmp_connection *connection); + +int cmp_connection_establish(struct cmp_connection *connection); int cmp_connection_update(struct cmp_connection *connection); void cmp_connection_break(struct cmp_connection *connection);
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 61342c49dc38..81c1bb209a89 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -63,8 +63,7 @@ static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, conn = &efw->in_conn;
// Establish connection via CMP. - err = cmp_connection_establish(conn, - amdtp_stream_get_max_payload(stream)); + err = cmp_connection_establish(conn); if (err < 0) return err;
@@ -177,17 +176,25 @@ static int keep_resources(struct snd_efw *efw, struct amdtp_stream *stream, { unsigned int pcm_channels; unsigned int midi_ports; + struct cmp_connection *conn; + int err;
if (stream == &efw->tx_stream) { pcm_channels = efw->pcm_capture_channels[mode]; midi_ports = efw->midi_out_ports; + conn = &efw->out_conn; } else { pcm_channels = efw->pcm_playback_channels[mode]; midi_ports = efw->midi_in_ports; + conn = &efw->in_conn; }
- return amdtp_am824_set_parameters(stream, rate, pcm_channels, - midi_ports, false); + err = amdtp_am824_set_parameters(stream, rate, pcm_channels, + midi_ports, false); + if (err < 0) + return err; + + return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); }
int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) @@ -228,8 +235,10 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) return err;
err = keep_resources(efw, &efw->rx_stream, rate, mode); - if (err < 0) + if (err < 0) { + cmp_connection_release(&efw->in_conn); return err; + } }
return 0; @@ -285,6 +294,9 @@ void snd_efw_stream_stop_duplex(struct snd_efw *efw) if (efw->substreams_counter == 0) { stop_stream(efw, &efw->tx_stream); stop_stream(efw, &efw->rx_stream); + + cmp_connection_release(&efw->out_conn); + cmp_connection_release(&efw->in_conn); } }
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 837733f10736..a8bc798731ff 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -111,8 +111,7 @@ static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) else conn = &oxfw->out_conn;
- err = cmp_connection_establish(conn, - amdtp_stream_get_max_payload(stream)); + err = cmp_connection_establish(conn); if (err < 0) return err;
@@ -203,15 +202,18 @@ static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream) enum avc_general_plug_dir dir; u8 **formats; struct snd_oxfw_stream_formation formation; + struct cmp_connection *conn; int i; int err;
if (stream == &oxfw->rx_stream) { dir = AVC_GENERAL_PLUG_DIR_IN; formats = oxfw->rx_stream_formats; + conn = &oxfw->in_conn; } else { dir = AVC_GENERAL_PLUG_DIR_OUT; formats = oxfw->tx_stream_formats; + conn = &oxfw->out_conn; }
err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); @@ -239,8 +241,12 @@ static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream) if (formation.pcm == 0) return -EINVAL;
- return amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, + err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, formation.midi * 8, false); + if (err < 0) + return err; + + return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); }
int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, @@ -299,8 +305,10 @@ int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
if (oxfw->has_output) { err = keep_resources(oxfw, &oxfw->tx_stream); - if (err < 0) + if (err < 0) { + cmp_connection_release(&oxfw->in_conn); return err; + } } }
@@ -361,10 +369,12 @@ void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw) if (oxfw->substreams_count == 0) { amdtp_stream_stop(&oxfw->rx_stream); cmp_connection_break(&oxfw->in_conn); + cmp_connection_release(&oxfw->in_conn);
if (oxfw->has_output) { amdtp_stream_stop(&oxfw->tx_stream); cmp_connection_break(&oxfw->out_conn); + cmp_connection_release(&oxfw->out_conn); } } }
On Sat, 15 Jun 2019 11:10:55 +0200, Takashi Sakamoto wrote:
Hi,
This patchset is a part of patches to reserve/release isochronous resources in pcm.hw_params/hw_free callbacks, like posted patchsets below: https://mailman.alsa-project.org/pipermail/alsa-devel/2019-June/150118.html https://mailman.alsa-project.org/pipermail/alsa-devel/2019-June/150863.html
In IEC 61883-1/6, CMP is depicted with operations of isochronous resources. The ALSA firewire-lib module implements some kernel API for CMP according to it. However, once the isochronous resources are allocated, several packet streaming can run consecutively. Deallocation of isochronous resources for each of packet streaming is not needless.
In this patchset, allocation of isochronous resources is split from establishment of connection so that CMP runs with allocated isochronous resources.
Takashi Sakamoto (6): ALSA: bebob: code rafactoring for callback functions to PCM interface ALSA: bebob: code refactoring for callback function to rawmidi interface ALSA: bebob: change the range of critical section for stream data in PCM.hw_free callback ALSA: bebob: code refactoring for error path to start duplex stream ALSA: fireworks: change the range of critical section for stream data in PCM.hw_free callback ALSA: firewire-lib: split allocation of isochronous resources from establishment of connection
Applied now. Thanks.
Takashi
participants (2)
-
Takashi Iwai
-
Takashi Sakamoto