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 <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
struct delayed_work work;
int button_pressed;
spinlock_t lock;
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);
};
static atomic_t count_displays = ATOMIC_INIT(0);
struct appledisplay *pdata = bl_get_data(bd);
int retval;
struct appledisplay *pdata = bl_get_data(bd);
int retval;
+ mutex_lock(&pdata->sysfslock);
pdata->msgdata[0] = 0x10;
pdata->msgdata[1] = bd->props.brightness;
pdata->msgdata[0] = 0x10;
pdata->msgdata[1] = bd->props.brightness;
0,
pdata->msgdata, 2,
ACD_USB_TIMEOUT);
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);
return retval;
}
static int appledisplay_bl_get_brightness(struct backlight_device *bd)
{
struct appledisplay *pdata = bl_get_data(bd);
+ int retval, brightness;
+ mutex_lock(&pdata->sysfslock);
retval = usb_control_msg(
pdata->udev,
usb_rcvctrlpipe(pdata->udev, 0),
retval = usb_control_msg(
pdata->udev,
usb_rcvctrlpipe(pdata->udev, 0),
0,
pdata->msgdata, 2,
ACD_USB_TIMEOUT);
0,
pdata->msgdata, 2,
ACD_USB_TIMEOUT);
+ brightness = pdata->msgdata[1];
+ mutex_unlock(&pdata->sysfslock);
if (retval < 0)
return retval;
else
if (retval < 0)
return retval;
else
- return pdata->msgdata[1];
}
static const struct backlight_ops appledisplay_bl_data = {
}
static const struct backlight_ops appledisplay_bl_data = {
spin_lock_init(&pdata->lock);
INIT_DELAYED_WORK(&pdata->work, appledisplay_work);
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);
/* Allocate buffer for control messages */
pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);