patch-2.4.18 linux/drivers/macintosh/adb.c

Next file: linux/drivers/macintosh/adbhid.c
Previous file: linux/drivers/macintosh/Makefile
Back to the patch index
Back to the overall index

diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
@@ -34,6 +34,7 @@
 #include <linux/wait.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/completion.h>
 #include <asm/uaccess.h>
 #ifdef CONFIG_PPC
 #include <asm/prom.h>
@@ -78,7 +79,7 @@
 static int adb_inited = 0;
 static pid_t adb_probe_task_pid;
 static int adb_probe_task_flag;
-static wait_queue_head_t adb_probe_task_wq;
+static struct completion adb_probe_task_comp;
 static int sleepy_trackpad;
 int __adb_probe_sync;
 
@@ -318,7 +319,7 @@
 		if (machine_is_compatible("AAPL,PowerBook1998") ||
 			machine_is_compatible("PowerBook1,1"))
 			sleepy_trackpad = 1;
-		init_waitqueue_head(&adb_probe_task_wq);
+		init_completion(&adb_probe_task_comp);
 		adbdev_init();
 		adb_reset_bus();
 	}
@@ -435,7 +436,7 @@
 static void
 adb_probe_wakeup(struct adb_request *req)
 {
-	wake_up(&adb_probe_task_wq);
+	complete(&adb_probe_task_comp);
 }
 
 static struct adb_request adb_sreq;
@@ -484,20 +485,11 @@
 	if ((flags & ADBREQ_SYNC) &&
 	    (current->pid && adb_probe_task_pid &&
 	    adb_probe_task_pid == current->pid)) {
-		DECLARE_WAITQUEUE(wait, current);
 		req->done = adb_probe_wakeup;
-		add_wait_queue(&adb_probe_task_wq, &wait);
 		rc = adb_controller->send_request(req, 0);
 		if (rc || req->complete)
 			goto bail;
-		for (;;) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			if (req->complete)
-				break;
-			schedule();
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&adb_probe_task_wq, &wait);
+		wait_for_completion(&adb_probe_task_comp);
 		rc = 0;
 		goto bail;
 	}
@@ -707,17 +699,16 @@
 		return ret;
 
 	req = NULL;
+	spin_lock_irqsave(&state->lock, flags);
 	add_wait_queue(&state->wait_queue, &wait);
 	current->state = TASK_INTERRUPTIBLE;
 
 	for (;;) {
-		spin_lock_irqsave(&state->lock, flags);
 		req = state->completed;
 		if (req != NULL)
 			state->completed = req->next;
 		else if (atomic_read(&state->n_pending) == 0)
 			ret = -EIO;
-		spin_unlock_irqrestore(&state->lock, flags);
 		if (req != NULL || ret != 0)
 			break;
 		
@@ -729,12 +720,15 @@
 			ret = -ERESTARTSYS;
 			break;
 		}
+		spin_unlock_irqrestore(&state->lock, flags);
 		schedule();
+		spin_lock_irqsave(&state->lock, flags);
 	}
 
 	current->state = TASK_RUNNING;
 	remove_wait_queue(&state->wait_queue, &wait);
-
+	spin_unlock_irqrestore(&state->lock, flags);
+	
 	if (ret)
 		return ret;
 
@@ -757,6 +751,8 @@
 
 	if (count < 2 || count > sizeof(req->data))
 		return -EINVAL;
+	if (adb_controller == NULL)
+		return -ENXIO;
 	ret = verify_area(VERIFY_READ, buf, count);
 	if (ret)
 		return ret;
@@ -776,7 +772,10 @@
 		goto out;
 
 	atomic_inc(&state->n_pending);
-	if (adb_controller == NULL) return -ENXIO;
+
+	/* If a probe is in progress, wait for it to complete */
+	while (adb_probe_task_pid != 0 || test_bit(0, &adb_probe_task_flag))
+		schedule();
 
 	/* Special case for ADB_BUSRESET request, all others are sent to
 	   the controller */
@@ -784,6 +783,8 @@
 		&&(req->data[1] == ADB_BUSRESET)) {
 		ret = do_adb_reset_bus();
 		atomic_dec(&state->n_pending);
+		if (ret == 0)
+			ret = count;
 		goto out;
 	} else {	
 		req->reply_expected = ((req->data[1] & 0xc) == 0xc);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)