From: Greg KH To: torvalds@transmeta.com Cc: linux-usb-devel@lists.sourceforge.net Subject: [PATCH 01 of 16] USB audio driver change Hi, Here's a patch against 2.5.3-pre3 for the USB audio driver that converts it to dynamically allocate its urbs. The majority of the patches in this set are changes like this. The reason I am making these changes, is that we want to move to a proper reference counting scheme for USB urbs. To do that, and to keep things simpler, all USB drivers need to dynamically allocate their urbs. thanks, greg k-h diff -Nru a/drivers/usb/audio.c b/drivers/usb/audio.c --- a/drivers/usb/audio.c Tue Jan 22 12:54:24 2002 +++ b/drivers/usb/audio.c Tue Jan 22 12:54:24 2002 @@ -297,12 +297,12 @@ #define FLG_CONNECTED 32 struct my_data_urb { - struct urb urb; + struct urb *urb; struct usb_iso_packet_descriptor isoframe[DESCFRAMES]; }; struct my_sync_urb { - struct urb urb; + struct urb *urb; struct usb_iso_packet_descriptor isoframe[SYNCFRAMES]; }; @@ -648,27 +648,27 @@ spin_unlock_irqrestore(&as->lock, flags); if (notkilled && signal_pending(current)) { if (i & FLG_URB0RUNNING) - usb_unlink_urb(&u->durb[0].urb); + usb_unlink_urb(u->durb[0].urb); if (i & FLG_URB1RUNNING) - usb_unlink_urb(&u->durb[1].urb); + usb_unlink_urb(u->durb[1].urb); if (i & FLG_SYNC0RUNNING) - usb_unlink_urb(&u->surb[0].urb); + usb_unlink_urb(u->surb[0].urb); if (i & FLG_SYNC1RUNNING) - usb_unlink_urb(&u->surb[1].urb); + usb_unlink_urb(u->surb[1].urb); notkilled = 0; } } set_current_state(TASK_RUNNING); - if (u->durb[0].urb.transfer_buffer) - kfree(u->durb[0].urb.transfer_buffer); - if (u->durb[1].urb.transfer_buffer) - kfree(u->durb[1].urb.transfer_buffer); - if (u->surb[0].urb.transfer_buffer) - kfree(u->surb[0].urb.transfer_buffer); - if (u->surb[1].urb.transfer_buffer) - kfree(u->surb[1].urb.transfer_buffer); - u->durb[0].urb.transfer_buffer = u->durb[1].urb.transfer_buffer = - u->surb[0].urb.transfer_buffer = u->surb[1].urb.transfer_buffer = NULL; + if (u->durb[0].urb->transfer_buffer) + kfree(u->durb[0].urb->transfer_buffer); + if (u->durb[1].urb->transfer_buffer) + kfree(u->durb[1].urb->transfer_buffer); + if (u->surb[0].urb->transfer_buffer) + kfree(u->surb[0].urb->transfer_buffer); + if (u->surb[1].urb->transfer_buffer) + kfree(u->surb[1].urb->transfer_buffer); + u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = + u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL; } static inline void usbin_release(struct usb_audiodev *as) @@ -904,9 +904,9 @@ #if 0 printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); #endif - if (urb == &u->durb[0].urb) + if (urb == u->durb[0].urb) mask = FLG_URB0RUNNING; - else if (urb == &u->durb[1].urb) + else if (urb == u->durb[1].urb) mask = FLG_URB1RUNNING; else { mask = 0; @@ -969,9 +969,9 @@ #if 0 printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); #endif - if (urb == &u->surb[0].urb) + if (urb == u->surb[0].urb) mask = FLG_SYNC0RUNNING; - else if (urb == &u->surb[1].urb) + else if (urb == u->surb[1].urb) mask = FLG_SYNC1RUNNING; else { mask = 0; @@ -1017,26 +1017,26 @@ u->phase = 0; maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); bufsz = DESCFRAMES * maxsze; - if (u->durb[0].urb.transfer_buffer) - kfree(u->durb[0].urb.transfer_buffer); - u->durb[0].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL); - u->durb[0].urb.transfer_buffer_length = bufsz; - if (u->durb[1].urb.transfer_buffer) - kfree(u->durb[1].urb.transfer_buffer); - u->durb[1].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL); - u->durb[1].urb.transfer_buffer_length = bufsz; + if (u->durb[0].urb->transfer_buffer) + kfree(u->durb[0].urb->transfer_buffer); + u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); + u->durb[0].urb->transfer_buffer_length = bufsz; + if (u->durb[1].urb->transfer_buffer) + kfree(u->durb[1].urb->transfer_buffer); + u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); + u->durb[1].urb->transfer_buffer_length = bufsz; if (u->syncpipe) { - if (u->surb[0].urb.transfer_buffer) - kfree(u->surb[0].urb.transfer_buffer); - u->surb[0].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); - u->surb[0].urb.transfer_buffer_length = 3*SYNCFRAMES; - if (u->surb[1].urb.transfer_buffer) - kfree(u->surb[1].urb.transfer_buffer); - u->surb[1].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); - u->surb[1].urb.transfer_buffer_length = 3*SYNCFRAMES; + if (u->surb[0].urb->transfer_buffer) + kfree(u->surb[0].urb->transfer_buffer); + u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); + u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES; + if (u->surb[1].urb->transfer_buffer) + kfree(u->surb[1].urb->transfer_buffer); + u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); + u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES; } - if (!u->durb[0].urb.transfer_buffer || !u->durb[1].urb.transfer_buffer || - (u->syncpipe && (!u->surb[0].urb.transfer_buffer || !u->surb[1].urb.transfer_buffer))) { + if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || + (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) { printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum); return 0; } @@ -1048,7 +1048,7 @@ } u->flags |= FLG_RUNNING; if (!(u->flags & FLG_URB0RUNNING)) { - urb = &u->durb[0].urb; + urb = u->durb[0].urb; urb->dev = dev; urb->pipe = u->datapipe; urb->transfer_flags = USB_ISO_ASAP; @@ -1061,7 +1061,7 @@ u->flags &= ~FLG_RUNNING; } if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) { - urb = &u->durb[1].urb; + urb = u->durb[1].urb; urb->dev = dev; urb->pipe = u->datapipe; urb->transfer_flags = USB_ISO_ASAP; @@ -1075,7 +1075,7 @@ } if (u->syncpipe) { if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) { - urb = &u->surb[0].urb; + urb = u->surb[0].urb; urb->dev = dev; urb->pipe = u->syncpipe; urb->transfer_flags = USB_ISO_ASAP; @@ -1089,7 +1089,7 @@ u->flags &= ~FLG_RUNNING; } if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) { - urb = &u->surb[1].urb; + urb = u->surb[1].urb; urb->dev = dev; urb->pipe = u->syncpipe; urb->transfer_flags = USB_ISO_ASAP; @@ -1125,27 +1125,27 @@ spin_unlock_irqrestore(&as->lock, flags); if (notkilled && signal_pending(current)) { if (i & FLG_URB0RUNNING) - usb_unlink_urb(&u->durb[0].urb); + usb_unlink_urb(u->durb[0].urb); if (i & FLG_URB1RUNNING) - usb_unlink_urb(&u->durb[1].urb); + usb_unlink_urb(u->durb[1].urb); if (i & FLG_SYNC0RUNNING) - usb_unlink_urb(&u->surb[0].urb); + usb_unlink_urb(u->surb[0].urb); if (i & FLG_SYNC1RUNNING) - usb_unlink_urb(&u->surb[1].urb); + usb_unlink_urb(u->surb[1].urb); notkilled = 0; } } set_current_state(TASK_RUNNING); - if (u->durb[0].urb.transfer_buffer) - kfree(u->durb[0].urb.transfer_buffer); - if (u->durb[1].urb.transfer_buffer) - kfree(u->durb[1].urb.transfer_buffer); - if (u->surb[0].urb.transfer_buffer) - kfree(u->surb[0].urb.transfer_buffer); - if (u->surb[1].urb.transfer_buffer) - kfree(u->surb[1].urb.transfer_buffer); - u->durb[0].urb.transfer_buffer = u->durb[1].urb.transfer_buffer = - u->surb[0].urb.transfer_buffer = u->surb[1].urb.transfer_buffer = NULL; + if (u->durb[0].urb->transfer_buffer) + kfree(u->durb[0].urb->transfer_buffer); + if (u->durb[1].urb->transfer_buffer) + kfree(u->durb[1].urb->transfer_buffer); + if (u->surb[0].urb->transfer_buffer) + kfree(u->surb[0].urb->transfer_buffer); + if (u->surb[1].urb->transfer_buffer) + kfree(u->surb[1].urb->transfer_buffer); + u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = + u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL; } static inline void usbout_release(struct usb_audiodev *as) @@ -1262,9 +1262,9 @@ #if 0 printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); #endif - if (urb == &u->durb[0].urb) + if (urb == u->durb[0].urb) mask = FLG_URB0RUNNING; - else if (urb == &u->durb[1].urb) + else if (urb == u->durb[1].urb) mask = FLG_URB1RUNNING; else { mask = 0; @@ -1334,9 +1334,9 @@ #if 0 printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); #endif - if (urb == &u->surb[0].urb) + if (urb == u->surb[0].urb) mask = FLG_SYNC0RUNNING; - else if (urb == &u->surb[1].urb) + else if (urb == u->surb[1].urb) mask = FLG_SYNC1RUNNING; else { mask = 0; @@ -1382,26 +1382,26 @@ u->phase = 0; maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); bufsz = DESCFRAMES * maxsze; - if (u->durb[0].urb.transfer_buffer) - kfree(u->durb[0].urb.transfer_buffer); - u->durb[0].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL); - u->durb[0].urb.transfer_buffer_length = bufsz; - if (u->durb[1].urb.transfer_buffer) - kfree(u->durb[1].urb.transfer_buffer); - u->durb[1].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL); - u->durb[1].urb.transfer_buffer_length = bufsz; + if (u->durb[0].urb->transfer_buffer) + kfree(u->durb[0].urb->transfer_buffer); + u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); + u->durb[0].urb->transfer_buffer_length = bufsz; + if (u->durb[1].urb->transfer_buffer) + kfree(u->durb[1].urb->transfer_buffer); + u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); + u->durb[1].urb->transfer_buffer_length = bufsz; if (u->syncpipe) { - if (u->surb[0].urb.transfer_buffer) - kfree(u->surb[0].urb.transfer_buffer); - u->surb[0].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); - u->surb[0].urb.transfer_buffer_length = 3*SYNCFRAMES; - if (u->surb[1].urb.transfer_buffer) - kfree(u->surb[1].urb.transfer_buffer); - u->surb[1].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); - u->surb[1].urb.transfer_buffer_length = 3*SYNCFRAMES; + if (u->surb[0].urb->transfer_buffer) + kfree(u->surb[0].urb->transfer_buffer); + u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); + u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES; + if (u->surb[1].urb->transfer_buffer) + kfree(u->surb[1].urb->transfer_buffer); + u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); + u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES; } - if (!u->durb[0].urb.transfer_buffer || !u->durb[1].urb.transfer_buffer || - (u->syncpipe && (!u->surb[0].urb.transfer_buffer || !u->surb[1].urb.transfer_buffer))) { + if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || + (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) { printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum); return 0; } @@ -1413,7 +1413,7 @@ } u->flags |= FLG_RUNNING; if (!(u->flags & FLG_URB0RUNNING)) { - urb = &u->durb[0].urb; + urb = u->durb[0].urb; urb->dev = dev; urb->pipe = u->datapipe; urb->transfer_flags = USB_ISO_ASAP; @@ -1426,7 +1426,7 @@ u->flags &= ~FLG_RUNNING; } if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) { - urb = &u->durb[1].urb; + urb = u->durb[1].urb; urb->dev = dev; urb->pipe = u->datapipe; urb->transfer_flags = USB_ISO_ASAP; @@ -1440,7 +1440,7 @@ } if (u->syncpipe) { if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) { - urb = &u->surb[0].urb; + urb = u->surb[0].urb; urb->dev = dev; urb->pipe = u->syncpipe; urb->transfer_flags = USB_ISO_ASAP; @@ -1454,7 +1454,7 @@ u->flags &= ~FLG_RUNNING; } if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) { - urb = &u->surb[1].urb; + urb = u->surb[1].urb; urb->dev = dev; urb->pipe = u->syncpipe; urb->transfer_flags = USB_ISO_ASAP; @@ -1921,6 +1921,14 @@ usbout_release(as); dmabuf_release(&as->usbin.dma); dmabuf_release(&as->usbout.dma); + usb_free_urb(as->usbin.durb[0].urb); + usb_free_urb(as->usbin.durb[1].urb); + usb_free_urb(as->usbin.surb[0].urb); + usb_free_urb(as->usbin.surb[1].urb); + usb_free_urb(as->usbout.durb[0].urb); + usb_free_urb(as->usbout.durb[1].urb); + usb_free_urb(as->usbout.surb[0].urb); + usb_free_urb(as->usbout.surb[1].urb); kfree(as); } while (!list_empty(&s->mixerlist)) { @@ -2821,14 +2829,33 @@ init_waitqueue_head(&as->usbin.dma.wait); init_waitqueue_head(&as->usbout.dma.wait); spin_lock_init(&as->lock); - spin_lock_init(&as->usbin.durb[0].urb.lock); - spin_lock_init(&as->usbin.durb[1].urb.lock); - spin_lock_init(&as->usbin.surb[0].urb.lock); - spin_lock_init(&as->usbin.surb[1].urb.lock); - spin_lock_init(&as->usbout.durb[0].urb.lock); - spin_lock_init(&as->usbout.durb[1].urb.lock); - spin_lock_init(&as->usbout.surb[0].urb.lock); - spin_lock_init(&as->usbout.surb[1].urb.lock); + as->usbin.durb[0].urb = usb_alloc_urb(0); + as->usbin.durb[1].urb = usb_alloc_urb(0); + as->usbin.surb[0].urb = usb_alloc_urb(0); + as->usbin.surb[1].urb = usb_alloc_urb(0); + as->usbout.durb[0].urb = usb_alloc_urb(0); + as->usbout.durb[1].urb = usb_alloc_urb(0); + as->usbout.surb[0].urb = usb_alloc_urb(0); + as->usbout.surb[1].urb = usb_alloc_urb(0); + if ((!as->usbin.durb[0].urb) || + (!as->usbin.durb[1].urb) || + (!as->usbin.surb[0].urb) || + (!as->usbin.surb[1].urb) || + (!as->usbout.durb[0].urb) || + (!as->usbout.durb[1].urb) || + (!as->usbout.surb[0].urb) || + (!as->usbout.surb[1].urb)) { + usb_free_urb(as->usbin.durb[0].urb); + usb_free_urb(as->usbin.durb[1].urb); + usb_free_urb(as->usbin.surb[0].urb); + usb_free_urb(as->usbin.surb[1].urb); + usb_free_urb(as->usbout.durb[0].urb); + usb_free_urb(as->usbout.durb[1].urb); + usb_free_urb(as->usbout.surb[0].urb); + usb_free_urb(as->usbout.surb[1].urb); + kfree(as); + return; + } as->state = s; as->usbin.interface = asifin; as->usbout.interface = asifout; @@ -2997,11 +3024,27 @@ } } if (as->numfmtin == 0 && as->numfmtout == 0) { + usb_free_urb(as->usbin.durb[0].urb); + usb_free_urb(as->usbin.durb[1].urb); + usb_free_urb(as->usbin.surb[0].urb); + usb_free_urb(as->usbin.surb[1].urb); + usb_free_urb(as->usbout.durb[0].urb); + usb_free_urb(as->usbout.durb[1].urb); + usb_free_urb(as->usbout.surb[0].urb); + usb_free_urb(as->usbout.surb[1].urb); kfree(as); return; } if ((as->dev_audio = register_sound_dsp(&usb_audio_fops, -1)) < 0) { printk(KERN_ERR "usbaudio: cannot register dsp\n"); + usb_free_urb(as->usbin.durb[0].urb); + usb_free_urb(as->usbin.durb[1].urb); + usb_free_urb(as->usbin.surb[0].urb); + usb_free_urb(as->usbin.surb[1].urb); + usb_free_urb(as->usbout.durb[0].urb); + usb_free_urb(as->usbout.durb[1].urb); + usb_free_urb(as->usbout.surb[0].urb); + usb_free_urb(as->usbout.surb[1].urb); kfree(as); return; }