Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55851f73 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela
Browse files

[ALSA] usb-audio: use usb_buffer_alloc/free



USB generic driver
Use the USB buffer allocation functions to avoid repeated DMA mappings
of our buffers, which are re-used quite a lot.

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent daa150ef
Loading
Loading
Loading
Loading
+33 −19
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ struct audioformat {

struct snd_urb_ctx {
	struct urb *urb;
	unsigned int buffer_size;	/* size of data buffer, if data URB */
	snd_usb_substream_t *subs;
	int index;	/* index for urb array */
	int packets;	/* number of packets per urb */
@@ -176,7 +177,8 @@ struct snd_usb_substream {
	unsigned int nurbs;			/* # urbs */
	snd_urb_ctx_t dataurb[MAX_URBS];	/* data urb table */
	snd_urb_ctx_t syncurb[SYNC_URBS];	/* sync urb table */
	char syncbuf[SYNC_URBS * 4];	/* sync buffer; it's so small - let's get static */
	char *syncbuf;				/* sync buffer for all sync URBs */
	dma_addr_t sync_dma;			/* DMA address of syncbuf */

	u64 formats;			/* format bitmasks (all or'ed) */
	unsigned int num_formats;		/* number of supported audio formats (list) */
@@ -855,7 +857,10 @@ static int snd_usb_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
static void release_urb_ctx(snd_urb_ctx_t *u)
{
	if (u->urb) {
		kfree(u->urb->transfer_buffer);
		if (u->buffer_size)
			usb_buffer_free(u->subs->dev, u->buffer_size,
					u->urb->transfer_buffer,
					u->urb->transfer_dma);
		usb_free_urb(u->urb);
		u->urb = NULL;
	}
@@ -876,6 +881,9 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force)
		release_urb_ctx(&subs->dataurb[i]);
	for (i = 0; i < SYNC_URBS; i++)
		release_urb_ctx(&subs->syncurb[i]);
	usb_buffer_free(subs->dev, SYNC_URBS * 4,
			subs->syncbuf, subs->sync_dma);
	subs->syncbuf = NULL;
	subs->nurbs = 0;
}

@@ -986,21 +994,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
		u->index = i;
		u->subs = subs;
		u->packets = npacks[i];
		u->buffer_size = maxsize * u->packets;
		if (subs->fmt_type == USB_FORMAT_TYPE_II)
			u->packets++; /* for transfer delimiter */
		u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
		if (! u->urb) {
			release_substream_urbs(subs, 0);
			return -ENOMEM;
		}
		u->urb->transfer_buffer = kmalloc(maxsize * u->packets,
						  GFP_KERNEL);
		if (! u->urb->transfer_buffer) {
			release_substream_urbs(subs, 0);
			return -ENOMEM;
		}
		if (! u->urb)
			goto out_of_memory;
		u->urb->transfer_buffer =
			usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL,
					 &u->urb->transfer_dma);
		if (! u->urb->transfer_buffer)
			goto out_of_memory;
		u->urb->pipe = subs->datapipe;
		u->urb->transfer_flags = URB_ISO_ASAP;
		u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
		u->urb->interval = 1 << subs->datainterval;
		u->urb->context = u;
		u->urb->complete = snd_usb_complete_callback(snd_complete_urb);
@@ -1008,20 +1014,24 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by

	if (subs->syncpipe) {
		/* allocate and initialize sync urbs */
		subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4,
						 GFP_KERNEL, &subs->sync_dma);
		if (! subs->syncbuf)
			goto out_of_memory;
		for (i = 0; i < SYNC_URBS; i++) {
			snd_urb_ctx_t *u = &subs->syncurb[i];
			u->index = i;
			u->subs = subs;
			u->packets = 1;
			u->urb = usb_alloc_urb(1, GFP_KERNEL);
			if (! u->urb) {
				release_substream_urbs(subs, 0);
				return -ENOMEM;
			}
			if (! u->urb)
				goto out_of_memory;
			u->urb->transfer_buffer = subs->syncbuf + i * 4;
			u->urb->transfer_dma = subs->sync_dma + i * 4;
			u->urb->transfer_buffer_length = 4;
			u->urb->pipe = subs->syncpipe;
			u->urb->transfer_flags = URB_ISO_ASAP;
			u->urb->transfer_flags = URB_ISO_ASAP |
						 URB_NO_TRANSFER_DMA_MAP;
			u->urb->number_of_packets = 1;
			u->urb->interval = 1 << subs->syncinterval;
			u->urb->context = u;
@@ -1029,6 +1039,10 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
		}
	}
	return 0;

out_of_memory:
	release_substream_urbs(subs, 0);
	return -ENOMEM;
}


@@ -2036,7 +2050,7 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat
		subs->ops = audio_urb_ops_high_speed[stream];
	snd_pcm_lib_preallocate_pages(as->pcm->streams[stream].substream,
				      SNDRV_DMA_TYPE_CONTINUOUS,
				      snd_dma_continuous_data(GFP_KERNEL),
				      snd_dma_continuous_data(GFP_NOIO),
				      64 * 1024, 128 * 1024);
	snd_pcm_set_ops(as->pcm, stream,
			stream == SNDRV_PCM_STREAM_PLAYBACK ?
+13 −4
Original line number Diff line number Diff line
@@ -765,7 +765,10 @@ static snd_rawmidi_ops_t snd_usbmidi_input_ops = {
static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
{
	if (ep->urb) {
		kfree(ep->urb->transfer_buffer);
		usb_buffer_free(ep->umidi->chip->dev,
				ep->urb->transfer_buffer_length,
				ep->urb->transfer_buffer,
				ep->urb->transfer_dma);
		usb_free_urb(ep->urb);
	}
	kfree(ep);
@@ -799,7 +802,8 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
	else
		pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep);
	length = usb_maxpacket(umidi->chip->dev, pipe, 0);
	buffer = kmalloc(length, GFP_KERNEL);
	buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL,
				  &ep->urb->transfer_dma);
	if (!buffer) {
		snd_usbmidi_in_endpoint_delete(ep);
		return -ENOMEM;
@@ -812,6 +816,7 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
		usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, length,
				  snd_usb_complete_callback(snd_usbmidi_in_urb_complete),
				  ep);
	ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;

	rep->in = ep;
	return 0;
@@ -835,7 +840,9 @@ static void snd_usbmidi_out_endpoint_delete(snd_usb_midi_out_endpoint_t* ep)
	if (ep->tasklet.func)
		tasklet_kill(&ep->tasklet);
	if (ep->urb) {
		kfree(ep->urb->transfer_buffer);
		usb_buffer_free(ep->umidi->chip->dev, ep->max_transfer,
				ep->urb->transfer_buffer,
				ep->urb->transfer_dma);
		usb_free_urb(ep->urb);
	}
	kfree(ep);
@@ -867,7 +874,8 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
	/* we never use interrupt output pipes */
	pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
	ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1);
	buffer = kmalloc(ep->max_transfer, GFP_KERNEL);
	buffer = usb_buffer_alloc(umidi->chip->dev, ep->max_transfer,
				  GFP_KERNEL, &ep->urb->transfer_dma);
	if (!buffer) {
		snd_usbmidi_out_endpoint_delete(ep);
		return -ENOMEM;
@@ -875,6 +883,7 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
	usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer,
			  ep->max_transfer,
			  snd_usb_complete_callback(snd_usbmidi_out_urb_complete), ep);
	ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;

	spin_lock_init(&ep->buffer_lock);
	tasklet_init(&ep->tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep);