diff options
Diffstat (limited to 'drivers/macintosh/adb.c')
| -rw-r--r-- | drivers/macintosh/adb.c | 136 |
1 files changed, 87 insertions, 49 deletions
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index 28958101061..9e9c56758a0 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -24,7 +24,6 @@ #include <linux/fs.h> #include <linux/mm.h> #include <linux/sched.h> -#include <linux/smp_lock.h> #include <linux/adb.h> #include <linux/cuda.h> #include <linux/pmu.h> @@ -37,16 +36,15 @@ #include <linux/device.h> #include <linux/kthread.h> #include <linux/platform_device.h> +#include <linux/mutex.h> -#include <asm/uaccess.h> -#include <asm/semaphore.h> +#include <linux/uaccess.h> #ifdef CONFIG_PPC #include <asm/prom.h> #include <asm/machdep.h> #endif -EXPORT_SYMBOL(adb_controller); EXPORT_SYMBOL(adb_client_list); extern struct adb_driver via_macii_driver; @@ -56,6 +54,7 @@ extern struct adb_driver adb_iop_driver; extern struct adb_driver via_pmu_driver; extern struct adb_driver macio_adb_driver; +static DEFINE_MUTEX(adb_mutex); static struct adb_driver *adb_driver_list[] = { #ifdef CONFIG_ADB_MACII &via_macii_driver, @@ -80,11 +79,11 @@ static struct adb_driver *adb_driver_list[] = { static struct class *adb_dev_class; -struct adb_driver *adb_controller; +static struct adb_driver *adb_controller; BLOCKING_NOTIFIER_HEAD(adb_client_list); static int adb_got_sleep; static int adb_inited; -static DECLARE_MUTEX(adb_probe_mutex); +static DEFINE_SEMAPHORE(adb_probe_mutex); static int sleepy_trackpad; static int autopoll_devs; int __adb_probe_sync; @@ -102,7 +101,7 @@ static struct adb_handler { } adb_handler[16]; /* - * The adb_handler_sem mutex protects all accesses to the original_address + * The adb_handler_mutex mutex protects all accesses to the original_address * and handler_id fields of adb_handler[i] for all i, and changes to the * handler field. * Accesses to the handler field are protected by the adb_handler_lock @@ -110,7 +109,7 @@ static struct adb_handler { * time adb_unregister returns, we know that the old handler isn't being * called. */ -static DECLARE_MUTEX(adb_handler_sem); +static DEFINE_MUTEX(adb_handler_mutex); static DEFINE_RWLOCK(adb_handler_lock); #if 0 @@ -194,8 +193,7 @@ static int adb_scan_bus(void) break; noMovement = 0; - } - else { + } else { /* * No devices left at address i; move the * one(s) we moved to `highFree' back to i. @@ -264,7 +262,7 @@ adb_reset_bus(void) /* * notify clients before sleep */ -static int adb_suspend(struct platform_device *dev, pm_message_t state) +static int __adb_suspend(struct platform_device *dev, pm_message_t state) { adb_got_sleep = 1; /* We need to get a lock on the probe thread */ @@ -277,10 +275,25 @@ static int adb_suspend(struct platform_device *dev, pm_message_t state) return 0; } +static int adb_suspend(struct device *dev) +{ + return __adb_suspend(to_platform_device(dev), PMSG_SUSPEND); +} + +static int adb_freeze(struct device *dev) +{ + return __adb_suspend(to_platform_device(dev), PMSG_FREEZE); +} + +static int adb_poweroff(struct device *dev) +{ + return __adb_suspend(to_platform_device(dev), PMSG_HIBERNATE); +} + /* * reset bus after sleep */ -static int adb_resume(struct platform_device *dev) +static int __adb_resume(struct platform_device *dev) { adb_got_sleep = 0; up(&adb_probe_mutex); @@ -288,9 +301,14 @@ static int adb_resume(struct platform_device *dev) return 0; } + +static int adb_resume(struct device *dev) +{ + return __adb_resume(to_platform_device(dev)); +} #endif /* CONFIG_PM */ -int __init adb_init(void) +static int __init adb_init(void) { struct adb_driver *driver; int i; @@ -318,13 +336,15 @@ int __init adb_init(void) break; } } - if ((adb_controller == NULL) || adb_controller->init()) { - printk(KERN_WARNING "Warning: no ADB interface detected\n"); + if (adb_controller != NULL && adb_controller->init && + adb_controller->init()) adb_controller = NULL; + if (adb_controller == NULL) { + printk(KERN_WARNING "Warning: no ADB interface detected\n"); } else { #ifdef CONFIG_PPC - if (machine_is_compatible("AAPL,PowerBook1998") || - machine_is_compatible("PowerBook1,1")) + if (of_machine_is_compatible("AAPL,PowerBook1998") || + of_machine_is_compatible("PowerBook1,1")) sleepy_trackpad = 1; #endif /* CONFIG_PPC */ @@ -334,7 +354,7 @@ int __init adb_init(void) return 0; } -__initcall(adb_init); +device_initcall(adb_init); static int do_adb_reset_bus(void) @@ -355,7 +375,7 @@ do_adb_reset_bus(void) msleep(500); } - down(&adb_handler_sem); + mutex_lock(&adb_handler_mutex); write_lock_irq(&adb_handler_lock); memset(adb_handler, 0, sizeof(adb_handler)); write_unlock_irq(&adb_handler_lock); @@ -376,7 +396,7 @@ do_adb_reset_bus(void) if (adb_controller->autopoll) adb_controller->autopoll(autopoll_devs); } - up(&adb_handler_sem); + mutex_unlock(&adb_handler_mutex); blocking_notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL); @@ -454,7 +474,7 @@ adb_register(int default_id, int handler_id, struct adb_ids *ids, { int i; - down(&adb_handler_sem); + mutex_lock(&adb_handler_mutex); ids->nids = 0; for (i = 1; i < 16; i++) { if ((adb_handler[i].original_address == default_id) && @@ -472,7 +492,7 @@ adb_register(int default_id, int handler_id, struct adb_ids *ids, ids->id[ids->nids++] = i; } } - up(&adb_handler_sem); + mutex_unlock(&adb_handler_mutex); return ids->nids; } @@ -481,7 +501,7 @@ adb_unregister(int index) { int ret = -ENODEV; - down(&adb_handler_sem); + mutex_lock(&adb_handler_mutex); write_lock_irq(&adb_handler_lock); if (adb_handler[index].handler) { while(adb_handler[index].busy) { @@ -493,7 +513,7 @@ adb_unregister(int index) adb_handler[index].handler = NULL; } write_unlock_irq(&adb_handler_lock); - up(&adb_handler_sem); + mutex_unlock(&adb_handler_mutex); return ret; } @@ -501,7 +521,7 @@ void adb_input(unsigned char *buf, int nb, int autopoll) { int i, id; - static int dump_adb_input = 0; + static int dump_adb_input; unsigned long flags; void (*handler)(unsigned char *, int, int); @@ -557,19 +577,19 @@ adb_try_handler_change(int address, int new_id) { int ret; - down(&adb_handler_sem); + mutex_lock(&adb_handler_mutex); ret = try_handler_change(address, new_id); - up(&adb_handler_sem); + mutex_unlock(&adb_handler_mutex); return ret; } int adb_get_infos(int address, int *original_address, int *handler_id) { - down(&adb_handler_sem); + mutex_lock(&adb_handler_mutex); *original_address = adb_handler[address].original_address; *handler_id = adb_handler[address].handler_id; - up(&adb_handler_sem); + mutex_unlock(&adb_handler_mutex); return (*original_address != 0); } @@ -623,15 +643,14 @@ do_adb_query(struct adb_request *req) { int ret = -EINVAL; - switch(req->data[1]) - { + switch(req->data[1]) { case ADB_QUERY_GETDEVINFO: if (req->nbytes < 3) break; - down(&adb_handler_sem); + mutex_lock(&adb_handler_mutex); req->reply[0] = adb_handler[req->data[2]].original_address; req->reply[1] = adb_handler[req->data[2]].handler_id; - up(&adb_handler_sem); + mutex_unlock(&adb_handler_mutex); req->complete = 1; req->reply_len = 2; adb_write_done(req); @@ -644,12 +663,18 @@ do_adb_query(struct adb_request *req) static int adb_open(struct inode *inode, struct file *file) { struct adbdev_state *state; + int ret = 0; - if (iminor(inode) > 0 || adb_controller == NULL) - return -ENXIO; + mutex_lock(&adb_mutex); + if (iminor(inode) > 0 || adb_controller == NULL) { + ret = -ENXIO; + goto out; + } state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL); - if (state == 0) - return -ENOMEM; + if (state == 0) { + ret = -ENOMEM; + goto out; + } file->private_data = state; spin_lock_init(&state->lock); atomic_set(&state->n_pending, 0); @@ -657,7 +682,9 @@ static int adb_open(struct inode *inode, struct file *file) init_waitqueue_head(&state->wait_queue); state->inuse = 1; - return 0; +out: + mutex_unlock(&adb_mutex); + return ret; } static int adb_release(struct inode *inode, struct file *file) @@ -665,7 +692,7 @@ static int adb_release(struct inode *inode, struct file *file) struct adbdev_state *state = file->private_data; unsigned long flags; - lock_kernel(); + mutex_lock(&adb_mutex); if (state) { file->private_data = NULL; spin_lock_irqsave(&state->lock, flags); @@ -678,7 +705,7 @@ static int adb_release(struct inode *inode, struct file *file) spin_unlock_irqrestore(&state->lock, flags); } } - unlock_kernel(); + mutex_unlock(&adb_mutex); return 0; } @@ -688,7 +715,7 @@ static ssize_t adb_read(struct file *file, char __user *buf, int ret = 0; struct adbdev_state *state = file->private_data; struct adb_request *req; - wait_queue_t wait = __WAITQUEUE_INITIALIZER(wait,current); + DECLARE_WAITQUEUE(wait, current); unsigned long flags; if (count < 2) @@ -701,7 +728,7 @@ static ssize_t adb_read(struct file *file, char __user *buf, req = NULL; spin_lock_irqsave(&state->lock, flags); add_wait_queue(&state->wait_queue, &wait); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); for (;;) { req = state->completed; @@ -725,7 +752,7 @@ static ssize_t adb_read(struct file *file, char __user *buf, spin_lock_irqsave(&state->lock, flags); } - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&state->wait_queue, &wait); spin_unlock_irqrestore(&state->lock, flags); @@ -785,8 +812,8 @@ static ssize_t adb_write(struct file *file, const char __user *buf, } /* Special case for ADB_BUSRESET request, all others are sent to the controller */ - else if ((req->data[0] == ADB_PACKET)&&(count > 1) - &&(req->data[1] == ADB_BUSRESET)) { + 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); @@ -822,14 +849,25 @@ static const struct file_operations adb_fops = { .release = adb_release, }; +#ifdef CONFIG_PM +static const struct dev_pm_ops adb_dev_pm_ops = { + .suspend = adb_suspend, + .resume = adb_resume, + /* Hibernate hooks */ + .freeze = adb_freeze, + .thaw = adb_resume, + .poweroff = adb_poweroff, + .restore = adb_resume, +}; +#endif + static struct platform_driver adb_pfdrv = { .driver = { .name = "adb", - }, #ifdef CONFIG_PM - .suspend = adb_suspend, - .resume = adb_resume, + .pm = &adb_dev_pm_ops, #endif + }, }; static struct platform_device adb_pfdev = { @@ -855,7 +893,7 @@ adbdev_init(void) adb_dev_class = class_create(THIS_MODULE, "adb"); if (IS_ERR(adb_dev_class)) return; - device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), "adb"); + device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb"); platform_device_register(&adb_pfdev); platform_driver_probe(&adb_pfdrv, adb_dummy_probe); |
