From: Oliver Neukum <oneu...@suse.de>

The workqueue handler may call appledisplay_bl_get_brightness() while
user space calls appledisplay_bl_update_status(). As they share a
buffer that must not happen. Use a mutex for mutual exclusion.

Signed-off-by: Oliver Neukum <oneu...@suse.de>
---
 drivers/usb/misc/appledisplay.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index ba6a5d6..55acd44 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -81,6 +81,7 @@ struct appledisplay {
        struct delayed_work work;
        int button_pressed;
        spinlock_t lock;
+       struct mutex sysfslock;         /* concurrent read and write */
 };
 
 static atomic_t count_displays = ATOMIC_INIT(0);
@@ -144,6 +145,7 @@ static int appledisplay_bl_update_status(struct 
backlight_device *bd)
        struct appledisplay *pdata = bl_get_data(bd);
        int retval;
 
+       mutex_lock(&pdata->sysfslock);
        pdata->msgdata[0] = 0x10;
        pdata->msgdata[1] = bd->props.brightness;
 
@@ -156,15 +158,17 @@ static int appledisplay_bl_update_status(struct 
backlight_device *bd)
                0,
                pdata->msgdata, 2,
                ACD_USB_TIMEOUT);
-
+       mutex_unlock(&pdata->sysfslock);
+       
        return retval;
 }
 
 static int appledisplay_bl_get_brightness(struct backlight_device *bd)
 {
        struct appledisplay *pdata = bl_get_data(bd);
-       int retval;
+       int retval, brightness;
 
+       mutex_lock(&pdata->sysfslock);
        retval = usb_control_msg(
                pdata->udev,
                usb_rcvctrlpipe(pdata->udev, 0),
@@ -174,11 +178,13 @@ static int appledisplay_bl_get_brightness(struct 
backlight_device *bd)
                0,
                pdata->msgdata, 2,
                ACD_USB_TIMEOUT);
+       brightness = pdata->msgdata[1];
+       mutex_unlock(&pdata->sysfslock);
 
        if (retval < 0)
                return retval;
        else
-               return pdata->msgdata[1];
+               return brightness;
 }
 
 static const struct backlight_ops appledisplay_bl_data = {
@@ -241,6 +247,7 @@ static int appledisplay_probe(struct usb_interface *iface,
 
        spin_lock_init(&pdata->lock);
        INIT_DELAYED_WORK(&pdata->work, appledisplay_work);
+       mutex_init(&pdata->sysfslock);
 
        /* Allocate buffer for control messages */
        pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);
-- 
1.8.4.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to