ALSA: line6: Enable different number of URBs for frame transfers
authorAndrej Krutak <dev@andree.sk>
Sun, 18 Sep 2016 18:59:21 +0000 (20:59 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 19 Sep 2016 20:58:08 +0000 (22:58 +0200)
This basically changes LINE6_ISO_BUFFERS constant to a configurable
iso_buffers property.

Signed-off-by: Andrej Krutak <dev@andree.sk>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/line6/capture.c
sound/usb/line6/driver.c
sound/usb/line6/driver.h
sound/usb/line6/pcm.c
sound/usb/line6/pcm.h
sound/usb/line6/playback.c

index f518fbbe88de2efb884332b91a1ab91b895c2b3f..c2808a0b771a400def8ef7807abd6df040e8a6ca 100644 (file)
@@ -29,10 +29,10 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
        int ret;
        struct urb *urb_in;
 
-       index =
-           find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS);
+       index = find_first_zero_bit(&line6pcm->in.active_urbs,
+                                   line6pcm->line6->iso_buffers);
 
-       if (index < 0 || index >= LINE6_ISO_BUFFERS) {
+       if (index < 0 || index >= line6pcm->line6->iso_buffers) {
                dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
                return -EINVAL;
        }
@@ -73,7 +73,7 @@ int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)
 {
        int ret = 0, i;
 
-       for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+       for (i = 0; i < line6pcm->line6->iso_buffers; ++i) {
                ret = submit_audio_in_urb(line6pcm);
                if (ret < 0)
                        break;
@@ -154,7 +154,7 @@ static void audio_in_callback(struct urb *urb)
        line6pcm->in.last_frame = urb->start_frame;
 
        /* find index of URB */
-       for (index = 0; index < LINE6_ISO_BUFFERS; ++index)
+       for (index = 0; index < line6pcm->line6->iso_buffers; ++index)
                if (urb == line6pcm->in.urbs[index])
                        break;
 
@@ -247,8 +247,13 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
        struct usb_line6 *line6 = line6pcm->line6;
        int i;
 
+       line6pcm->in.urbs = kzalloc(
+               sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL);
+       if (line6pcm->in.urbs == NULL)
+               return -ENOMEM;
+
        /* create audio URBs and fill in constant values: */
-       for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+       for (i = 0; i < line6->iso_buffers; ++i) {
                struct urb *urb;
 
                /* URB for audio in: */
index 81b7da8e56d39e352a5b629bbdf73aa460889b4d..527c4086f6fc3d6c48d7ba47af90c8e8e9796ac0 100644 (file)
@@ -467,6 +467,7 @@ static void line6_get_interval(struct usb_line6 *line6)
        unsigned epnum = usb_pipeendpoint(pipe);
 
        ep = usbdev->ep_in[epnum];
+       line6->iso_buffers = LINE6_ISO_BUFFERS;
        if (ep) {
                line6->interval = ep->desc.bInterval;
                line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
index 7da643e79e3b50426c3cbaf4d46184d7283f3848..43dd1d06b5facfa736d20f59cfa69733fc58f902 100644 (file)
@@ -111,6 +111,8 @@ struct usb_line6 {
 
        /* Interval (ms) */
        int interval;
+       /* Number of isochronous URBs used for frame transfers */
+       int iso_buffers;
 
        /* Maximum size of USB packet */
        int max_packet_size;
index 41aa3355e920499830aeefdaf961659dfcabdba3..317ba68446c64e1f322df49605d323dcbba4002e 100644 (file)
@@ -104,7 +104,7 @@ static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
 {
        int i;
 
-       for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
+       for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
                if (test_bit(i, &pcms->active_urbs)) {
                        if (!test_and_set_bit(i, &pcms->unlink_urbs))
                                usb_unlink_urb(pcms->urbs[i]);
@@ -124,7 +124,7 @@ static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
 
        do {
                alive = 0;
-               for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
+               for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
                        if (test_bit(i, &pcms->active_urbs))
                                alive++;
                }
@@ -153,7 +153,8 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
 {
        /* Invoked multiple times in a row so allocate once only */
        if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
-               pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
+               pstr->buffer = kmalloc(line6pcm->line6->iso_buffers *
+                                      LINE6_ISO_PACKETS *
                                       line6pcm->max_packet_size, GFP_KERNEL);
                if (!pstr->buffer)
                        return -ENOMEM;
@@ -434,24 +435,30 @@ static struct snd_kcontrol_new line6_controls[] = {
 /*
        Cleanup the PCM device.
 */
-static void cleanup_urbs(struct line6_pcm_stream *pcms)
+static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers)
 {
        int i;
 
-       for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
+       /* Most likely impossible in current code... */
+       if (pcms->urbs == NULL)
+               return;
+
+       for (i = 0; i < iso_buffers; i++) {
                if (pcms->urbs[i]) {
                        usb_kill_urb(pcms->urbs[i]);
                        usb_free_urb(pcms->urbs[i]);
                }
        }
+       kfree(pcms->urbs);
+       pcms->urbs = NULL;
 }
 
 static void line6_cleanup_pcm(struct snd_pcm *pcm)
 {
        struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
 
-       cleanup_urbs(&line6pcm->out);
-       cleanup_urbs(&line6pcm->in);
+       cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers);
+       cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers);
        kfree(line6pcm);
 }
 
index 508410adbd517e9017d1c2db7ec251f216794c9a..e983880703ea9a76b5d17224d9e7c407c8a16ea5 100644 (file)
@@ -90,7 +90,7 @@ struct line6_pcm_properties {
 
 struct line6_pcm_stream {
        /* allocated URBs */
-       struct urb *urbs[LINE6_ISO_BUFFERS];
+       struct urb **urbs;
 
        /* Temporary buffer;
         * Since the packet size is not known in advance, this buffer is
index 97ed593f6010f6dccf4e5eb5db39e4a2381a7692..1380facda4276b3c9b354e3633c3b68ffe151a19 100644 (file)
@@ -154,10 +154,10 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
                (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
        struct urb *urb_out;
 
-       index =
-           find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS);
+       index = find_first_zero_bit(&line6pcm->out.active_urbs,
+                                   line6pcm->line6->iso_buffers);
 
-       if (index < 0 || index >= LINE6_ISO_BUFFERS) {
+       if (index < 0 || index >= line6pcm->line6->iso_buffers) {
                dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
                return -EINVAL;
        }
@@ -286,7 +286,7 @@ int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
 {
        int ret = 0, i;
 
-       for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+       for (i = 0; i < line6pcm->line6->iso_buffers; ++i) {
                ret = submit_audio_out_urb(line6pcm);
                if (ret < 0)
                        break;
@@ -313,11 +313,11 @@ static void audio_out_callback(struct urb *urb)
        line6pcm->out.last_frame = urb->start_frame;
 
        /* find index of URB */
-       for (index = 0; index < LINE6_ISO_BUFFERS; index++)
+       for (index = 0; index < line6pcm->line6->iso_buffers; index++)
                if (urb == line6pcm->out.urbs[index])
                        break;
 
-       if (index >= LINE6_ISO_BUFFERS)
+       if (index >= line6pcm->line6->iso_buffers)
                return;         /* URB has been unlinked asynchronously */
 
        for (i = 0; i < LINE6_ISO_PACKETS; i++)
@@ -401,8 +401,13 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
        struct usb_line6 *line6 = line6pcm->line6;
        int i;
 
+       line6pcm->out.urbs = kzalloc(
+               sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL);
+       if (line6pcm->out.urbs == NULL)
+               return -ENOMEM;
+
        /* create audio URBs and fill in constant values: */
-       for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+       for (i = 0; i < line6->iso_buffers; ++i) {
                struct urb *urb;
 
                /* URB for audio out: */