[PATCH] update adb driver

From: Paul Mackerras (paulus@samba.org)
Date: Sun Mar 30 2003 - 17:55:55 EST


This patch updates the ADB (Apple desktop bus) driver used on macs and
powermacs. The main change, from Ben Herrenschmidt, is that handlers
are called without a lock held now. It also adds a way for userland
to obtain some information about individual ADB devices from the
driver.

Please apply.

Paul.

diff -urN linux-2.5/drivers/macintosh/adb.c linuxppc-2.5/drivers/macintosh/adb.c
--- linux-2.5/drivers/macintosh/adb.c 2003-03-21 19:48:22.000000000 +1100
+++ linuxppc-2.5/drivers/macintosh/adb.c 2003-03-21 20:06:37.000000000 +1100
@@ -102,6 +102,7 @@
         void (*handler)(unsigned char *, int, struct pt_regs *, int);
         int original_address;
         int handler_id;
+ int busy;
 } adb_handler[16];
 
 /*
@@ -134,7 +135,7 @@
 {
         if (current->pid && adb_probe_task_pid &&
           adb_probe_task_pid == current->pid) {
- current->state = TASK_UNINTERRUPTIBLE;
+ set_task_state(current, TASK_UNINTERRUPTIBLE);
                 schedule_timeout(1 + ms * HZ / 1000);
         } else
                 mdelay(ms);
@@ -249,7 +250,7 @@
         strcpy(current->comm, "kadbprobe");
 
         sigfillset(&blocked);
- sigprocmask(SIG_BLOCK, &blocked, NULL);
+ sigprocmask(SIG_BLOCK, &blocked, NULL);
         flush_signals(current);
 
         printk(KERN_INFO "adb: starting probe task...\n");
@@ -550,12 +551,17 @@
         down(&adb_handler_sem);
         write_lock_irq(&adb_handler_lock);
         if (adb_handler[index].handler) {
+ while(adb_handler[index].busy) {
+ write_unlock_irq(&adb_handler_lock);
+ yield();
+ write_lock_irq(&adb_handler_lock);
+ }
                 ret = 0;
                 adb_handler[index].handler = 0;
         }
         write_unlock_irq(&adb_handler_lock);
         up(&adb_handler_sem);
- return 0;
+ return ret;
 }
 
 void
@@ -563,6 +569,8 @@
 {
         int i, id;
         static int dump_adb_input = 0;
+ unsigned long flags;
+
         void (*handler)(unsigned char *, int, struct pt_regs *, int);
 
         /* We skip keystrokes and mouse moves when the sleep process
@@ -578,11 +586,17 @@
                         printk(" %x", buf[i]);
                 printk(", id = %d\n", id);
         }
- read_lock(&adb_handler_lock);
+ write_lock_irqsave(&adb_handler_lock, flags);
         handler = adb_handler[id].handler;
- if (handler != 0)
+ if (handler != NULL)
+ adb_handler[id].busy = 1;
+ write_unlock_irqrestore(&adb_handler_lock, flags);
+ if (handler != NULL) {
                 (*handler)(buf, nb, regs, autopoll);
- read_unlock(&adb_handler_lock);
+ wmb();
+ adb_handler[id].busy = 0;
+ }
+
 }
 
 /* Try to change handler to new_id. Will return 1 if successful. */
@@ -671,6 +685,29 @@
         spin_unlock_irqrestore(&state->lock, flags);
 }
 
+static int
+do_adb_query(struct adb_request *req)
+{
+ int ret = -EINVAL;
+
+ switch(req->data[1])
+ {
+ case ADB_QUERY_GETDEVINFO:
+ if (req->nbytes < 3)
+ break;
+ down(&adb_handler_sem);
+ req->reply[0] = adb_handler[req->data[2]].original_address;
+ req->reply[1] = adb_handler[req->data[2]].handler_id;
+ up(&adb_handler_sem);
+ req->complete = 1;
+ req->reply_len = 2;
+ adb_write_done(req);
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
 static int adb_open(struct inode *inode, struct file *file)
 {
         struct adbdev_state *state;
@@ -806,24 +843,32 @@
 
         /* If a probe is in progress or we are sleeping, wait for it to complete */
         down(&adb_probe_mutex);
- up(&adb_probe_mutex);
 
+ /* Queries are special requests sent to the ADB driver itself */
+ if (req->data[0] == ADB_QUERY) {
+ if (count > 1)
+ ret = do_adb_query(req);
+ else
+ ret = -EINVAL;
+ up(&adb_probe_mutex);
+ }
         /* Special case for ADB_BUSRESET request, all others are sent to
            the controller */
- if ((req->data[0] == ADB_PACKET)&&(count > 1)
+ else if ((req->data[0] == ADB_PACKET)&&(count > 1)
                 &&(req->data[1] == ADB_BUSRESET)) {
                 ret = do_adb_reset_bus();
+ up(&adb_probe_mutex);
                 atomic_dec(&state->n_pending);
                 if (ret == 0)
                         ret = count;
                 goto out;
         } else {
                 req->reply_expected = ((req->data[1] & 0xc) == 0xc);
-
                 if (adb_controller && adb_controller->send_request)
                         ret = adb_controller->send_request(req, 0);
                 else
                         ret = -ENXIO;
+ up(&adb_probe_mutex);
         }
 
         if (ret != 0) {
diff -urN linux-2.5/drivers/macintosh/macio-adb.c linuxppc-2.5/drivers/macintosh/macio-adb.c
--- linux-2.5/drivers/macintosh/macio-adb.c 2002-10-13 15:00:41.000000000 +1000
+++ linuxppc-2.5/drivers/macintosh/macio-adb.c 2002-11-22 23:15:30.000000000 +1100
@@ -8,6 +8,7 @@
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/interrupt.h>
 #include <asm/prom.h>
 #include <linux/adb.h>
 #include <asm/io.h>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Mar 31 2003 - 22:00:35 EST