HID: cp2112: fix sleep-while-atomic regression
cover HID: cp2112: fix sleep-while-atomic regression
These patches fix a sleep-while-atomic and an error-handling issue introduced by a patch that went into 4.9.
Note that this series has only been compile tested.
Johan
Johan Hovold (2):
HID: cp2112: fix sleep-while-atomic
HID: cp2112: fix gpio-callback error handling
drivers/hid/hid-cp2112.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-)
Signature · 1 line
2.10.2
PATCH 1/2 HID: cp2112: fix sleep-while-atomic
A recent commit fixing DMA-buffers on stack added a shared transfer buffer protected by a spinlock. This is broken as the USB HID request callbacks can sleep. Fix this up by replacing the spinlock with a mutex.
--- drivers/hid/hid-cp2112.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-)
drivers/hid/hid-cp2112.c +11 -15
@@ -168,7 +168,7 @@ struct cp2112_device {atomic_t xfer_avail;struct gpio_chip gc;u8 *in_out_buffer; -spinlock_t lock; +struct mutex lock;struct gpio_desc *desc[8 ];bool gpio_poll;
@@ -186,10 +186,9 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)struct cp2112_device *dev =gpiochip_get_data (chip);struct hid_device *hdev = dev->hdev;u8 *buf = dev->in_out_buffer; -unsigned long flags;int ret; -spin_lock_irqsave (&dev->lock, flags); +mutex_lock (&dev->lock); ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
@@ -213,7 +212,7 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ret =0 ; exit: -spin_unlock_irqrestore (&dev->lock, flags); +mutex_unlock (&dev->lock);return ret <=0 ? ret : -EIO ; }
@@ -222,10 +221,9 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)struct cp2112_device *dev =gpiochip_get_data (chip);struct hid_device *hdev = dev->hdev;u8 *buf = dev->in_out_buffer; -unsigned long flags;int ret; -spin_lock_irqsave (&dev->lock, flags); +mutex_lock (&dev->lock); buf[0 ] =CP2112_GPIO_SET ; buf[1 ] = value ?0xff :0 ;
@@ -237,7 +235,7 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)if (ret <0 )hid_err (hdev,"error setting GPIO values: %d\n" , ret); -spin_unlock_irqrestore (&dev->lock, flags); +mutex_unlock (&dev->lock); }static int cp2112_gpio_get_all (struct gpio_chip *chip)
@@ -245,10 +243,9 @@ static int cp2112_gpio_get_all(struct gpio_chip *chip)struct cp2112_device *dev =gpiochip_get_data (chip);struct hid_device *hdev = dev->hdev;u8 *buf = dev->in_out_buffer; -unsigned long flags;int ret; -spin_lock_irqsave (&dev->lock, flags); +mutex_lock (&dev->lock); ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf, CP2112_GPIO_GET_LENGTH, HID_FEATURE_REPORT,
@@ -262,7 +259,7 @@ static int cp2112_gpio_get_all(struct gpio_chip *chip) ret = buf[1 ]; exit: -spin_unlock_irqrestore (&dev->lock, flags); +mutex_unlock (&dev->lock);return ret; }
@@ -284,10 +281,9 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,struct cp2112_device *dev =gpiochip_get_data (chip);struct hid_device *hdev = dev->hdev;u8 *buf = dev->in_out_buffer; -unsigned long flags;int ret; -spin_lock_irqsave (&dev->lock, flags); +mutex_lock (&dev->lock); ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
@@ -308,7 +304,7 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip, goto fail; } -spin_unlock_irqrestore (&dev->lock, flags); +mutex_unlock (&dev->lock);/* * Set gpio value when output direction is already set,
@@ -319,7 +315,7 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,return 0 ; fail: -spin_unlock_irqrestore (&dev->lock, flags); +mutex_unlock (&dev->lock);return ret <0 ? ret : -EIO ; }
@@ -1235,7 +1231,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)if (!dev->in_out_buffer)return -ENOMEM ; -spin_lock_init (&dev->lock); +mutex_init (&dev->lock); ret =hid_parse (hdev);if (ret) {
Signature · 1 line
2.10.2
PATCH 2/2 HID: cp2112: fix gpio-callback error handling
In case of a zero-length report, the gpio direction_input callback would currently return success instead of an errno.
--- drivers/hid/hid-cp2112.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hid/hid-cp2112.c +1 -1
@@ -213,7 +213,7 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset) exit:mutex_unlock (&dev->lock); -return ret <=0 ? ret : -EIO ; +return ret <0 ? ret : -EIO ; }static void cp2112_gpio_set (struct gpio_chip *chip,unsigned offset,int value)
Signature · 1 line
2.10.2
Quoted 4 lines · Johan Hovold
These patches fix a sleep-while-atomic and an error-handling issue introduced by a patch that went into 4.9.
Note that this series has only been compile tested.
Tested the series, and:
Thanks for spotting that!
Cheers,
Benjamin
Quoted 14 lines
Johan
Johan Hovold (2):
HID: cp2112: fix sleep-while-atomic
HID: cp2112: fix gpio-callback error handlingdrivers/hid/hid-cp2112.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-)Signature · 1 line
2.10.2
Quoted 2 lines · Johan Hovold
These patches fix a sleep-while-atomic and an error-handling issue introduced by a patch that went into 4.9.
Applied, thanks a lot for fixing this up.
Signature · 2 lines
Jiri Kosina SUSE Labs