<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.220   -&gt; 1.221  
#	drivers/usb/auerswald.c	1.3     -&gt; 1.4    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/02/06	greg@soap.kroah.net	1.221
# patch from Wolfgang Mües &lt;wmues@nexgo.de&gt; for the usb auerswald.c driver:
#   	- Code-Review from Oliver Neukum: remove SMP races.
#   	- Added some wake_up calls after auerbuf_releasebuf to wake up tasks waiting
#   	  for cp buffers.
#   	- Change the module count handling to automatic (owner: THIS_MODULE).
# --------------------------------------------
#
diff -Nru a/drivers/usb/auerswald.c b/drivers/usb/auerswald.c
--- a/drivers/usb/auerswald.c	Wed Feb  6 20:47:18 2002
+++ b/drivers/usb/auerswald.c	Wed Feb  6 20:47:18 2002
@@ -49,7 +49,7 @@
 
 /*-------------------------------------------------------------------*/
 /* Version Information */
-#define DRIVER_VERSION "0.9.9"
+#define DRIVER_VERSION "0.9.11"
 #define DRIVER_AUTHOR  "Wolfgang Mües &lt;wmues@nexgo.de&gt;"
 #define DRIVER_DESC    "Auerswald PBX/System Telephone usb driver"
 
@@ -191,6 +191,13 @@
         struct list_head free_list;     /* list of available elements */
 } auerchain_t,*pauerchain_t;
 
+/* urb blocking completion helper struct */
+typedef struct
+{
+	wait_queue_head_t wqh;    	/* wait for completion */
+	unsigned int done;		/* completion flag */
+} auerchain_chs_t,*pauerchain_chs_t;
+
 /* ...................................................................*/
 /* buffer element */
 struct  auerbufctl;                     /* forward */
@@ -330,7 +337,7 @@
                 urb    = acep-&gt;urbp;
                 dbg ("auerchain_complete: submitting next urb from chain");
 		urb-&gt;status = 0;	/* needed! */
