static void usb_write_callback(struct urb *urb, struct pt_regs *regs)
{
        struct midi_out_endpoint *ep = (struct midi_out_endpoint *)urb->context;

        if ( waitqueue_active( &ep->wait ) )
                wake_up_interruptible( &ep->wait );
}

Always wake up unconditionally.

                if ( maxretry-- < 0 ) {
                        printk(KERN_ERR "usbmidi: usb_bulk_msg timed out\n");
                        ret = -ETIME;
                        break;
                }
                interruptible_sleep_on_timeout( &ep->wait, 10 );

Broken, use an if in conjunction with schedule.
If you want a timeout you have to unlink the urb if it occurs.

        /* urb->dev must be reinitialized on 2.4.x kernels */
        urb->dev = ep->usbdev;

        urb->actual_length = 0;
        usb_submit_urb(urb, GFP_KERNEL);

Must be GFP_ATOMIC, you are in interrupt.


/* This routine must be called with spin_lock */

/** Wrapper around usb_write().
 *  This routine must be called with spin_lock held on ep.
 *  Called by midiWrite(), putOneMidiEvent(), and  usb_midi_write();
 **/

On the contrary, calling this with a spinlock held is absolutely inadmissable.


        spin_lock_irqsave( &ep->lock, flags );
        ep->buf[ep->bufWrPtr++] = (m->mout.cableId<<4) | cin;
        ep->buf[ep->bufWrPtr++] = m->mout.buf[0];
        ep->buf[ep->bufWrPtr++] = m->mout.buf[1];
        ep->buf[ep->bufWrPtr++] = m->mout.buf[2];
        if ( ep->bufWrPtr >= ep->bufSize ) {
                ret = flush_midi_buffer( ep );
        }
        spin_unlock_irqrestore( &ep->lock, flags);

You _must_ use a semaphore. flush_midi_buffer() sleeps.

                spin_lock_irqsave( &ep->lock, flags );
                if ( ep->bufWrPtr+4 > ep->bufSize ) {
                        ret = flush_midi_buffer( ep );
                        if ( !ret ) {
                                spin_unlock_irqrestore( &ep->lock, flags );
                                return ret;

Same here. Use a semaphore. As well as several times more in this
function. And other functions.


                        spin_lock_irqsave( &ep->lock, flags );
                        for (i = 0; i < cnt; i++) {
                                if ( copy_to_user( buffer+i, 
m->min.buf+m->min.bufRdPtr, 1 ) ) {
                                        if ( !ret )
                                                ret = -EFAULT;
                                        break;

copy_to_user() with spinlock held. Absolutely _forbidden_


                __set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue( &open_wait, &wait );
                up(&open_sem);
                schedule();
                __set_current_state(TASK_RUNNING);
                remove_wait_queue( &open_wait, &wait );

What's that supposed to do ?


        s->count--;

No, no, no. This is release. The count _is_ zero.

Has anybody ever looked at this driver?

        HTH
                Oliver



-------------------------------------------------------
This SF.NET email is sponsored by: Order your Holiday Geek Presents Now!
Green Lasers, Hip Geek T-Shirts, Remote Control Tanks, Caffeinated Soap,
MP3 Players,  XBox Games,  Flying Saucers,  WebCams,  Smart Putty.
T H I N K G E E K . C O M       http://www.thinkgeek.com/sf/
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to