lib.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. /*
  2. * miscellaneous helper functions
  3. *
  4. * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5. * Licensed under the terms of the GNU General Public License, version 2.
  6. */
  7. #include <linux/delay.h>
  8. #include <linux/device.h>
  9. #include <linux/firewire.h>
  10. #include <linux/module.h>
  11. #include "lib.h"
  12. #define ERROR_RETRY_DELAY_MS 5
  13. /**
  14. * snd_fw_transaction - send a request and wait for its completion
  15. * @unit: the driver's unit on the target device
  16. * @tcode: the transaction code
  17. * @offset: the address in the target's address space
  18. * @buffer: input/output data
  19. * @length: length of @buffer
  20. *
  21. * Submits an asynchronous request to the target device, and waits for the
  22. * response. The node ID and the current generation are derived from @unit.
  23. * On a bus reset or an error, the transaction is retried a few times.
  24. * Returns zero on success, or a negative error code.
  25. */
  26. int snd_fw_transaction(struct fw_unit *unit, int tcode,
  27. u64 offset, void *buffer, size_t length)
  28. {
  29. struct fw_device *device = fw_parent_device(unit);
  30. int generation, rcode, tries = 0;
  31. for (;;) {
  32. generation = device->generation;
  33. smp_rmb(); /* node_id vs. generation */
  34. rcode = fw_run_transaction(device->card, tcode,
  35. device->node_id, generation,
  36. device->max_speed, offset,
  37. buffer, length);
  38. if (rcode == RCODE_COMPLETE)
  39. return 0;
  40. if (rcode_is_permanent_error(rcode) || ++tries >= 3) {
  41. dev_err(&unit->device, "transaction failed: %s\n",
  42. fw_rcode_string(rcode));
  43. return -EIO;
  44. }
  45. msleep(ERROR_RETRY_DELAY_MS);
  46. }
  47. }
  48. EXPORT_SYMBOL(snd_fw_transaction);
  49. MODULE_DESCRIPTION("FireWire audio helper functions");
  50. MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
  51. MODULE_LICENSE("GPL v2");