From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2E6D5FA3728 for ; Wed, 16 Oct 2019 21:57:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 009B021D7D for ; Wed, 16 Oct 2019 21:57:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1571263060; bh=HSW9Eg9Cocl1FHpauNvnQ+JPck1GECfflNlQLO7SD2w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=WS9KAEToN/nWwFRVwgKTSXarz8OA4uWZ8eGSbuNidZXlxyKGg6jwWlN9oao+ieNPn 60SLX5HwZkGhAiDQUqXW2lsuRoABmmk/rtgXQwYoQL4C1FlRzYDGAtAZycYBfBL0ma 2UE3Cb8CKAvm+Ggygv8ijmIZff7jSHIQQUlGB9To= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2395505AbfJPV5j (ORCPT ); Wed, 16 Oct 2019 17:57:39 -0400 Received: from mail.kernel.org ([198.145.29.99]:50432 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2395495AbfJPV5h (ORCPT ); Wed, 16 Oct 2019 17:57:37 -0400 Received: from localhost (unknown [192.55.54.58]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id EF44121D7A; Wed, 16 Oct 2019 21:57:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1571263057; bh=HSW9Eg9Cocl1FHpauNvnQ+JPck1GECfflNlQLO7SD2w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FB6G+2Zgbpwe2nRII9z0lbH4PNiHHOk2LVYIjGZemWp03Yk5YzS7+na6RTR4pXyqQ HavUhLWmLaNbavbBJ/7pYdUJNQYSWFuC0XUmkdLL7NuDTIdZA2ScB5O6s/lUH9FHXj pfldp2HUB8ztt8qc4AemEOeVoswWlrWKkRR8NESs= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Kent Gibson , Bartosz Golaszewski , Sasha Levin Subject: [PATCH 4.19 59/81] gpiolib: dont clear FLAG_IS_OUT when emulating open-drain/open-source Date: Wed, 16 Oct 2019 14:51:10 -0700 Message-Id: <20191016214843.408438977@linuxfoundation.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191016214805.727399379@linuxfoundation.org> References: <20191016214805.727399379@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Bartosz Golaszewski [ Upstream commit e735244e2cf068f98b6384681a38993e0517a838 ] When emulating open-drain/open-source by not actively driving the output lines - we're simply changing their mode to input. This is wrong as it will then make it impossible to change the value of such line - it's now considered to actually be in input mode. If we want to still use the direction_input() callback for simplicity then we need to set FLAG_IS_OUT manually in gpiod_direction_output() and not clear it in gpio_set_open_drain_value_commit() and gpio_set_open_source_value_commit(). Fixes: c663e5f56737 ("gpio: support native single-ended hardware drivers") Cc: stable@vger.kernel.org Reported-by: Kent Gibson Signed-off-by: Bartosz Golaszewski [Bartosz: backported to v5.3, v4.19] Signed-off-by: Bartosz Golaszewski Signed-off-by: Sasha Levin --- drivers/gpio/gpiolib.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 3289b53a7ba14..565ab945698ca 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2649,8 +2649,10 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) if (!ret) goto set_output_value; /* Emulate open drain by not actively driving the line high */ - if (value) - return gpiod_direction_input(desc); + if (value) { + ret = gpiod_direction_input(desc); + goto set_output_flag; + } } else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), @@ -2658,8 +2660,10 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) if (!ret) goto set_output_value; /* Emulate open source by not actively driving the line low */ - if (!value) - return gpiod_direction_input(desc); + if (!value) { + ret = gpiod_direction_input(desc); + goto set_output_flag; + } } else { gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), PIN_CONFIG_DRIVE_PUSH_PULL); @@ -2667,6 +2671,17 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) set_output_value: return gpiod_direction_output_raw_commit(desc, value); + +set_output_flag: + /* + * When emulating open-source or open-drain functionalities by not + * actively driving the line (setting mode to input) we still need to + * set the IS_OUT flag or otherwise we won't be able to set the line + * value anymore. + */ + if (ret == 0) + set_bit(FLAG_IS_OUT, &desc->flags); + return ret; } EXPORT_SYMBOL_GPL(gpiod_direction_output); @@ -2980,8 +2995,6 @@ static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value) if (value) { err = chip->direction_input(chip, offset); - if (!err) - clear_bit(FLAG_IS_OUT, &desc->flags); } else { err = chip->direction_output(chip, offset, 0); if (!err) @@ -3011,8 +3024,6 @@ static void gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value set_bit(FLAG_IS_OUT, &desc->flags); } else { err = chip->direction_input(chip, offset); - if (!err) - clear_bit(FLAG_IS_OUT, &desc->flags); } trace_gpio_direction(desc_to_gpio(desc), !value, err); if (err < 0) -- 2.20.1