linux/sound/firewire/lib.c
<<
>>
Prefs
   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 */
  20const 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}
  40EXPORT_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 */
  55int 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}
  81EXPORT_SYMBOL(snd_fw_transaction);
  82
  83MODULE_DESCRIPTION("FireWire audio helper functions");
  84MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
  85MODULE_LICENSE("GPL v2");
  86