Hi, this fixes several deadlocks in the write path, does a general cleanup of locking and closes reentrancy races in read and write. Please test.
Regards Oliver You can import this changeset into BK by piping this whole message to: '| bk receive [path to repository]' or apply the patch as usual. =================================================================== [EMAIL PROTECTED], 2003-01-11 17:57:07+01:00, [EMAIL PROTECTED] - locking cleanup usb-midi.c | 67 ++++++++++++++++++++++++------------------------------------- 1 files changed, 27 insertions(+), 40 deletions(-) diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c --- a/drivers/usb/class/usb-midi.c Sat Jan 11 17:58:06 2003 +++ b/drivers/usb/class/usb-midi.c Sat Jan 11 17:58:06 2003 @@ -172,8 +172,8 @@ struct usb_device *usbdev; int endpoint; - spinlock_t lock; - wait_queue_head_t wait; + struct semaphore sem; + struct completion wait; unsigned char *buf; int bufWrPtr; @@ -205,6 +205,7 @@ struct list_head list; struct usb_midi_state *midi; + struct semaphore threadsem; int dev_midi; mode_t open_mode; @@ -312,8 +313,7 @@ { struct midi_out_endpoint *ep = (struct midi_out_endpoint *)urb->context; - if ( waitqueue_active( &ep->wait ) ) - wake_up_interruptible( &ep->wait ); + complete( &ep->wait ); } @@ -326,7 +326,7 @@ int maxretry = 50; DECLARE_WAITQUEUE(wait,current); - init_waitqueue_head(&ep->wait); + init_complete(&ep->wait); d = ep->usbdev; pipe = usb_sndbulkpipe(d, ep->endpoint); @@ -341,19 +341,7 @@ goto error; } - add_wait_queue( &ep->wait, &wait ); - set_current_state( TASK_INTERRUPTIBLE ); - - while( ep->urb->status == -EINPROGRESS ) { - if ( maxretry-- < 0 ) { - printk(KERN_ERR "usbmidi: usb_bulk_msg timed out\n"); - ret = -ETIME; - break; - } - interruptible_sleep_on_timeout( &ep->wait, 10 ); - } - set_current_state( TASK_RUNNING ); - remove_wait_queue( &ep->wait, &wait ); + wait_for_completion(&ep->wait); error: return ret; @@ -507,7 +495,6 @@ static int put_one_midi_event(struct usb_mididev *m) { int cin; - unsigned long flags; struct midi_out_endpoint *ep = m->mout.ep; int ret=0; @@ -516,7 +503,7 @@ return -EINVAL; } - spin_lock_irqsave( &ep->lock, flags ); + down( &ep->sem ); 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]; @@ -524,7 +511,7 @@ if ( ep->bufWrPtr >= ep->bufSize ) { ret = flush_midi_buffer( ep ); } - spin_unlock_irqrestore( &ep->lock, flags); + up( &ep->sem ); m->mout.buf[0] = m->mout.buf[1] = m->mout.buf[2] = 0; m->mout.bufPtr = 0; @@ -547,11 +534,11 @@ if ( m->singlebyte != 0 ) { /** Simple code to handle the single-byte USB-MIDI protocol. */ - spin_lock_irqsave( &ep->lock, flags ); + down( &ep->sem ); if ( ep->bufWrPtr+4 > ep->bufSize ) { ret = flush_midi_buffer( ep ); if ( !ret ) { - spin_unlock_irqrestore( &ep->lock, flags ); + up( &ep->sem ); return ret; } } @@ -562,7 +549,7 @@ if ( ep->bufWrPtr >= ep->bufSize ) { ret = flush_midi_buffer( ep ); } - spin_unlock_irqrestore( &ep->lock, flags ); + up( &ep->sem ); return ret; } @@ -574,9 +561,9 @@ sysrt_buf[1] = c; sysrt_buf[2] = 0; sysrt_buf[3] = 0; - spin_lock_irqsave( &ep->lock, flags ); + down( &ep->sem ); ret = usb_write( ep, sysrt_buf, 4 ); - spin_unlock_irqrestore( &ep->lock, flags ); + up( &ep->sem ); /* m->mout.lastEvent = 0; */ return ret; @@ -662,6 +649,7 @@ return 0; } + down(&m->threadsem); add_wait_queue( &ep->wait, &wait ); ret = 0; while( count > 0 ) { @@ -722,6 +710,7 @@ remove_wait_queue( &ep->wait, &wait ); set_current_state(TASK_RUNNING); + up(&m->threadsem); return ret; } @@ -740,7 +729,6 @@ { struct usb_mididev *m = (struct usb_mididev *)file->private_data; ssize_t ret; - unsigned long int flags; if ( ppos != &file->f_pos ) { return -ESPIPE; @@ -752,6 +740,7 @@ return 0; } + down(&m->threadsem); ret = 0; while( count > 0 ) { unsigned char c; @@ -771,11 +760,12 @@ ret++; } - spin_lock_irqsave( &m->mout.ep->lock, flags ); + down( &m->mout.ep->sem ); if ( flush_midi_buffer(m->mout.ep) < 0 ) { ret = -EFAULT; } - spin_unlock_irqrestore( &m->mout.ep->lock, flags ); + up( &m->mout.ep->sem ); + up(&m->threadsem); return ret; } @@ -803,10 +793,10 @@ if ( file->f_mode & FMODE_WRITE ) { poll_wait( file, &oep->wait, wait ); - spin_lock_irqsave( &oep->lock, flags ); + down( &oep->sem ); if ( oep->bufWrPtr < oep->bufSize ) mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore( &oep->lock, flags ); + up( &oep->sem ); } return mask; @@ -884,18 +874,17 @@ m->mout.bufRemains = 0; m->mout.isInExclusive = 0; m->mout.lastEvent = 0; - spin_lock_init(&m->mout.ep->lock); + init_MUTEX(&m->mout.ep->sem); } if ( (file->f_mode & FMODE_READ) && m->min.ep != NULL ) { - unsigned long int flagsep; - spin_lock_irqsave( &m->min.ep->lock, flagsep ); + spin_lock( &m->min.ep->lock ); m->min.ep->cables[m->min.cableId] = m; m->min.ep->readers += 1; m->min.bufRdPtr = 0; m->min.bufWrPtr = 0; m->min.bufRemains = 0; - spin_unlock_irqrestore( &m->min.ep->lock, flagsep ); + spin_unlock( &m->min.ep->lock ); if ( !(m->min.ep->urbSubmitted)) { @@ -968,8 +957,6 @@ } if ( m->open_mode & FMODE_READ ) { - unsigned long int flagsep; - spin_lock_irqsave( &m->min.ep->lock, flagsep ); m->min.ep->cables[m->min.cableId] = 0; // discard cable m->min.ep->readers -= 1; m->open_mode &= ~FMODE_READ; @@ -978,10 +965,9 @@ m->min.ep->urbSubmitted = 0; usb_unlink_urb(m->min.ep->urb); } - spin_unlock_irqrestore( &m->min.ep->lock, flagsep ); } - s->count--; + s->count = 0; up(&open_sem); wake_up(&open_wait); @@ -1162,6 +1148,7 @@ } memset(m, 0, sizeof(struct usb_mididev)); + init_MUTEX(&m->threadsem); if ((m->dev_midi = register_sound_midi(&usb_midi_fops, -1)) < 0) { printk(KERN_ERR "usbmidi: cannot register midi device\n"); @@ -2028,7 +2015,7 @@ /* ------------------------------------------------------------------------- */ -static int usb_midi_probe(struct usb_interface *intf, +static int usb_midi_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_midi_state *s; =================================================================== This BitKeeper patch contains the following changesets: 1.1250 ## Wrapped with gzip_uu ## begin 664 bkpatch2445 M'XL(`!Y-(#X``ZU6:V_3,!3]'/^**TV:!B.M'W&<=.HT6">H`#$-)O&M2E.W MC=K&51X,I/QX_`C9JY0!JRI=U_?XY-Q[3]T>P'4IBX&GUMDW6:`#>*?*2G^4 MN<IE;ZDV<IWE]?>>*A8Z>:643O;-=M^=Z$]7?E5(6?8WV2RC'&G495*E2]#) M<N"1'NMVJA];.?"N+MY>?WA]A=!P".?+)%_(S[*"X1!-5V>S6JY[JT(E2_/` MIDLW%&-"".68\9#PAD:,!0T)\72FES,JXODTC)&3=+9+_'TNIMDPQ4&DN1B- MJ$`C(#W##YCU,>D3`D0,N!A@<8S)`&/8PPW'!'R,WL#_5W".4O!AK=)5EB\@ M7<LDK[?H/6B108PN;QN&_+]\(803C$YA4<C%F1.8JDTS*TQ99;\NI_UTG91V MY9M9]E*CF>(0QSCDC$<-81SC)J0!$VS*YF**8\GEOL[\D=X,@I"0"QPV!$<B MMK;8=\HXY=EKV.N<I]2`2:P-11K"@X!8,U'ZR$KA4ZQ$!?C!<YJI-1&H.=P4 M627;355*V-3K*JN6A4QFQFY%DDKM-3>'3^`7-_:MO7.Y=R3_X,41$1PH&A,1 MZN"555&G%91RDVR7JI``9GW2)?24MVM992H'N$FRZ@2-*19`'I_T7#GV](@1 M^Q!&0@-M2>01',JM?VIXX(5!T5BGQRYX69Y5DP[:(2TP"(`PC>26SVQ/YJJ8 MW*J[C^<$:YP.EM\%;Z9N\E:!%FD%<"HLP`:OWCY,<VS3-G@["7C@$(%%>#LX M0FX1-NS*"R?!AMW/$*X*&QXSC,,PZ,H[W/BGW1Q,4M"@+>UA:B0"9G@%__WQ MD1"V/A=^B=.@C:JKWEV10D0.&!E768T[8#MU1-@,=>Q"UP%UESW"L8/<:<%] M0&2[Z(+GK/3Q^LO%UZ.',BPZ)L:=44PMNMQF^<3<_*WH++=@L^/(8UN;"RV\ MSO<<B(7A'\41,2Z,(]M#%[S2/TU5G>O?7<!Z/OH*#CKSWRJ^UR"*F2$:M[&L MDBI+(=,<^B:8F)M@LBW45!ZU7TFSJ[.RF.MK!5[JY?S5[;^#="G355EOAB2B .:2#T%?P3&[G%(8H(```` ` end ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel