diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2011-09-04 16:17:38 -0400 |
---|---|---|
committer | Clemens Ladisch <clemens@ladisch.de> | 2013-10-20 16:07:57 -0400 |
commit | 1b70485f135a39d5f2d8c392a16817456fa3a5cd (patch) | |
tree | cf1b9b833619374c3169c368890652d53594b43d /sound/firewire/isight.c | |
parent | a644a9473f7f9519e2fe519136959dd0e671572a (diff) |
ALSA: firewire: extend snd_fw_transaction()
Add a flag to snd_fw_transaction() to allow it to abort when a bus reset
happens. This removes most of the duplicated error handling loops that
were required around calls to the low-level fw_run_transaction().
Also add a flag to suppress error messages; errors are expected when we
attempt to clean up after the device was unplugged.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound/firewire/isight.c')
-rw-r--r-- | sound/firewire/isight.c | 43 |
1 files changed, 20 insertions, 23 deletions
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 58a5afefdc69..fd42e6b315e6 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c | |||
@@ -217,7 +217,7 @@ static void isight_packet(struct fw_iso_context *context, u32 cycle, | |||
217 | 217 | ||
218 | static int isight_connect(struct isight *isight) | 218 | static int isight_connect(struct isight *isight) |
219 | { | 219 | { |
220 | int ch, err, rcode, errors = 0; | 220 | int ch, err; |
221 | __be32 value; | 221 | __be32 value; |
222 | 222 | ||
223 | retry_after_bus_reset: | 223 | retry_after_bus_reset: |
@@ -230,27 +230,19 @@ retry_after_bus_reset: | |||
230 | } | 230 | } |
231 | 231 | ||
232 | value = cpu_to_be32(ch | (isight->device->max_speed << SPEED_SHIFT)); | 232 | value = cpu_to_be32(ch | (isight->device->max_speed << SPEED_SHIFT)); |
233 | for (;;) { | 233 | err = snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, |
234 | rcode = fw_run_transaction( | 234 | isight->audio_base + REG_ISO_TX_CONFIG, |
235 | isight->device->card, | 235 | &value, 4, FW_FIXED_GENERATION | |
236 | TCODE_WRITE_QUADLET_REQUEST, | 236 | isight->resources.generation); |
237 | isight->device->node_id, | 237 | if (err == -EAGAIN) { |
238 | isight->resources.generation, | 238 | fw_iso_resources_free(&isight->resources); |
239 | isight->device->max_speed, | 239 | goto retry_after_bus_reset; |
240 | isight->audio_base + REG_ISO_TX_CONFIG, | 240 | } else if (err < 0) { |
241 | &value, 4); | 241 | goto err_resources; |
242 | if (rcode == RCODE_COMPLETE) { | ||
243 | return 0; | ||
244 | } else if (rcode == RCODE_GENERATION) { | ||
245 | fw_iso_resources_free(&isight->resources); | ||
246 | goto retry_after_bus_reset; | ||
247 | } else if (rcode_is_permanent_error(rcode) || ++errors >= 3) { | ||
248 | err = -EIO; | ||
249 | goto err_resources; | ||
250 | } | ||
251 | msleep(5); | ||
252 | } | 242 | } |
253 | 243 | ||
244 | return 0; | ||
245 | |||
254 | err_resources: | 246 | err_resources: |
255 | fw_iso_resources_free(&isight->resources); | 247 | fw_iso_resources_free(&isight->resources); |
256 | error: | 248 | error: |
@@ -315,17 +307,19 @@ static int isight_hw_params(struct snd_pcm_substream *substream, | |||
315 | static int reg_read(struct isight *isight, int offset, __be32 *value) | 307 | static int reg_read(struct isight *isight, int offset, __be32 *value) |
316 | { | 308 | { |
317 | return snd_fw_transaction(isight->unit, TCODE_READ_QUADLET_REQUEST, | 309 | return snd_fw_transaction(isight->unit, TCODE_READ_QUADLET_REQUEST, |
318 | isight->audio_base + offset, value, 4); | 310 | isight->audio_base + offset, value, 4, 0); |
319 | } | 311 | } |
320 | 312 | ||
321 | static int reg_write(struct isight *isight, int offset, __be32 value) | 313 | static int reg_write(struct isight *isight, int offset, __be32 value) |
322 | { | 314 | { |
323 | return snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, | 315 | return snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, |
324 | isight->audio_base + offset, &value, 4); | 316 | isight->audio_base + offset, &value, 4, 0); |
325 | } | 317 | } |
326 | 318 | ||
327 | static void isight_stop_streaming(struct isight *isight) | 319 | static void isight_stop_streaming(struct isight *isight) |
328 | { | 320 | { |
321 | __be32 value; | ||
322 | |||
329 | if (!isight->context) | 323 | if (!isight->context) |
330 | return; | 324 | return; |
331 | 325 | ||
@@ -333,7 +327,10 @@ static void isight_stop_streaming(struct isight *isight) | |||
333 | fw_iso_context_destroy(isight->context); | 327 | fw_iso_context_destroy(isight->context); |
334 | isight->context = NULL; | 328 | isight->context = NULL; |
335 | fw_iso_resources_free(&isight->resources); | 329 | fw_iso_resources_free(&isight->resources); |
336 | reg_write(isight, REG_AUDIO_ENABLE, 0); | 330 | value = 0; |
331 | snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, | ||
332 | isight->audio_base + REG_AUDIO_ENABLE, | ||
333 | &value, 4, FW_QUIET); | ||
337 | } | 334 | } |
338 | 335 | ||
339 | static int isight_hw_free(struct snd_pcm_substream *substream) | 336 | static int isight_hw_free(struct snd_pcm_substream *substream) |