mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 04:23:35 +02:00
This was done entirely with mindless brute force, using
git grep -l '\<k[vmz]*alloc_objs*(.*, GFP_KERNEL)' |
xargs sed -i 's/\(alloc_objs*(.*\), GFP_KERNEL)/\1)/'
to convert the new alloc_obj() users that had a simple GFP_KERNEL
argument to just drop that argument.
Note that due to the extreme simplicity of the scripting, any slightly
more complex cases spread over multiple lines would not be triggered:
they definitely exist, but this covers the vast bulk of the cases, and
the resulting diff is also then easier to check automatically.
For the same reason the 'flex' versions will be done as a separate
conversion.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
203 lines
4.5 KiB
C
203 lines
4.5 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Linux driver for TerraTec DMX 6Fire USB
|
|
*
|
|
* Rawmidi driver
|
|
*
|
|
* Author: Torsten Schenk <torsten.schenk@zoho.com>
|
|
* Created: Jan 01, 2011
|
|
* Copyright: (C) Torsten Schenk
|
|
*/
|
|
|
|
#include <sound/rawmidi.h>
|
|
|
|
#include "midi.h"
|
|
#include "chip.h"
|
|
#include "comm.h"
|
|
|
|
enum {
|
|
MIDI_BUFSIZE = 64
|
|
};
|
|
|
|
static void usb6fire_midi_out_handler(struct urb *urb)
|
|
{
|
|
struct midi_runtime *rt = urb->context;
|
|
int ret;
|
|
|
|
guard(spinlock_irqsave)(&rt->out_lock);
|
|
|
|
if (rt->out) {
|
|
ret = snd_rawmidi_transmit(rt->out, rt->out_buffer + 4,
|
|
MIDI_BUFSIZE - 4);
|
|
if (ret > 0) { /* more data available, send next packet */
|
|
rt->out_buffer[1] = ret + 2;
|
|
rt->out_buffer[3] = rt->out_serial++;
|
|
urb->transfer_buffer_length = ret + 4;
|
|
|
|
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
|
if (ret < 0)
|
|
dev_err(&urb->dev->dev,
|
|
"midi out urb submit failed: %d\n",
|
|
ret);
|
|
} else /* no more data to transmit */
|
|
rt->out = NULL;
|
|
}
|
|
}
|
|
|
|
static void usb6fire_midi_in_received(
|
|
struct midi_runtime *rt, u8 *data, int length)
|
|
{
|
|
guard(spinlock_irqsave)(&rt->in_lock);
|
|
if (rt->in)
|
|
snd_rawmidi_receive(rt->in, data, length);
|
|
}
|
|
|
|
static int usb6fire_midi_out_open(struct snd_rawmidi_substream *alsa_sub)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int usb6fire_midi_out_close(struct snd_rawmidi_substream *alsa_sub)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void usb6fire_midi_out_trigger(
|
|
struct snd_rawmidi_substream *alsa_sub, int up)
|
|
{
|
|
struct midi_runtime *rt = alsa_sub->rmidi->private_data;
|
|
struct urb *urb = &rt->out_urb;
|
|
__s8 ret;
|
|
|
|
guard(spinlock_irqsave)(&rt->out_lock);
|
|
if (up) { /* start transfer */
|
|
if (rt->out) /* we are already transmitting so just return */
|
|
return;
|
|
|
|
ret = snd_rawmidi_transmit(alsa_sub, rt->out_buffer + 4,
|
|
MIDI_BUFSIZE - 4);
|
|
if (ret > 0) {
|
|
rt->out_buffer[1] = ret + 2;
|
|
rt->out_buffer[3] = rt->out_serial++;
|
|
urb->transfer_buffer_length = ret + 4;
|
|
|
|
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
|
if (ret < 0)
|
|
dev_err(&urb->dev->dev,
|
|
"midi out urb submit failed: %d\n",
|
|
ret);
|
|
else
|
|
rt->out = alsa_sub;
|
|
}
|
|
} else if (rt->out == alsa_sub)
|
|
rt->out = NULL;
|
|
}
|
|
|
|
static void usb6fire_midi_out_drain(struct snd_rawmidi_substream *alsa_sub)
|
|
{
|
|
struct midi_runtime *rt = alsa_sub->rmidi->private_data;
|
|
int retry = 0;
|
|
|
|
while (rt->out && retry++ < 100)
|
|
msleep(10);
|
|
}
|
|
|
|
static int usb6fire_midi_in_open(struct snd_rawmidi_substream *alsa_sub)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int usb6fire_midi_in_close(struct snd_rawmidi_substream *alsa_sub)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void usb6fire_midi_in_trigger(
|
|
struct snd_rawmidi_substream *alsa_sub, int up)
|
|
{
|
|
struct midi_runtime *rt = alsa_sub->rmidi->private_data;
|
|
|
|
guard(spinlock_irqsave)(&rt->in_lock);
|
|
if (up)
|
|
rt->in = alsa_sub;
|
|
else
|
|
rt->in = NULL;
|
|
}
|
|
|
|
static const struct snd_rawmidi_ops out_ops = {
|
|
.open = usb6fire_midi_out_open,
|
|
.close = usb6fire_midi_out_close,
|
|
.trigger = usb6fire_midi_out_trigger,
|
|
.drain = usb6fire_midi_out_drain
|
|
};
|
|
|
|
static const struct snd_rawmidi_ops in_ops = {
|
|
.open = usb6fire_midi_in_open,
|
|
.close = usb6fire_midi_in_close,
|
|
.trigger = usb6fire_midi_in_trigger
|
|
};
|
|
|
|
int usb6fire_midi_init(struct sfire_chip *chip)
|
|
{
|
|
int ret;
|
|
struct midi_runtime *rt = kzalloc_obj(struct midi_runtime);
|
|
struct comm_runtime *comm_rt = chip->comm;
|
|
|
|
if (!rt)
|
|
return -ENOMEM;
|
|
|
|
rt->out_buffer = kzalloc(MIDI_BUFSIZE, GFP_KERNEL);
|
|
if (!rt->out_buffer) {
|
|
kfree(rt);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
rt->chip = chip;
|
|
rt->in_received = usb6fire_midi_in_received;
|
|
rt->out_buffer[0] = 0x80; /* 'send midi' command */
|
|
rt->out_buffer[1] = 0x00; /* size of data */
|
|
rt->out_buffer[2] = 0x00; /* always 0 */
|
|
spin_lock_init(&rt->in_lock);
|
|
spin_lock_init(&rt->out_lock);
|
|
|
|
comm_rt->init_urb(comm_rt, &rt->out_urb, rt->out_buffer, rt,
|
|
usb6fire_midi_out_handler);
|
|
|
|
ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance);
|
|
if (ret < 0) {
|
|
kfree(rt->out_buffer);
|
|
kfree(rt);
|
|
dev_err(&chip->dev->dev, "unable to create midi.\n");
|
|
return ret;
|
|
}
|
|
rt->instance->private_data = rt;
|
|
strscpy(rt->instance->name, "DMX6FireUSB MIDI");
|
|
rt->instance->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
|
|
SNDRV_RAWMIDI_INFO_INPUT |
|
|
SNDRV_RAWMIDI_INFO_DUPLEX;
|
|
snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_OUTPUT,
|
|
&out_ops);
|
|
snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_INPUT,
|
|
&in_ops);
|
|
|
|
chip->midi = rt;
|
|
return 0;
|
|
}
|
|
|
|
void usb6fire_midi_abort(struct sfire_chip *chip)
|
|
{
|
|
struct midi_runtime *rt = chip->midi;
|
|
|
|
if (rt)
|
|
usb_poison_urb(&rt->out_urb);
|
|
}
|
|
|
|
void usb6fire_midi_destroy(struct sfire_chip *chip)
|
|
{
|
|
struct midi_runtime *rt = chip->midi;
|
|
|
|
kfree(rt->out_buffer);
|
|
kfree(rt);
|
|
chip->midi = NULL;
|
|
}
|