From: Stelian Pop > Well, 2 processes simultaneously enabling and disabling input device > will mess up the driver; some locking is needed there. Pretty extreme, > I know... Right. The input_mutex in the patch below should fix this issue. Cc: Stelian Pop Cc: Johannes Berg Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Dmitry Torokhov Cc: Robert Love Cc: Jean Delvare Signed-off-by: Andrew Morton --- drivers/hwmon/ams.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff -puN drivers/hwmon/ams.c~apple-motion-sensor-driver-update-2 drivers/hwmon/ams.c --- a/drivers/hwmon/ams.c~apple-motion-sensor-driver-update-2 +++ a/drivers/hwmon/ams.c @@ -1,7 +1,7 @@ /* * Apple Motion Sensor driver * - * Copyright (C) 2006 Stelian Pop (stelian@popies.net) + * Copyright (C) 2005 Stelian Pop (stelian@popies.net) * * Clean room implementation based on the reverse engineered OSX driver by * Johannes Berg , documentation available at @@ -101,6 +101,7 @@ struct ams { int xcalib; /* calibrated null value for x */ int ycalib; /* calibrated null value for y */ int zcalib; /* calibrated null value for z */ + struct mutex input_mutex; struct task_struct *kthread; /* kthread for input */ }; @@ -226,8 +227,10 @@ static void ams_mouse_enable(void) { s8 x, y, z; + mutex_lock(&ams.input_mutex); + if (ams.idev) - return; + goto out; ams_sensors(&x, &y, &z); ams.xcalib = x; @@ -236,7 +239,7 @@ static void ams_mouse_enable(void) ams.idev = input_allocate_device(); if (!ams.idev) - return; + goto out; ams.idev->name = "Apple Motion Sensor"; ams.idev->id.bustype = BUS_I2C; @@ -253,27 +256,33 @@ static void ams_mouse_enable(void) if (input_register_device(ams.idev)) { input_free_device(ams.idev); ams.idev = NULL; - return; + goto out; } ams.kthread = kthread_run(ams_mouse_kthread, NULL, "kams"); if (IS_ERR(ams.kthread)) { input_unregister_device(ams.idev); ams.idev = NULL; - return; + goto out; } +out: + mutex_unlock(&ams.input_mutex); } static void ams_mouse_disable(void) { + mutex_lock(&ams.input_mutex); + if (!ams.idev) - return; + goto out; kthread_stop(ams.kthread); input_unregister_device(ams.idev); ams.idev = NULL; +out: + mutex_unlock(&ams.input_mutex); } static ssize_t ams_show_mouse(struct device *dev, struct device_attribute *attr, @@ -488,6 +497,8 @@ static int __init ams_init(void) if ((ams.of_dev = of_platform_device_create(np, "ams", NULL)) == NULL) goto free_irq2; + mutex_init(&ams.input_mutex); + device_create_file(&ams.of_dev->dev, &dev_attr_x); device_create_file(&ams.of_dev->dev, &dev_attr_y); device_create_file(&ams.of_dev->dev, &dev_attr_z); @@ -503,6 +514,7 @@ free_device_files: device_remove_file(&ams.of_dev->dev, &dev_attr_y); device_remove_file(&ams.of_dev->dev, &dev_attr_z); device_remove_file(&ams.of_dev->dev, &dev_attr_mouse); + mutex_destroy(&ams.input_mutex); free_irq2: free_irq(ams.irq2, NULL); free_irq1: @@ -523,6 +535,8 @@ static void __exit ams_exit(void) device_remove_file(&ams.of_dev->dev, &dev_attr_z); device_remove_file(&ams.of_dev->dev, &dev_attr_mouse); + mutex_destroy(&ams.input_mutex); + of_device_unregister(ams.of_dev); } _