linux/sound/firewire/fcp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Function Control Protocol (IEC 61883-1) helper functions
   4 *
   5 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
   6 */
   7
   8#include <linux/device.h>
   9#include <linux/firewire.h>
  10#include <linux/firewire-constants.h>
  11#include <linux/list.h>
  12#include <linux/module.h>
  13#include <linux/slab.h>
  14#include <linux/sched.h>
  15#include <linux/spinlock.h>
  16#include <linux/wait.h>
  17#include <linux/delay.h>
  18#include "fcp.h"
  19#include "lib.h"
  20#include "amdtp-stream.h"
  21
  22#define CTS_AVC 0x00
  23
  24#define ERROR_RETRIES   3
  25#define ERROR_DELAY_MS  5
  26#define FCP_TIMEOUT_MS  125
  27
  28int avc_general_set_sig_fmt(struct fw_unit *unit, unsigned int rate,
  29                            enum avc_general_plug_dir dir,
  30                            unsigned short pid)
  31{
  32        unsigned int sfc;
  33        u8 *buf;
  34        bool flag;
  35        int err;
  36
  37        flag = false;
  38        for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) {
  39                if (amdtp_rate_table[sfc] == rate) {
  40                        flag = true;
  41                        break;
  42                }
  43        }
  44        if (!flag)
  45                return -EINVAL;
  46
  47        buf = kzalloc(8, GFP_KERNEL);
  48        if (buf == NULL)
  49                return -ENOMEM;
  50
  51        buf[0] = 0x00;          /* AV/C CONTROL */
  52        buf[1] = 0xff;          /* UNIT */
  53        if (dir == AVC_GENERAL_PLUG_DIR_IN)
  54                buf[2] = 0x19;  /* INPUT PLUG SIGNAL FORMAT */
  55        else
  56                buf[2] = 0x18;  /* OUTPUT PLUG SIGNAL FORMAT */
  57        buf[3] = 0xff & pid;    /* plug id */
  58        buf[4] = 0x90;          /* EOH_1, Form_1, FMT. AM824 */
  59        buf[5] = 0x07 & sfc;    /* FDF-hi. AM824, frequency */
  60        buf[6] = 0xff;          /* FDF-mid. AM824, SYT hi (not used)*/
  61        buf[7] = 0xff;          /* FDF-low. AM824, SYT lo (not used) */
  62
  63        /* do transaction and check buf[1-5] are the same against command */
  64        err = fcp_avc_transaction(unit, buf, 8, buf, 8,
  65                                  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5));
  66        if (err < 0)
  67                ;
  68        else if (err < 8)
  69                err = -EIO;
  70        else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
  71                err = -ENOSYS;
  72        else if (buf[0] == 0x0a) /* REJECTED */
  73                err = -EINVAL;
  74        if (err < 0)
  75                goto end;
  76
  77        err = 0;
  78end:
  79        kfree(buf);
  80        return err;
  81}
  82EXPORT_SYMBOL(avc_general_set_sig_fmt);
  83
  84int avc_general_get_sig_fmt(struct fw_unit *unit, unsigned int *rate,
  85                            enum avc_general_plug_dir dir,
  86                            unsigned short pid)
  87{
  88        unsigned int sfc;
  89        u8 *buf;
  90        int err;
  91
  92        buf = kzalloc(8, GFP_KERNEL);
  93        if (buf == NULL)
  94                return -ENOMEM;
  95
  96        buf[0] = 0x01;          /* AV/C STATUS */
  97        buf[1] = 0xff;          /* Unit */
  98        if (dir == AVC_GENERAL_PLUG_DIR_IN)
  99                buf[2] = 0x19;  /* INPUT PLUG SIGNAL FORMAT */
 100        else
 101                buf[2] = 0x18;  /* OUTPUT PLUG SIGNAL FORMAT */
 102        buf[3] = 0xff & pid;    /* plug id */
 103        buf[4] = 0x90;          /* EOH_1, Form_1, FMT. AM824 */
 104        buf[5] = 0xff;          /* FDF-hi. AM824, frequency */
 105        buf[6] = 0xff;          /* FDF-mid. AM824, SYT hi (not used) */
 106        buf[7] = 0xff;          /* FDF-low. AM824, SYT lo (not used) */
 107
 108        /* do transaction and check buf[1-4] are the same against command */
 109        err = fcp_avc_transaction(unit, buf, 8, buf, 8,
 110                                  BIT(1) | BIT(2) | BIT(3) | BIT(4));
 111        if (err < 0)
 112                ;
 113        else if (err < 8)
 114                err = -EIO;
 115        else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
 116                err = -ENOSYS;
 117        else if (buf[0] == 0x0a) /* REJECTED */
 118                err = -EINVAL;
 119        else if (buf[0] == 0x0b) /* IN TRANSITION */
 120                err = -EAGAIN;
 121        if (err < 0)
 122                goto end;
 123
 124        /* check sfc field and pick up rate */
 125        sfc = 0x07 & buf[5];
 126        if (sfc >= CIP_SFC_COUNT) {
 127                err = -EAGAIN;  /* also in transition */
 128                goto end;
 129        }
 130
 131        *rate = amdtp_rate_table[sfc];
 132        err = 0;
 133end:
 134        kfree(buf);
 135        return err;
 136}
 137EXPORT_SYMBOL(avc_general_get_sig_fmt);
 138
 139int avc_general_get_plug_info(struct fw_unit *unit, unsigned int subunit_type,
 140                              unsigned int subunit_id, unsigned int subfunction,
 141                              u8 info[AVC_PLUG_INFO_BUF_BYTES])
 142{
 143        u8 *buf;
 144        int err;
 145
 146        /* extended subunit in spec.4.2 is not supported */
 147        if ((subunit_type == 0x1E) || (subunit_id == 5))
 148                return -EINVAL;
 149
 150        buf = kzalloc(8, GFP_KERNEL);
 151        if (buf == NULL)
 152                return -ENOMEM;
 153
 154        buf[0] = 0x01;  /* AV/C STATUS */
 155        /* UNIT or Subunit, Functionblock */
 156        buf[1] = ((subunit_type & 0x1f) << 3) | (subunit_id & 0x7);
 157        buf[2] = 0x02;  /* PLUG INFO */
 158        buf[3] = 0xff & subfunction;
 159
 160        err = fcp_avc_transaction(unit, buf, 8, buf, 8, BIT(1) | BIT(2));
 161        if (err < 0)
 162                ;
 163        else if (err < 8)
 164                err = -EIO;
 165        else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
 166                err = -ENOSYS;
 167        else if (buf[0] == 0x0a) /* REJECTED */
 168                err = -EINVAL;
 169        else if (buf[0] == 0x0b) /* IN TRANSITION */
 170                err = -EAGAIN;
 171        if (err < 0)
 172                goto end;
 173
 174        info[0] = buf[4];
 175        info[1] = buf[5];
 176        info[2] = buf[6];
 177        info[3] = buf[7];
 178
 179        err = 0;
 180end:
 181        kfree(buf);
 182        return err;
 183}
 184EXPORT_SYMBOL(avc_general_get_plug_info);
 185
 186static DEFINE_SPINLOCK(transactions_lock);
 187static LIST_HEAD(transactions);
 188
 189enum fcp_state {
 190        STATE_PENDING,
 191        STATE_BUS_RESET,
 192        STATE_COMPLETE,
 193        STATE_DEFERRED,
 194};
 195
 196struct fcp_transaction {
 197        struct list_head list;
 198        struct fw_unit *unit;
 199        void *response_buffer;
 200        unsigned int response_size;
 201        unsigned int response_match_bytes;
 202        enum fcp_state state;
 203        wait_queue_head_t wait;
 204        bool deferrable;
 205};
 206
 207/**
 208 * fcp_avc_transaction - send an AV/C command and wait for its response
 209 * @unit: a unit on the target device
 210 * @command: a buffer containing the command frame; must be DMA-able
 211 * @command_size: the size of @command
 212 * @response: a buffer for the response frame
 213 * @response_size: the maximum size of @response
 214 * @response_match_bytes: a bitmap specifying the bytes used to detect the
 215 *                        correct response frame
 216 *
 217 * This function sends a FCP command frame to the target and waits for the
 218 * corresponding response frame to be returned.
 219 *
 220 * Because it is possible for multiple FCP transactions to be active at the
 221 * same time, the correct response frame is detected by the value of certain
 222 * bytes.  These bytes must be set in @response before calling this function,
 223 * and the corresponding bits must be set in @response_match_bytes.
 224 *
 225 * @command and @response can point to the same buffer.
 226 *
 227 * Returns the actual size of the response frame, or a negative error code.
 228 */
 229int fcp_avc_transaction(struct fw_unit *unit,
 230                        const void *command, unsigned int command_size,
 231                        void *response, unsigned int response_size,
 232                        unsigned int response_match_bytes)
 233{
 234        struct fcp_transaction t;
 235        int tcode, ret, tries = 0;
 236
 237        t.unit = unit;
 238        t.response_buffer = response;
 239        t.response_size = response_size;
 240        t.response_match_bytes = response_match_bytes;
 241        t.state = STATE_PENDING;
 242        init_waitqueue_head(&t.wait);
 243
 244        if (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03)
 245                t.deferrable = true;
 246
 247        spin_lock_irq(&transactions_lock);
 248        list_add_tail(&t.list, &transactions);
 249        spin_unlock_irq(&transactions_lock);
 250
 251        for (;;) {
 252                tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST
 253                                          : TCODE_WRITE_BLOCK_REQUEST;
 254                ret = snd_fw_transaction(t.unit, tcode,
 255                                         CSR_REGISTER_BASE + CSR_FCP_COMMAND,
 256                                         (void *)command, command_size, 0);
 257                if (ret < 0)
 258                        break;
 259deferred:
 260                wait_event_timeout(t.wait, t.state != STATE_PENDING,
 261                                   msecs_to_jiffies(FCP_TIMEOUT_MS));
 262
 263                if (t.state == STATE_DEFERRED) {
 264                        /*
 265                         * 'AV/C General Specification' define no time limit
 266                         * on command completion once an INTERIM response has
 267                         * been sent. but we promise to finish this function
 268                         * for a caller. Here we use FCP_TIMEOUT_MS for next
 269                         * interval. This is not in the specification.
 270                         */
 271                        t.state = STATE_PENDING;
 272                        goto deferred;
 273                } else if (t.state == STATE_COMPLETE) {
 274                        ret = t.response_size;
 275                        break;
 276                } else if (t.state == STATE_BUS_RESET) {
 277                        msleep(ERROR_DELAY_MS);
 278                } else if (++tries >= ERROR_RETRIES) {
 279                        dev_err(&t.unit->device, "FCP command timed out\n");
 280                        ret = -EIO;
 281                        break;
 282                }
 283        }
 284
 285        spin_lock_irq(&transactions_lock);
 286        list_del(&t.list);
 287        spin_unlock_irq(&transactions_lock);
 288
 289        return ret;
 290}
 291EXPORT_SYMBOL(fcp_avc_transaction);
 292
 293/**
 294 * fcp_bus_reset - inform the target handler about a bus reset
 295 * @unit: the unit that might be used by fcp_avc_transaction()
 296 *
 297 * This function must be called from the driver's .update handler to inform
 298 * the FCP transaction handler that a bus reset has happened.  Any pending FCP
 299 * transactions are retried.
 300 */
 301void fcp_bus_reset(struct fw_unit *unit)
 302{
 303        struct fcp_transaction *t;
 304
 305        spin_lock_irq(&transactions_lock);
 306        list_for_each_entry(t, &transactions, list) {
 307                if (t->unit == unit &&
 308                    (t->state == STATE_PENDING ||
 309                     t->state == STATE_DEFERRED)) {
 310                        t->state = STATE_BUS_RESET;
 311                        wake_up(&t->wait);
 312                }
 313        }
 314        spin_unlock_irq(&transactions_lock);
 315}
 316EXPORT_SYMBOL(fcp_bus_reset);
 317
 318/* checks whether the response matches the masked bytes in response_buffer */
 319static bool is_matching_response(struct fcp_transaction *transaction,
 320                                 const void *response, size_t length)
 321{
 322        const u8 *p1, *p2;
 323        unsigned int mask, i;
 324
 325        p1 = response;
 326        p2 = transaction->response_buffer;
 327        mask = transaction->response_match_bytes;
 328
 329        for (i = 0; ; ++i) {
 330                if ((mask & 1) && p1[i] != p2[i])
 331                        return false;
 332                mask >>= 1;
 333                if (!mask)
 334                        return true;
 335                if (--length == 0)
 336                        return false;
 337        }
 338}
 339
 340static void fcp_response(struct fw_card *card, struct fw_request *request,
 341                         int tcode, int destination, int source,
 342                         int generation, unsigned long long offset,
 343                         void *data, size_t length, void *callback_data)
 344{
 345        struct fcp_transaction *t;
 346        unsigned long flags;
 347
 348        if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC)
 349                return;
 350
 351        spin_lock_irqsave(&transactions_lock, flags);
 352        list_for_each_entry(t, &transactions, list) {
 353                struct fw_device *device = fw_parent_device(t->unit);
 354                if (device->card != card ||
 355                    device->generation != generation)
 356                        continue;
 357                smp_rmb(); /* node_id vs. generation */
 358                if (device->node_id != source)
 359                        continue;
 360
 361                if (t->state == STATE_PENDING &&
 362                    is_matching_response(t, data, length)) {
 363                        if (t->deferrable && *(const u8 *)data == 0x0f) {
 364                                t->state = STATE_DEFERRED;
 365                        } else {
 366                                t->state = STATE_COMPLETE;
 367                                t->response_size = min_t(unsigned int, length,
 368                                                         t->response_size);
 369                                memcpy(t->response_buffer, data,
 370                                       t->response_size);
 371                        }
 372                        wake_up(&t->wait);
 373                }
 374        }
 375        spin_unlock_irqrestore(&transactions_lock, flags);
 376}
 377
 378static struct fw_address_handler response_register_handler = {
 379        .length = 0x200,
 380        .address_callback = fcp_response,
 381};
 382
 383static int __init fcp_module_init(void)
 384{
 385        static const struct fw_address_region response_register_region = {
 386                .start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE,
 387                .end = CSR_REGISTER_BASE + CSR_FCP_END,
 388        };
 389
 390        fw_core_add_address_handler(&response_register_handler,
 391                                    &response_register_region);
 392
 393        return 0;
 394}
 395
 396static void __exit fcp_module_exit(void)
 397{
 398        WARN_ON(!list_empty(&transactions));
 399        fw_core_remove_address_handler(&response_register_handler);
 400}
 401
 402module_init(fcp_module_init);
 403module_exit(fcp_module_exit);
 404