From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-eopbgr680134.outbound.protection.outlook.com ([40.107.68.134]:2178 "EHLO NAM04-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1731884AbeIXUy0 (ORCPT ); Mon, 24 Sep 2018 16:54:26 -0400 From: Sasha Levin To: "stable@vger.kernel.org" , "linux-kernel@vger.kernel.org" CC: Michael Hennerich , Linus Walleij , Sasha Levin Subject: [PATCH AUTOSEL 3.18 03/13] gpio: adp5588: Fix sleep-in-atomic-context bug Date: Mon, 24 Sep 2018 14:50:09 +0000 Message-ID: <20180924144959.164754-3-alexander.levin@microsoft.com> References: <20180924144959.164754-1-alexander.levin@microsoft.com> In-Reply-To: <20180924144959.164754-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Michael Hennerich [ Upstream commit 6537886cdc9a637711fd6da980dbb87c2c87c9aa ] This fixes: [BUG] gpio: gpio-adp5588: A possible sleep-in-atomic-context bug in adp5588_gpio_write() [BUG] gpio: gpio-adp5588: A possible sleep-in-atomic-context bug in adp5588_gpio_direction_input() Reported-by: Jia-Ju Bai Signed-off-by: Michael Hennerich Signed-off-by: Linus Walleij Signed-off-by: Sasha Levin --- drivers/gpio/gpio-adp5588.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index 3beed6ea8c65..348cde425220 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c @@ -41,6 +41,8 @@ struct adp5588_gpio { uint8_t int_en[3]; uint8_t irq_mask[3]; uint8_t irq_stat[3]; + uint8_t int_input_en[3]; + uint8_t int_lvl_cached[3]; }; =20 static int adp5588_gpio_read(struct i2c_client *client, u8 reg) @@ -177,12 +179,28 @@ static void adp5588_irq_bus_sync_unlock(struct irq_da= ta *d) struct adp5588_gpio *dev =3D irq_data_get_irq_chip_data(d); int i; =20 - for (i =3D 0; i <=3D ADP5588_BANK(ADP5588_MAXGPIO); i++) + for (i =3D 0; i <=3D ADP5588_BANK(ADP5588_MAXGPIO); i++) { + if (dev->int_input_en[i]) { + mutex_lock(&dev->lock); + dev->dir[i] &=3D ~dev->int_input_en[i]; + dev->int_input_en[i] =3D 0; + adp5588_gpio_write(dev->client, GPIO_DIR1 + i, + dev->dir[i]); + mutex_unlock(&dev->lock); + } + + if (dev->int_lvl_cached[i] !=3D dev->int_lvl[i]) { + dev->int_lvl_cached[i] =3D dev->int_lvl[i]; + adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + i, + dev->int_lvl[i]); + } + if (dev->int_en[i] ^ dev->irq_mask[i]) { dev->int_en[i] =3D dev->irq_mask[i]; adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i, dev->int_en[i]); } + } =20 mutex_unlock(&dev->irq_lock); } @@ -225,9 +243,7 @@ static int adp5588_irq_set_type(struct irq_data *d, uns= igned int type) else return -EINVAL; =20 - adp5588_gpio_direction_input(&dev->gpio_chip, gpio); - adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank, - dev->int_lvl[bank]); + dev->int_input_en[bank] |=3D bit; =20 return 0; } --=20 2.17.1