/* * digi00x-transaction.c - a part of driver for Digidesign Digi 002/003 family * * Copyright (c) 2014-2015 Takashi Sakamoto * * Licensed under the terms of the GNU General Public License, version 2. */ #include #include "digi00x.h" static int fill_midi_message(struct snd_rawmidi_substream *substream, u8 *buf) { int bytes; buf[0] = 0x80; bytes = snd_rawmidi_transmit_peek(substream, buf + 1, 2); if (bytes >= 0) buf[3] = 0xc0 | bytes; return bytes; } static void handle_midi_control(struct snd_dg00x *dg00x, __be32 *buf, unsigned int length) { struct snd_rawmidi_substream *substream; unsigned int i; unsigned int len; u8 *b; substream = ACCESS_ONCE(dg00x->in_control); if (substream == NULL) return; length /= 4; for (i = 0; i < length; i++) { b = (u8 *)&buf[i]; len = b[3] & 0xf; if (len > 0) snd_rawmidi_receive(dg00x->in_control, b + 1, len); } } static void handle_unknown_message(struct snd_dg00x *dg00x, unsigned long long offset, __be32 *buf) { unsigned long flags; spin_lock_irqsave(&dg00x->lock, flags); dg00x->msg = be32_to_cpu(*buf); spin_unlock_irqrestore(&dg00x->lock, flags); wake_up(&dg00x->hwdep_wait); } static void handle_message(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, int generation, unsigned long long offset, void *data, size_t length, void *callback_data) { struct snd_dg00x *dg00x = callback_data; __be32 *buf = (__be32 *)data; if (offset == dg00x->async_handler.offset) handle_unknown_message(dg00x, offset, buf); else if (offset == dg00x->async_handler.offset + 4) handle_midi_control(dg00x, buf, length); fw_send_response(card, request, RCODE_COMPLETE); } int snd_dg00x_transaction_reregister(struct snd_dg00x *dg00x) { struct fw_device *device = fw_parent_device(dg00x->unit); __be32 data[2]; int err; /* Unknown. 4bytes. */ data[0] = cpu_to_be32((device->card->node_id << 16) | (dg00x->async_handler.offset >> 32)); data[1] = cpu_to_be32(dg00x->async_handler.offset); err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_BLOCK_REQUEST, DG00X_ADDR_BASE + DG00X_OFFSET_MESSAGE_ADDR, &data, sizeof(data), 0); if (err < 0) return err; /* Asynchronous transactions for MIDI control message. */ data[0] = cpu_to_be32((device->card->node_id << 16) | (dg00x->async_handler.offset >> 32)); data[1] = cpu_to_be32(dg00x->async_handler.offset + 4); return snd_fw_transaction(dg00x->unit, TCODE_WRITE_BLOCK_REQUEST, DG00X_ADDR_BASE + DG00X_OFFSET_MIDI_CTL_ADDR, &data, sizeof(data), 0); } int snd_dg00x_transaction_register(struct snd_dg00x *dg00x) { static const struct fw_address_region resp_register_region = { .start = 0xffffe0000000ull, .end = 0xffffe000ffffull, }; int err; dg00x->async_handler.length = 12; dg00x->async_handler.address_callback = handle_message; dg00x->async_handler.callback_data = dg00x; err = fw_core_add_address_handler(&dg00x->async_handler, &resp_register_region); if (err < 0) return err; err = snd_dg00x_transaction_reregister(dg00x); if (err < 0) goto error; err = snd_fw_async_midi_port_init(&dg00x->out_control, dg00x->unit, DG00X_ADDR_BASE + DG00X_OFFSET_MMC, 4, fill_midi_message); if (err < 0) goto error; return err; error: fw_core_remove_address_handler(&dg00x->async_handler); dg00x->async_handler.callback_data = NULL; return err; } void snd_dg00x_transaction_unregister(struct snd_dg00x *dg00x) { if (dg00x->async_handler.callback_data == NULL) return; snd_fw_async_midi_port_destroy(&dg00x->out_control); fw_core_remove_address_handler(&dg00x->async_handler); dg00x->async_handler.callback_data = NULL; } />
context:
space:
mode:
authorVegard Nossum <vegard.nossum@oracle.com>2016-10-08 11:18:07 +0200
committerAl Viro <viro@zeniv.linux.org.uk>2016-10-14 20:00:34 -0400
commitffecee4f2442bb8cb6b34c3335fef4eb50c22fdd (patch)
tree53d6e7bcb5ff21f6f72d12d905b5173b35c2987a /tools/perf/scripts/Build
parentde34f4da7f62ff59ac6e1ef320b0fcfa3296fce3 (diff)
iov_iter: kernel-doc import_iovec() and rw_copy_check_uvector()
Both import_iovec() and rw_copy_check_uvector() take an array (typically small and on-stack) which is used to hold an iovec array copy from userspace. This is to avoid an expensive memory allocation in the fast path (i.e. few iovec elements). The caller may have to check whether these functions actually used the provided buffer or allocated a new one -- but this differs between the too. Let's just add a kernel doc to clarify what the semantics are for each function. Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'tools/perf/scripts/Build')