[alsa-devel] [PATCH 18/44] fireworks: Add connection and stream management
Takashi Sakamoto
o-takashi at sakamocchi.jp
Fri Apr 4 16:22:49 CEST 2014
Clemens,
(Apr 04 2014 05:56), Clemens Ladisch wrote:
> Takashi Sakamoto wrote:
>> Fireworks manages connections by CMP and can transmit/receive AMDTP streams
>> with a few quirks. This commit adds functionality to start/stop the streams.
>>
>> +++ b/sound/firewire/fireworks/fireworks.c
>> +static int
>> +init_stream(struct snd_efw *efw, struct amdtp_stream *stream)
>> +{
>> + ...
>> + err = amdtp_stream_init(stream, efw->unit, s_dir, CIP_BLOCKING);
>
> amdtp_stream_destroy() must be called.
For me, there is an ambiguous on what you said. Must it be called before
calling amdtp_stream_init() or in a case that the function returns error?
If the former, can I request you the reason?
Else, is it due to reference counter of firewire unit? (fw_unit_get/put)
>> +static int
>> +start_stream(struct snd_efw *efw, struct amdtp_stream *stream,
>> + unsigned int sampling_rate)
>> +{
>> + ...
>> + err = amdtp_stream_start(stream,
>> + conn->resources.channel,
>> + conn->speed);
>> + if (err < 0)
>> + stop_stream(efw, stream);
>> +
>> + /* wait first callback */
>> + if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) {
>> + stop_stream(efw, stream);
>> + err = -ETIMEDOUT;
>> + }
>> +end:
>> + return err;
>> +}
>
> If amdtp_stream_start() fails, this function will try to wait for
> the stream anyway.
Exactly. I missed it.
>> +int snd_efw_stream_init_duplex(struct snd_efw *efw)
>> +{
>> + int err;
>> +
>> + err = init_stream(efw, &efw->tx_stream);
>> + if (err < 0)
>> + goto end;
>> +
>> + err = init_stream(efw, &efw->rx_stream);
>> + if (err < 0)
>> + goto end;
>
> If the second init_stream() fails, this function will return with only one
> of the streams initialized.
>
>> +
>> + /* set IEC61883 compliant mode */
>> + err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883);
>> +end:
>> + return err;
>
> And if this fails, this function will return an error, but the two streams
> will still be initialized.
>
> In the error cases, any so-far initialized stream must be destroyed.
OK.
>> +int snd_efw_stream_stop_duplex(struct snd_efw *efw)
>> +{
>> + struct amdtp_stream *master, *slave;
>> + enum cip_flags sync_mode;
>> + unsigned int slave_substreams;
>> + int err;
>> +
>> + mutex_lock(&efw->mutex);
>> +
>> + err = get_roles(efw, &sync_mode, &master, &slave);
>> + if (err < 0)
>> + goto end;
>
> snd_efw_stream_stop_duplex() must always succeed so that the
> resources can be freed properly. Therefore, it should not
> try to ask the device for anything (the device might be
> resetting or be unplugged).
Exactly.
> Either cache the master/slave pointers when starting the stream,
> or rewrite get_roles() so that it does not access the device.
Hm. the cache is better idea for this issue.
Thank you
Takashi Sakamoto
o-takashi at sakamocchi.jp
More information about the Alsa-devel
mailing list