lib.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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. * rcode_string - convert a firewire result code to a string
  15. * @rcode: the result
  16. */
  17. const char *rcode_string(unsigned int rcode)
  18. {
  19. static const char *const names[] = {
  20. [RCODE_COMPLETE] = "complete",
  21. [RCODE_CONFLICT_ERROR] = "conflict error",
  22. [RCODE_DATA_ERROR] = "data error",
  23. [RCODE_TYPE_ERROR] = "type error",
  24. [RCODE_ADDRESS_ERROR] = "address error",
  25. [RCODE_SEND_ERROR] = "send error",
  26. [RCODE_CANCELLED] = "cancelled",
  27. [RCODE_BUSY] = "busy",
  28. [RCODE_GENERATION] = "generation",
  29. [RCODE_NO_ACK] = "no ack",
  30. };
  31. if (rcode < ARRAY_SIZE(names) && names[rcode])
  32. return names[rcode];
  33. else
  34. return "unknown";
  35. }
  36. EXPORT_SYMBOL(rcode_string);
  37. /**
  38. * snd_fw_transaction - send a request and wait for its completion
  39. * @unit: the driver's unit on the target device
  40. * @tcode: the transaction code
  41. * @offset: the address in the target's address space
  42. * @buffer: input/output data
  43. * @length: length of @buffer
  44. *
  45. * Submits an asynchronous request to the target device, and waits for the
  46. * response. The node ID and the current generation are derived from @unit.
  47. * On a bus reset or an error, the transaction is retried a few times.
  48. * Returns zero on success, or a negative error code.
  49. */
  50. int snd_fw_transaction(struct fw_unit *unit, int tcode,
  51. u64 offset, void *buffer, size_t length)
  52. {
  53. struct fw_device *device = fw_parent_device(unit);
  54. int generation, rcode, tries = 0;
  55. for (;;) {
  56. generation = device->generation;
  57. smp_rmb(); /* node_id vs. generation */
  58. rcode = fw_run_transaction(device->card, tcode,
  59. device->node_id, generation,
  60. device->max_speed, offset,
  61. buffer, length);
  62. if (rcode == RCODE_COMPLETE)
  63. return 0;
  64. if (rcode_is_permanent_error(rcode) || ++tries >= 3) {
  65. dev_err(&unit->device, "transaction failed: %s\n",
  66. rcode_string(rcode));
  67. return -EIO;
  68. }
  69. msleep(ERROR_RETRY_DELAY_MS);
  70. }
  71. }
  72. EXPORT_SYMBOL(snd_fw_transaction);
  73. MODULE_DESCRIPTION("FireWire audio helper functions");
  74. MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
  75. MODULE_LICENSE("GPL v2");