-		result = usb_submit_urb( urb);
+		result = usb_submit_urb(urb, GFP_KERNEL);
 
                 /* check for submit errors */
                 if (result) {
@@ -408,7 +415,7 @@
         if (acep) {
                 dbg("submitting urb immediate");
 		urb-&gt;status = 0;	/* needed! */
-                result = usb_submit_urb( urb);
+                result = usb_submit_urb(urb, GFP_KERNEL);
                 /* check for submit errors */
                 if (result) {
                         urb-&gt;status = result;
@@ -600,8 +607,10 @@
 /* completion handler for synchronous chained URBs */
 static void auerchain_blocking_completion (struct urb *urb)
 {
-	wait_queue_head_t *wakeup = (wait_queue_head_t *)urb-&gt;context;
-	wake_up (wakeup);
+	pauerchain_chs_t pchs = (pauerchain_chs_t)urb-&gt;context;
+	pchs-&gt;done = 1;
+	wmb();
+	wake_up (&amp;pchs-&gt;wqh);
 }
 
 
@@ -609,36 +618,43 @@
 static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int timeout, int* actual_length)
 {
 	DECLARE_WAITQUEUE (wait, current);
-	DECLARE_WAIT_QUEUE_HEAD (wqh);
+	auerchain_chs_t chs;
 	int status;
 
 	dbg ("auerchain_start_wait_urb called");
-	init_waitqueue_head (&amp;wqh);
-	current-&gt;state = TASK_INTERRUPTIBLE;
-	add_wait_queue (&amp;wqh, &amp;wait);
-	urb-&gt;context = &amp;wqh;
-	status = auerchain_submit_urb ( acp, urb);
+	init_waitqueue_head (&amp;chs.wqh);
+	chs.done = 0;
+
+	set_current_state (TASK_UNINTERRUPTIBLE);
+	add_wait_queue (&amp;chs.wqh, &amp;wait);
+	urb-&gt;context = &amp;chs;
+	status = auerchain_submit_urb (acp, urb);
 	if (status) {
 		/* something went wrong */
-		current-&gt;state = TASK_RUNNING;
-		remove_wait_queue (&amp;wqh, &amp;wait);
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&amp;chs.wqh, &amp;wait);
 		return status;
 	}
 
-	if (urb-&gt;status == -EINPROGRESS) {
-		while (timeout &amp;&amp; urb-&gt;status == -EINPROGRESS)
-			status = timeout = schedule_timeout (timeout);
-	} else
-		status = 1;
-
-	current-&gt;state = TASK_RUNNING;
-	remove_wait_queue (&amp;wqh, &amp;wait);
+	while (timeout &amp;&amp; !chs.done)
+	{
+		timeout = schedule_timeout (timeout);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		rmb();
+	}
 
-	if (!status) {
-		/* timeout */
-		dbg ("auerchain_start_wait_urb: timeout");
-		auerchain_unlink_urb (acp, urb);  /* remove urb safely */
-		status = -ETIMEDOUT;
+	set_current_state (TASK_RUNNING);
+	remove_wait_queue (&amp;chs.wqh, &amp;wait);
+
+	if (!timeout &amp;&amp; !chs.done) {
+		if (urb-&gt;status != -EINPROGRESS) {	/* No callback?!! */
+			dbg ("auerchain_start_wait_urb: raced timeout");
+			status = urb-&gt;status;
+		} else {
+			dbg ("auerchain_start_wait_urb: timeout");
+			auerchain_unlink_urb (acp, urb);  /* remove urb safely */
+			status = -ETIMEDOUT;
+		}
 	} else
 		status = urb-&gt;status;
 
@@ -932,6 +948,8 @@
 			/* reuse the buffer */
 			err ("control read: transmission error %d, can not retry", urb-&gt;status);
 			auerbuf_releasebuf (bp);
+			/* Wake up all processes waiting for a buffer */
+			wake_up (&amp;cp-&gt;bufferwait);
 			return;
 		}
 		bp-&gt;retries++;
@@ -1128,7 +1146,7 @@
         FILL_INT_URB (cp-&gt;inturbp, cp-&gt;usbdev, usb_rcvintpipe (cp-&gt;usbdev,AU_IRQENDP), cp-&gt;intbufp, irqsize, auerswald_int_complete, cp, ep-&gt;bInterval);
         /* start the urb */
 	cp-&gt;inturbp-&gt;status = 0;	/* needed! */
-	ret = usb_submit_urb (cp-&gt;inturbp);
+	ret = usb_submit_urb (cp-&gt;inturbp, GFP_KERNEL);
 
 intoend:
         if (ret &lt; 0) {
@@ -1376,9 +1394,6 @@
 	}
 	up (&amp;dev_table_mutex);
 
-	/* prevent module unloading */
-	MOD_INC_USE_COUNT;
-
 	/* we have access to the device. Now lets allocate memory */
 	ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL);
 	if (ccp == NULL) {
@@ -1415,7 +1430,6 @@
 	/* Error exit */
 ofail:	up (&amp;cp-&gt;mutex);
 	auerchar_delete (ccp);
-  	MOD_DEC_USE_COUNT;
 	return ret;
 }
 
@@ -1568,6 +1582,8 @@
         unsigned long flags;
 	pauerchar_t ccp = (pauerchar_t) file-&gt;private_data;
         pauerbuf_t   bp = NULL;
+	wait_queue_t wait;
+
         dbg ("auerchar_read");
 
 	/* Error checking */
@@ -1630,6 +1646,11 @@
 
 	/* a read buffer is not available. Try to get the next data block. */
 doreadlist:
+	/* Preparing for sleep */
+	init_waitqueue_entry (&amp;wait, current);
+	set_current_state (TASK_INTERRUPTIBLE);
+	add_wait_queue (&amp;ccp-&gt;readwait, &amp;wait);
+
 	bp = NULL;
 	spin_lock_irqsave (&amp;ccp-&gt;bufctl.lock, flags);
         if (!list_empty (&amp;ccp-&gt;bufctl.rec_buff_list)) {
@@ -1644,20 +1665,25 @@
 	if (bp) {
 		ccp-&gt;readbuf = bp;
 		ccp-&gt;readoffset = AUH_SIZE; /* for headerbyte */
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&amp;ccp-&gt;readwait, &amp;wait);
 		goto doreadbuf;		  /* now we can read! */
 	}
 
 	/* no data available. Should we wait? */
 	if (file-&gt;f_flags &amp; O_NONBLOCK) {
                 dbg ("No read buffer available, returning -EAGAIN");
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&amp;ccp-&gt;readwait, &amp;wait);
 		up (&amp;ccp-&gt;readmutex);
 		up (&amp;ccp-&gt;mutex);
-                return -EAGAIN;  /* nonblocking, no data available */
+		return -EAGAIN;  /* nonblocking, no data available */
         }
 
 	/* yes, we should wait! */
 	up (&amp;ccp-&gt;mutex); /* allow other operations while we wait */
