From: Bartosz Golaszewski Date: Wed, 23 Apr 2025 08:55:40 +0000 (+0200) Subject: HID: cp2112: hold the lock for the entire direction_output() call X-Git-Tag: v6.16-rc1~64^2~5^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=837b05fea0752ee900abe57253d9f79ca46dd227;p=thirdparty%2Fkernel%2Flinux.git HID: cp2112: hold the lock for the entire direction_output() call We currently take the lock, set direction to output, release it, reacquire it and set the desired value. That doesn't look correct. Introduce a helper function that sets the value without taking the lock and use it where applicable in order to combine the critical sections. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij Signed-off-by: Jiri Kosina --- diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index a001b9acd2d4a..408c865efdd45 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -218,15 +219,13 @@ exit: return ret; } -static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static void cp2112_gpio_set_unlocked(struct cp2112_device *dev, + unsigned int offset, int value) { - struct cp2112_device *dev = gpiochip_get_data(chip); struct hid_device *hdev = dev->hdev; u8 *buf = dev->in_out_buffer; int ret; - mutex_lock(&dev->lock); - buf[0] = CP2112_GPIO_SET; buf[1] = value ? CP2112_GPIO_ALL_GPIO_MASK : 0; buf[2] = BIT(offset); @@ -236,8 +235,16 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value) HID_REQ_SET_REPORT); if (ret < 0) hid_err(hdev, "error setting GPIO values: %d\n", ret); +} - mutex_unlock(&dev->lock); +static void cp2112_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct cp2112_device *dev = gpiochip_get_data(chip); + + guard(mutex)(&dev->lock); + + return cp2112_gpio_set_unlocked(dev, offset, value); } static int cp2112_gpio_get_all(struct gpio_chip *chip) @@ -306,13 +313,13 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip, goto fail; } - mutex_unlock(&dev->lock); - /* * Set gpio value when output direction is already set, * as specified in AN495, Rev. 0.2, cpt. 4.4 */ - cp2112_gpio_set(chip, offset, value); + cp2112_gpio_set_unlocked(dev, offset, value); + + mutex_unlock(&dev->lock); return 0;