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