[alsa-devel] [PATCH 0/4] ALSA: bebob: give up updating streams at bus reset
Hi,
This patchset is to simplify codes of ALSA bebob driver by giving up updating streams at bus reset.
DM1000/DM1100/DM1500 chipsets have a quirk to transfer packets with discontinuous value in 'dbc' field of CIP header. This is against packet streaming protocol (IEC 61883-1/6).
In the specification, units should continue packet streaming during 1 seconds after bus reset. During this period, connections are updated. Else, the streaming stops.
The discontinuity causes firewire-lib module (packet streaming layer) to stop streaming immediately. This is done far earlier than executing bus-reset handler. Therefore, updating streams at the bus-reset handler has no meaning.
This patchset will have little impacts for userspace applications because most users won't update IEEE 1394 bus when playbacking/recording. And PCM substream recovery is still available.
Regards
Takashi Sakamoto (4): ALSA: bebob: simplify bus-reset handling ALSA: bebob: move mutex from function callee to callers ALSA: bebob: change type of substream counter from atomic_t to unsigned int ALSA: bebob: give up updating streams at bus reset handler
sound/firewire/bebob/bebob.c | 21 ++++++++++---- sound/firewire/bebob/bebob.h | 5 +--- sound/firewire/bebob/bebob_midi.c | 16 +++++++--- sound/firewire/bebob/bebob_pcm.c | 28 +++++++++++++----- sound/firewire/bebob/bebob_stream.c | 58 +++---------------------------------- 5 files changed, 53 insertions(+), 75 deletions(-)
At bus-reset, DM1000/DM1100/DM1500 chipsets transfer packets with discontinuous value in 'dbc' field of CIP header. In this case, packet streaming layer in firewire-lib module stops streaming and set XRUN to PCM substream.
In ALSA, PCM applications are notified the XRUN status by the return value of ALSA PCM interface. They can recover this state by executing snd_pcm_prepare(), then PCM drivers' prepare handler is called, and start new PCM substream. For ALSA BeBoB driver, the handler establishes new connections and start new AMDTP streaming.
Unfortunately, neither the PCM applications nor the driver know the reason of XRUN. The driver gets to know the reason when update handler is called by IEEE 1394 bus driver. As long as I tested, the order of below events are not fixed: * Detecting packet discontinuity in tasklet context of OHCI 1394 driver * Calling prepare handler in process context of ALSA PCM application * Calling update handler in kthread context of IEEE 1394 bus driver
The unpredictable order is disadvantage for the driver to be compliant to CMP. In IEC 61883-1, new CMP establish operations should be done 1 sec (isoc_resource_delay) after bus-reset. Within 1 sec, CMP restore operations are allowed. For this reason, in former commit ('b6bc812327aa: ALSA: bebob/firewire-lib: Add a quirk for discontinuity at bus reset'), the process context is forced to wait for executing update handler. The process context wait for bus-reset up to 1 sec. This commit solves the issue, while causes more disadvantages. For PCM applications, calling snd_pcm_prepare() for recovering XRUN state takes more time and the driver got a bit complicated code, while the recovery is not always successful.
As long as I tested, DM1000/DM1100/DM1500 and BeBoB firmware can allow drivers to establish new connections just after bus reset. Furthermore, any FCP transactions are handled correctly. Therefore, the driver don't need to wait for bus reset handler for starting new streaming.
This commit removes the codes to reduce maintenance cost.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob.c | 7 +++---- sound/firewire/bebob/bebob.h | 2 -- sound/firewire/bebob/bebob_stream.c | 32 ++------------------------------ 3 files changed, 5 insertions(+), 36 deletions(-)
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 091290d..671179e 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -309,7 +309,10 @@ bebob_update(struct fw_unit *unit) return;
fcp_bus_reset(bebob->unit); + + mutex_lock(&bebob->mutex); snd_bebob_stream_update_duplex(bebob); + mutex_unlock(&bebob->mutex);
if (bebob->deferred_registration) { if (snd_card_register(bebob->card) < 0) { @@ -327,10 +330,6 @@ static void bebob_remove(struct fw_unit *unit) if (bebob == NULL) return;
- /* Awake bus-reset waiters. */ - if (!completion_done(&bebob->bus_reset)) - complete_all(&bebob->bus_reset); - /* No need to wait for releasing card object in this context. */ snd_card_free_when_closed(bebob->card); } diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 4d8fcc7..c2e885c 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -88,8 +88,6 @@ struct snd_bebob { unsigned int midi_input_ports; unsigned int midi_output_ports;
- /* for bus reset quirk */ - struct completion bus_reset; bool connected;
struct amdtp_stream *master; diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 5022c9b..073ad6d 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -549,8 +549,7 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) destroy_both_connections(bebob); goto end; } - /* See comments in next function */ - init_completion(&bebob->bus_reset); + bebob->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK;
/* @@ -588,25 +587,8 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) struct amdtp_stream *master, *slave; enum cip_flags sync_mode; unsigned int curr_rate; - bool updated = false; int err = 0;
- /* - * Normal BeBoB firmware has a quirk at bus reset to transmits packets - * with discontinuous value in dbc field. - * - * This 'struct completion' is used to call .update() at first to update - * connections/streams. Next following codes handle streaming error. - */ - if (amdtp_streaming_error(&bebob->tx_stream)) { - if (completion_done(&bebob->bus_reset)) - reinit_completion(&bebob->bus_reset); - - updated = (wait_for_completion_interruptible_timeout( - &bebob->bus_reset, - msecs_to_jiffies(FW_ISO_RESOURCE_DELAY)) > 0); - } - mutex_lock(&bebob->mutex);
/* Need no substreams */ @@ -642,8 +624,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) amdtp_stream_stop(master); if (amdtp_streaming_error(slave)) amdtp_stream_stop(slave); - if (!updated && - !amdtp_stream_running(master) && !amdtp_stream_running(slave)) + if (!amdtp_stream_running(master) && !amdtp_stream_running(slave)) break_both_connections(bebob);
/* stop streams if rate is different */ @@ -774,9 +755,6 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob)
void snd_bebob_stream_update_duplex(struct snd_bebob *bebob) { - /* vs. XRUN recovery due to discontinuity at bus reset */ - mutex_lock(&bebob->mutex); - if ((cmp_connection_update(&bebob->in_conn) < 0) || (cmp_connection_update(&bebob->out_conn) < 0)) { amdtp_stream_pcm_abort(&bebob->rx_stream); @@ -788,12 +766,6 @@ void snd_bebob_stream_update_duplex(struct snd_bebob *bebob) amdtp_stream_update(&bebob->rx_stream); amdtp_stream_update(&bebob->tx_stream); } - - /* wake up stream_start_duplex() */ - if (!completion_done(&bebob->bus_reset)) - complete_all(&bebob->bus_reset); - - mutex_unlock(&bebob->mutex); }
/*
Currently, critical section is protected by mutex in functions of fireworks_stream.c. Callers increments/decrements substreams counter before calling the functions. Moving mutex to the callers code allows to change type of the substream counter from atomic_t to unsigned int.
This commit is a preparation for obsoleting usage of atomic_t for substream counter.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_midi.c | 8 ++++++++ sound/firewire/bebob/bebob_pcm.c | 20 ++++++++++++++++---- sound/firewire/bebob/bebob_stream.c | 7 ------- 3 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index 90d95be..cb1b385 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c @@ -17,8 +17,10 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) if (err < 0) goto end;
+ mutex_lock(&bebob->mutex); atomic_inc(&bebob->substreams_counter); err = snd_bebob_stream_start_duplex(bebob, 0); + mutex_unlock(&bebob->mutex); if (err < 0) snd_bebob_stream_lock_release(bebob); end: @@ -34,8 +36,10 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) if (err < 0) goto end;
+ mutex_lock(&bebob->mutex); atomic_inc(&bebob->substreams_counter); err = snd_bebob_stream_start_duplex(bebob, 0); + mutex_unlock(&bebob->mutex); if (err < 0) snd_bebob_stream_lock_release(bebob); end: @@ -46,8 +50,10 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data;
+ mutex_lock(&bebob->mutex); atomic_dec(&bebob->substreams_counter); snd_bebob_stream_stop_duplex(bebob); + mutex_unlock(&bebob->mutex);
snd_bebob_stream_lock_release(bebob); return 0; @@ -57,8 +63,10 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) { struct snd_bebob *bebob = substream->rmidi->private_data;
+ mutex_lock(&bebob->mutex); atomic_dec(&bebob->substreams_counter); snd_bebob_stream_stop_duplex(bebob); + mutex_unlock(&bebob->mutex);
snd_bebob_stream_lock_release(bebob); return 0; diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index ef224d6..2053d31 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -218,8 +218,11 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream, if (err < 0) return err;
- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + mutex_lock(&bebob->mutex); atomic_inc(&bebob->substreams_counter); + mutex_unlock(&bebob->mutex); + }
amdtp_am824_set_pcm_format(&bebob->tx_stream, params_format(hw_params));
@@ -237,8 +240,11 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream, if (err < 0) return err;
- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + mutex_lock(&bebob->mutex); atomic_inc(&bebob->substreams_counter); + mutex_unlock(&bebob->mutex); + }
amdtp_am824_set_pcm_format(&bebob->rx_stream, params_format(hw_params));
@@ -250,8 +256,11 @@ 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) + if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { + mutex_lock(&bebob->mutex); atomic_dec(&bebob->substreams_counter); + mutex_unlock(&bebob->mutex); + }
snd_bebob_stream_stop_duplex(bebob);
@@ -262,8 +271,11 @@ pcm_playback_hw_free(struct snd_pcm_substream *substream) { struct snd_bebob *bebob = substream->private_data;
- if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { + mutex_lock(&bebob->mutex); atomic_dec(&bebob->substreams_counter); + mutex_unlock(&bebob->mutex); + }
snd_bebob_stream_stop_duplex(bebob);
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 073ad6d..6809913 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -589,8 +589,6 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) unsigned int curr_rate; int err = 0;
- mutex_lock(&bebob->mutex); - /* Need no substreams */ if (atomic_read(&bebob->substreams_counter) == 0) goto end; @@ -722,7 +720,6 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) } } end: - mutex_unlock(&bebob->mutex); return err; }
@@ -738,8 +735,6 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) master = &bebob->tx_stream; }
- mutex_lock(&bebob->mutex); - if (atomic_read(&bebob->substreams_counter) == 0) { amdtp_stream_pcm_abort(master); amdtp_stream_stop(master); @@ -749,8 +744,6 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob)
break_both_connections(bebob); } - - mutex_unlock(&bebob->mutex); }
void snd_bebob_stream_update_duplex(struct snd_bebob *bebob)
The counter is incremented/decremented in critical section protected with mutex. Therefore, no need to use atomic_t.
This commit changes the type to unsigned int.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob.h | 2 +- sound/firewire/bebob/bebob_midi.c | 8 ++++---- sound/firewire/bebob/bebob_pcm.c | 8 ++++---- sound/firewire/bebob/bebob_stream.c | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index c2e885c..4fe58e4 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -95,7 +95,7 @@ struct snd_bebob { struct amdtp_stream rx_stream; struct cmp_connection out_conn; struct cmp_connection in_conn; - atomic_t substreams_counter; + unsigned int substreams_counter;
struct snd_bebob_stream_formation tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES]; diff --git a/sound/firewire/bebob/bebob_midi.c b/sound/firewire/bebob/bebob_midi.c index cb1b385..868eb0d 100644 --- a/sound/firewire/bebob/bebob_midi.c +++ b/sound/firewire/bebob/bebob_midi.c @@ -18,7 +18,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) goto end;
mutex_lock(&bebob->mutex); - atomic_inc(&bebob->substreams_counter); + bebob->substreams_counter++; err = snd_bebob_stream_start_duplex(bebob, 0); mutex_unlock(&bebob->mutex); if (err < 0) @@ -37,7 +37,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) goto end;
mutex_lock(&bebob->mutex); - atomic_inc(&bebob->substreams_counter); + bebob->substreams_counter++; err = snd_bebob_stream_start_duplex(bebob, 0); mutex_unlock(&bebob->mutex); if (err < 0) @@ -51,7 +51,7 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) struct snd_bebob *bebob = substream->rmidi->private_data;
mutex_lock(&bebob->mutex); - atomic_dec(&bebob->substreams_counter); + bebob->substreams_counter--; snd_bebob_stream_stop_duplex(bebob); mutex_unlock(&bebob->mutex);
@@ -64,7 +64,7 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) struct snd_bebob *bebob = substream->rmidi->private_data;
mutex_lock(&bebob->mutex); - atomic_dec(&bebob->substreams_counter); + bebob->substreams_counter--; snd_bebob_stream_stop_duplex(bebob); mutex_unlock(&bebob->mutex);
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 2053d31..5d7b934 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -220,7 +220,7 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream,
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&bebob->mutex); - atomic_inc(&bebob->substreams_counter); + bebob->substreams_counter++; mutex_unlock(&bebob->mutex); }
@@ -242,7 +242,7 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream,
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&bebob->mutex); - atomic_inc(&bebob->substreams_counter); + bebob->substreams_counter++; mutex_unlock(&bebob->mutex); }
@@ -258,7 +258,7 @@ pcm_capture_hw_free(struct snd_pcm_substream *substream)
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { mutex_lock(&bebob->mutex); - atomic_dec(&bebob->substreams_counter); + bebob->substreams_counter--; mutex_unlock(&bebob->mutex); }
@@ -273,7 +273,7 @@ pcm_playback_hw_free(struct snd_pcm_substream *substream)
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { mutex_lock(&bebob->mutex); - atomic_dec(&bebob->substreams_counter); + bebob->substreams_counter--; mutex_unlock(&bebob->mutex); }
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 6809913..8c68745 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -590,7 +590,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate) int err = 0;
/* Need no substreams */ - if (atomic_read(&bebob->substreams_counter) == 0) + if (bebob->substreams_counter == 0) goto end;
err = get_sync_mode(bebob, &sync_mode); @@ -735,7 +735,7 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) master = &bebob->tx_stream; }
- if (atomic_read(&bebob->substreams_counter) == 0) { + if (bebob->substreams_counter == 0) { amdtp_stream_pcm_abort(master); amdtp_stream_stop(master);
DM1000/DM1100/DM1500 chipsets transfer packets with discontinue value in 'dbc' field of CIP header. For ALSA bebob driver, this makes its bus-reset handler meaningless, because the discontinuity is detected quite earlier than executing the handler.
This commit gives up updating streams at the bus reset handler.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob.c | 20 ++++++++++++++++---- sound/firewire/bebob/bebob.h | 1 - sound/firewire/bebob/bebob_stream.c | 15 --------------- 3 files changed, 16 insertions(+), 20 deletions(-)
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 671179e..3e4e075 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -300,6 +300,22 @@ error: return err; }
+/* + * This driver doesn't update streams in bus reset handler. + * + * DM1000/ DM1100/DM1500 chipsets with BeBoB firmware transfer packets with + * discontinued counter at bus reset. This discontinuity is immediately + * detected in packet streaming layer, then it sets XRUN to PCM substream. + * + * ALSA PCM applications can know the XRUN by getting -EPIPE from PCM operation. + * Then, they can recover the PCM substream by executing ioctl(2) with + * SNDRV_PCM_IOCTL_PREPARE. 'struct snd_pcm_ops.prepare' is called and drivers + * restart packet streaming. + * + * The above processing may be executed before this bus-reset handler is + * executed. When this handler updates streams with current isochronous + * channels, the streams already have the current ones. + */ static void bebob_update(struct fw_unit *unit) { @@ -310,10 +326,6 @@ bebob_update(struct fw_unit *unit)
fcp_bus_reset(bebob->unit);
- mutex_lock(&bebob->mutex); - snd_bebob_stream_update_duplex(bebob); - mutex_unlock(&bebob->mutex); - if (bebob->deferred_registration) { if (snd_card_register(bebob->card) < 0) { snd_bebob_stream_destroy_duplex(bebob); diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 4fe58e4..b50bb33d 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -217,7 +217,6 @@ int snd_bebob_stream_discover(struct snd_bebob *bebob); int snd_bebob_stream_init_duplex(struct snd_bebob *bebob); int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, unsigned int rate); void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob); -void snd_bebob_stream_update_duplex(struct snd_bebob *bebob); void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob);
void snd_bebob_stream_lock_changed(struct snd_bebob *bebob); diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 8c68745..77cbb02 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -746,21 +746,6 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) } }
-void snd_bebob_stream_update_duplex(struct snd_bebob *bebob) -{ - if ((cmp_connection_update(&bebob->in_conn) < 0) || - (cmp_connection_update(&bebob->out_conn) < 0)) { - amdtp_stream_pcm_abort(&bebob->rx_stream); - amdtp_stream_pcm_abort(&bebob->tx_stream); - amdtp_stream_stop(&bebob->rx_stream); - amdtp_stream_stop(&bebob->tx_stream); - break_both_connections(bebob); - } else { - amdtp_stream_update(&bebob->rx_stream); - amdtp_stream_update(&bebob->tx_stream); - } -} - /* * This function should be called before starting streams or after stopping * streams.
On Sat, 20 Feb 2016 08:18:55 +0100, Takashi Sakamoto wrote:
Hi,
This patchset is to simplify codes of ALSA bebob driver by giving up updating streams at bus reset.
DM1000/DM1100/DM1500 chipsets have a quirk to transfer packets with discontinuous value in 'dbc' field of CIP header. This is against packet streaming protocol (IEC 61883-1/6).
In the specification, units should continue packet streaming during 1 seconds after bus reset. During this period, connections are updated. Else, the streaming stops.
The discontinuity causes firewire-lib module (packet streaming layer) to stop streaming immediately. This is done far earlier than executing bus-reset handler. Therefore, updating streams at the bus-reset handler has no meaning.
This patchset will have little impacts for userspace applications because most users won't update IEEE 1394 bus when playbacking/recording. And PCM substream recovery is still available.
Regards
Takashi Sakamoto (4): ALSA: bebob: simplify bus-reset handling ALSA: bebob: move mutex from function callee to callers ALSA: bebob: change type of substream counter from atomic_t to unsigned int ALSA: bebob: give up updating streams at bus reset handler
Applied all four patches. Thanks.
Takashi
sound/firewire/bebob/bebob.c | 21 ++++++++++---- sound/firewire/bebob/bebob.h | 5 +--- sound/firewire/bebob/bebob_midi.c | 16 +++++++--- sound/firewire/bebob/bebob_pcm.c | 28 +++++++++++++----- sound/firewire/bebob/bebob_stream.c | 58 +++---------------------------------- 5 files changed, 53 insertions(+), 75 deletions(-)
-- 2.5.0
participants (2)
-
Takashi Iwai
-
Takashi Sakamoto