-	interruptible_sleep_on (&amp;ccp-&gt;readwait);
+	schedule();
+	remove_wait_queue (&amp;ccp-&gt;readwait, &amp;wait);
 	if (signal_pending (current)) {
 		/* waked up by a signal */
 		up (&amp;ccp-&gt;readmutex);
@@ -1688,6 +1714,7 @@
         pauerbuf_t bp;
         unsigned long flags;
 	int ret;
+	wait_queue_t wait;
 
         dbg ("auerchar_write %d bytes", len);
 
@@ -1724,6 +1751,11 @@
 		up (&amp;ccp-&gt;mutex);
 		return -EIO;
 	}
+	/* Prepare for sleep */
+	init_waitqueue_entry (&amp;wait, current);
+	set_current_state (TASK_INTERRUPTIBLE);
+	add_wait_queue (&amp;cp-&gt;bufferwait, &amp;wait);
+
 	/* Try to get a buffer from the device pool.
 	   We can't use a buffer from ccp-&gt;bufctl because the write
 	   command will last beond a release() */
@@ -1744,16 +1776,22 @@
 
 		/* NONBLOCK: don't wait */
 		if (file-&gt;f_flags &amp; O_NONBLOCK) {
+			set_current_state (TASK_RUNNING);
+			remove_wait_queue (&amp;cp-&gt;bufferwait, &amp;wait);
 			return -EAGAIN;
 		}
 
 		/* BLOCKING: wait */
-		interruptible_sleep_on (&amp;cp-&gt;bufferwait);
+		schedule();
+		remove_wait_queue (&amp;cp-&gt;bufferwait, &amp;wait);
 		if (signal_pending (current)) {
 			/* waked up by a signal */
 			return -ERESTARTSYS;
 		}
 		goto write_again;
+	} else {
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&amp;cp-&gt;bufferwait, &amp;wait);
 	}
 
 	/* protect against too big write requests */
@@ -1763,6 +1801,8 @@
 	if (copy_from_user ( bp-&gt;bufp+AUH_SIZE, buf, len)) {
 		dbg ("copy_from_user failed");
 		auerbuf_releasebuf (bp);
+		/* Wake up all processes waiting for a buffer */
+		wake_up (&amp;cp-&gt;bufferwait);
 		up (&amp;cp-&gt;mutex);
 		up (&amp;ccp-&gt;mutex);
 		return -EIO;
@@ -1787,6 +1827,8 @@
 	if (ret) {
 		dbg ("auerchar_write: nonzero result of auerchain_submit_urb %d", ret);
 		auerbuf_releasebuf (bp);
+		/* Wake up all processes waiting for a buffer */
+		wake_up (&amp;cp-&gt;bufferwait);
 		up (&amp;ccp-&gt;mutex);
 		return -EIO;
 	}
@@ -1831,9 +1873,6 @@
 	up (&amp;ccp-&gt;mutex);
 	auerchar_delete (ccp);
 
-	/* release the module */
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
@@ -2154,3 +2193,4 @@
 module_exit (auerswald_cleanup);
 
 /* --------------------------------------------------------------------- */
+
</pre></body></html>