From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23A152222CB; Fri, 13 Feb 2026 09:31:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975066; cv=none; b=OT5FBNO02NpIIHs0QOUn4kicVERolEYwr8xgleqS4wrG3cMo/+d7U+XJiu9W5BFrjVFhS6KwXXz3MPNKvX7lcIE9n49PquAVmEremxqIM3mHczdegFJY8t0mmEWiCsQP+4bho1bFym7AXelCB5mGcARQAjnEWkB9pEVIDE5Yqzs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975066; c=relaxed/simple; bh=SyNkwYYpX1Qe4VcjL4R7jtbLw5u6+UPC9JTgSugQXxQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mVMBhQL/cXmi9gHvLxUBmuaZaupJIDn4hwJW6Gu5r5rv/lgYnkG12Al8lYvkd76DsIJii3F9DsUMmlWIm49iyqQy9m/LELf+FTccJz+AyrbTmgZeKUsgN06wcPB5bZ5/wJVDSLabts/in0kLD9HH9vqKEive5HKTmpZVkKgSr90= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QVdXgZ90; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QVdXgZ90" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 03B7FC2BC9E; Fri, 13 Feb 2026 09:31:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975065; bh=SyNkwYYpX1Qe4VcjL4R7jtbLw5u6+UPC9JTgSugQXxQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QVdXgZ90DeKdu6KTKSXiCf0MgPWIsb0UtSL3PYn03zsGNK4xyTHzGdAknI46/Pg5x 2pCzhTRLan6XNXhw0eIzXUpspEa+Ee9S+ujPR9G9WV5PFBB3HcXHo40HsFbPI1LsUM jnoTz9FCb+Qda4tQIHWltNzqUSFcdzIcuOKcpBhX3vO7lHYsvYbhrHf9Wz7VpmA7FN tY/+SL8Q9UbrhO0Ef8akI4YamZ8qa2ChTGg+j3DsLn2bRTTiS32oIWiC4aVSlOOywU 0cMembfGjDEJIUre1B75PlGgTQFEuHYDzsRxVOMYPF+UF4mi+Tbw0NtdSkhzDR1zTY 7pEBe3FVuhHGw== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 01/11] gpio: Access `gpio_bus_type` in gpiochip_setup_dev() Date: Fri, 13 Feb 2026 09:29:48 +0000 Message-ID: <20260213092958.864411-2-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To make the intent clear, access `gpio_bus_type` only when it's ready in gpiochip_setup_dev(). Signed-off-by: Tzung-Bi Shih Reviewed-by: Linus Walleij --- v3: - No changes. v2: https://lore.kernel.org/all/20260203061059.975605-2-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-7-tzungbi@kernel.org drivers/gpio/gpiolib.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5757c0475990..f4dad3e5b5a3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -902,6 +902,8 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) struct fwnode_handle *fwnode =3D dev_fwnode(&gdev->dev); int ret; =20 + gdev->dev.bus =3D &gpio_bus_type; + /* * If fwnode doesn't belong to another device, it's safe to clear its * initialized flag. @@ -1083,7 +1085,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, * then make sure they get free():ed there. */ gdev->dev.type =3D &gpio_dev_type; - gdev->dev.bus =3D &gpio_bus_type; gdev->dev.parent =3D gc->parent; device_set_node(&gdev->dev, gpiochip_choose_fwnode(gc)); =20 @@ -1221,8 +1222,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, * we get a device node entry in sysfs under * /sys/bus/gpio/devices/gpiochipN/dev that can be used for * coldplug of device nodes and other udev business. - * We can do this only if gpiolib has been initialized. - * Otherwise, defer until later. + * We can do this only if gpiolib has been initialized + * (i.e., `gpio_bus_type` is ready). Otherwise, defer until later. */ if (gpiolib_initialized) { ret =3D gpiochip_setup_dev(gdev); --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1ABB32405E1; Fri, 13 Feb 2026 09:31:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975069; cv=none; b=LHfO3YBhUGY9kh0usYJewAHX9La7HlxuwrM0efjKWHH573uCKTmTl1KEg5QgTLjczzKYjoU4qXFyHkWuSjHwC/c03Uo7ycBxmLjqur4eygiEN6ILZIoMd8RnGLIBWVI//LJA42rwYJ5/B2AQlTQcNcEYqdxUrN5GfAboNsrRKvo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975069; c=relaxed/simple; bh=3yaZTDOU24FAmuSSempbk58vZlgrqTM2zntQtT1Ib4E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G+0IQKBUNMlVI5m8UOtWfnUhvv8+7Yq6YWAhy0GHi7IV6fvK+GvWnu82F6XI+AvVFujV+GmWPm3gCxTdhy6DpShf9qr9OfwwL4dg6cKi5g21Pxl4t/Dg6miSaxXSBrqzOgJR8oEvj3cbehuVT7qUzwGcKN4HtFQ+jECZWMfaqOM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rOnY1kvt; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="rOnY1kvt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 03780C116C6; Fri, 13 Feb 2026 09:31:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975068; bh=3yaZTDOU24FAmuSSempbk58vZlgrqTM2zntQtT1Ib4E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rOnY1kvtyzQdttQc8WZ7zlLqC0XJZb2WGgJU93EhUhrjx7vFftGlg0srUuv8tQPuz qwLWAiLVVEhtj8B3gM6l5jyGmK0wQA/S85CAUOHjVUuZ7kmqiISFcTvGpDtzsw9xfJ VY4/jdoYCkO6Jn2R8seaQcVxsqBrEKeyNkY+slousU/VPpVP6b05hXIL9UQo0B0b9F 5aYIunzOx4g3PLurZTlJef5RzTSOOT5yeH9Wl4eqaxkOtlnMlxLgSwTBpMblgp/BMA smehyXSLLWvA8MTSsmG2G3QgNvravfw0RTUzyXnb7oBhJHOf5VMOli1v7GTYfI3t62 YnYJPKYtuFFXg== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 02/11] gpio: Remove redundant check for struct gpio_chip Date: Fri, 13 Feb 2026 09:29:49 +0000 Message-ID: <20260213092958.864411-3-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" gpiolib_dbg_show() is only called by gpiolib_seq_show() which has ensured the struct gpio_chip. Remove the redundant check in gpiolib_dbg_show(). Signed-off-by: Tzung-Bi Shih Reviewed-by: Linus Walleij --- v3: - No changes. v2: https://lore.kernel.org/all/20260203061059.975605-3-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-8-tzungbi@kernel.org drivers/gpio/gpiolib.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f4dad3e5b5a3..1a3fd7600835 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -5313,23 +5313,14 @@ core_initcall(gpiolib_dev_init); =20 #ifdef CONFIG_DEBUG_FS =20 -static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev) +static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *gc) { bool active_low, is_irq, is_out; struct gpio_desc *desc; unsigned int gpio =3D 0; - struct gpio_chip *gc; unsigned long flags; int value; =20 - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!gc) { - seq_puts(s, "Underlying GPIO chip is gone\n"); - return; - } - for_each_gpio_desc(gc, desc) { guard(srcu)(&desc->gdev->desc_srcu); flags =3D READ_ONCE(desc->flags); @@ -5442,7 +5433,7 @@ static int gpiolib_seq_show(struct seq_file *s, void = *v) if (gc->dbg_show) gc->dbg_show(s, gc); else - gpiolib_dbg_show(s, gdev); + gpiolib_dbg_show(s, gc); =20 return 0; } --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49C452D9EC5; Fri, 13 Feb 2026 09:31:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975072; cv=none; b=pN5pS29fs+4n33gIrjd6O+4GW2Mo90WEHhgRQ+Q/ANxuP4bAKFxNKU2OYIP2U3sHCppydFr7M+Q3Pwy9damNUaW4klu17q5xtURAHoDpzB4UrXvQo2E4AkPKi/qq2Fk/TK8TgKVbkz01EyN/gkZsbrn9kQKQWxQUeyjWLatQb+0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975072; c=relaxed/simple; bh=4lmvZJ5YXxkra6JcPmvMDUqSNsmp29GAkCIdsIEWkuY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s8roDDZPNtsq+obwI/3kFj2Zp3NHWkxPxNSRb8hOe34oy8mdO4k429tSxVoGhGrW9U5hkcd0/KZjwIV7O4xc4zWMwcN3XztsR4DYDOS1aix3Dsalg/R7naClPcG3VDx4GWq/Uhp2pZo6hl02R+yO1PzW9/bSp7vJa8ml75Mdh94= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SMIo1mj8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SMIo1mj8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 01B40C16AAE; Fri, 13 Feb 2026 09:31:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975071; bh=4lmvZJ5YXxkra6JcPmvMDUqSNsmp29GAkCIdsIEWkuY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SMIo1mj82G6ZnNlKvnBix9OuoB6aqLPuw2r1mfW1Lp77VtUZaBPmEe9QMjwsAdOjE x0Uv53q0HLxoPV1BFcRSoVllV2VlYl0aJ4YEEv1YGPHvNb08Z1W753mCte1fY1D/xZ AEmR+PHTsXvJeckQu3sAlkxAdgdOoa0hlJVpQqy7V5fWYdSMWeN4pnI+Mh4W0R4vUZ TQHzkwIHSSjpAkniDPQRtH44mbzg6Q+HWEtZZlS0uWL0+iaLc6bJFg6te4z054HOGS Supv+oceFGs8qKUGM1ktNNocrDUHr0JlunVw+vJ9Vqu8a0GrFiYLv39HROq/2w4/Yy MpzsVQxPRsrcA== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 03/11] gpio: sysfs: Remove redundant check for struct gpio_chip Date: Fri, 13 Feb 2026 09:29:50 +0000 Message-ID: <20260213092958.864411-4-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" gpiochip_sysfs_unregister() is only called by gpiochip_remove() where the struct gpio_chip is ensured. Remove the redundant check. Signed-off-by: Tzung-Bi Shih Reviewed-by: Linus Walleij --- v3: - Pass struct gpio_chip * only. v2: https://lore.kernel.org/all/20260203061059.975605-4-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-9-tzungbi@kernel.org drivers/gpio/gpiolib-sysfs.c | 10 ++-------- drivers/gpio/gpiolib-sysfs.h | 4 ++-- drivers/gpio/gpiolib.c | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index cd553acf3055..97e269f30945 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -1048,11 +1048,11 @@ int gpiochip_sysfs_register(struct gpio_device *gde= v) return 0; } =20 -void gpiochip_sysfs_unregister(struct gpio_device *gdev) +void gpiochip_sysfs_unregister(struct gpio_chip *chip) { + struct gpio_device *gdev =3D chip->gpiodev; struct gpiodev_data *data; struct gpio_desc *desc; - struct gpio_chip *chip; =20 scoped_guard(mutex, &sysfs_lock) { data =3D gdev_get_data(gdev); @@ -1066,12 +1066,6 @@ void gpiochip_sysfs_unregister(struct gpio_device *g= dev) kfree(data); } =20 - guard(srcu)(&gdev->srcu); - - chip =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!chip) - return; - /* unregister gpiod class devices owned by sysfs */ for_each_gpio_desc_with_flag(chip, desc, GPIOD_FLAG_SYSFS) { gpiod_unexport(desc); diff --git a/drivers/gpio/gpiolib-sysfs.h b/drivers/gpio/gpiolib-sysfs.h index b794b396d6a5..9ee2f9dd268f 100644 --- a/drivers/gpio/gpiolib-sysfs.h +++ b/drivers/gpio/gpiolib-sysfs.h @@ -8,7 +8,7 @@ struct gpio_device; #ifdef CONFIG_GPIO_SYSFS =20 int gpiochip_sysfs_register(struct gpio_device *gdev); -void gpiochip_sysfs_unregister(struct gpio_device *gdev); +void gpiochip_sysfs_unregister(struct gpio_chip *chip); =20 #else =20 @@ -17,7 +17,7 @@ static inline int gpiochip_sysfs_register(struct gpio_dev= ice *gdev) return 0; } =20 -static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev) +static inline void gpiochip_sysfs_unregister(struct gpio_chip *chip) { } =20 diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1a3fd7600835..3ff57b1e51bf 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1286,7 +1286,7 @@ void gpiochip_remove(struct gpio_chip *gc) struct gpio_device *gdev =3D gc->gpiodev; =20 /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ - gpiochip_sysfs_unregister(gdev); + gpiochip_sysfs_unregister(gc); gpiochip_free_hogs(gc); gpiochip_free_remaining_irqs(gc); =20 --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E00F432695F; Fri, 13 Feb 2026 09:31:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975075; cv=none; b=XsIwDUYcO6kPNogT8/vprfUFeRgGH91JgzaA8tjZY1owJGJbhXNoTWn6YId3Xa+kDJT5QxB+A+5PEBygRkxEjTXW7+4oPYKvCI+GfI/8I8t8snguqt9seyZYoeHkeMAmLF1XIrt/rHUJP7EsL2SrOK2BfCrsJ37hMDT3gkuEFWc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975075; c=relaxed/simple; bh=a0Nuy0UYMO/xZM1sfMO/NhXKrBeZbiAntWD51TL+aEo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=goJK/X4CmxvUJs4mg6BhdSJWLsCh5UIUjpnnZVATGBccynLESyRbN1tVgQtpVaJwitYj+5EZUCF0v4dWSOvyNq95cS3Xi+4XolYJfbw+dy9smUc4BFqp+sryJ3IrVbuEVZJZjufKVCbrfzGkYxjullKJlr/99togWvc3PRQ8Y3Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KnUp4c4i; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KnUp4c4i" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F388BC116C6; Fri, 13 Feb 2026 09:31:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975074; bh=a0Nuy0UYMO/xZM1sfMO/NhXKrBeZbiAntWD51TL+aEo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KnUp4c4igH3L73SeFnlJHue+5d6oQX4YIFccDtCwThwzVbiuoGmNVpWCP++xvgp8c JN9UAfUcP95a0oEQ5e32iacV967RH6sawoW7qHfmylfXOizHVNRZ016E2Xyeq/qmzC NJA4OOMxZn3nJEAmDTlD/8Xmh7dlkaD7FGt8YFCFBdmr9KJ7JzJVV5wuKChmVGVIhz jwBCbLKLTH6PX4XK6NgpqB524QGAbsAQ7LA19p11lamvyE/8noVXXgEz+hOkdW+Hdz XqBxYxW1s4EJsYt6H9FMAK9DrkxgVNLR+3Z5QBaQiPx99Ef0E2H3ZzsV9Mr3N2KbrW 4fIfQr9yf4dKg== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 04/11] gpio: Ensure struct gpio_chip for gpiochip_setup_dev() Date: Fri, 13 Feb 2026 09:29:51 +0000 Message-ID: <20260213092958.864411-5-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Ensure struct gpio_chip for gpiochip_setup_dev(). This eliminates a few checks for struct gpio_chip. Signed-off-by: Tzung-Bi Shih --- v3: - Pass struct gpio_chip * only. v2: https://lore.kernel.org/all/20260203061059.975605-5-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-10-tzungbi@kernel.org drivers/gpio/gpiolib-cdev.c | 12 ++---------- drivers/gpio/gpiolib-cdev.h | 2 +- drivers/gpio/gpiolib-sysfs.c | 13 +++---------- drivers/gpio/gpiolib-sysfs.h | 4 ++-- drivers/gpio/gpiolib.c | 24 +++++++++++++++++------- 5 files changed, 25 insertions(+), 30 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 2adc3c070908..b028198adba8 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2782,9 +2782,9 @@ static const struct file_operations gpio_fileops =3D { #endif }; =20 -int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt) +int gpiolib_cdev_register(struct gpio_chip *gc, dev_t devt) { - struct gpio_chip *gc; + struct gpio_device *gdev =3D gc->gpiodev; int ret; =20 cdev_init(&gdev->chrdev, &gpio_fileops); @@ -2802,14 +2802,6 @@ int gpiolib_cdev_register(struct gpio_device *gdev, = dev_t devt) return ret; } =20 - guard(srcu)(&gdev->srcu); - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!gc) { - cdev_device_del(&gdev->chrdev, &gdev->dev); - destroy_workqueue(gdev->line_state_wq); - return -ENODEV; - } - gpiochip_dbg(gc, "added GPIO chardev (%d:%d)\n", MAJOR(devt), gdev->id); =20 return 0; diff --git a/drivers/gpio/gpiolib-cdev.h b/drivers/gpio/gpiolib-cdev.h index b42644cbffb8..4a9cb3335d99 100644 --- a/drivers/gpio/gpiolib-cdev.h +++ b/drivers/gpio/gpiolib-cdev.h @@ -7,7 +7,7 @@ =20 struct gpio_device; =20 -int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt); +int gpiolib_cdev_register(struct gpio_chip *gc, dev_t devt); void gpiolib_cdev_unregister(struct gpio_device *gdev); =20 #endif /* GPIOLIB_CDEV_H */ diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 97e269f30945..3fdcfa0c7d42 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -978,10 +978,10 @@ void gpiod_unexport(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_unexport); =20 -int gpiochip_sysfs_register(struct gpio_device *gdev) +int gpiochip_sysfs_register(struct gpio_chip *chip) { + struct gpio_device *gdev =3D chip->gpiodev; struct gpiodev_data *data; - struct gpio_chip *chip; struct device *parent; int err; =20 @@ -994,12 +994,6 @@ int gpiochip_sysfs_register(struct gpio_device *gdev) if (!class_is_registered(&gpio_class)) return 0; =20 - guard(srcu)(&gdev->srcu); - - chip =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!chip) - return -ENODEV; - /* * For sysfs backward compatibility we need to preserve this * preferred parenting to the gpio_chip parent field, if set. @@ -1080,10 +1074,9 @@ void gpiochip_sysfs_unregister(struct gpio_chip *chi= p) */ static int gpiofind_sysfs_register(struct gpio_chip *gc, const void *data) { - struct gpio_device *gdev =3D gc->gpiodev; int ret; =20 - ret =3D gpiochip_sysfs_register(gdev); + ret =3D gpiochip_sysfs_register(gc); if (ret) gpiochip_err(gc, "failed to register the sysfs entry: %d\n", ret); =20 diff --git a/drivers/gpio/gpiolib-sysfs.h b/drivers/gpio/gpiolib-sysfs.h index 9ee2f9dd268f..aacc8e6454a4 100644 --- a/drivers/gpio/gpiolib-sysfs.h +++ b/drivers/gpio/gpiolib-sysfs.h @@ -7,12 +7,12 @@ struct gpio_device; =20 #ifdef CONFIG_GPIO_SYSFS =20 -int gpiochip_sysfs_register(struct gpio_device *gdev); +int gpiochip_sysfs_register(struct gpio_chip *chip); void gpiochip_sysfs_unregister(struct gpio_chip *chip); =20 #else =20 -static inline int gpiochip_sysfs_register(struct gpio_device *gdev) +static inline int gpiochip_sysfs_register(struct gpio_chip *chip) { return 0; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 3ff57b1e51bf..74ee7bfb974c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -882,14 +882,14 @@ static const struct device_type gpio_dev_type =3D { }; =20 #ifdef CONFIG_GPIO_CDEV -#define gcdev_register(gdev, devt) gpiolib_cdev_register((gdev), (devt)) +#define gcdev_register(gc, devt) gpiolib_cdev_register((gc), (devt)) #define gcdev_unregister(gdev) gpiolib_cdev_unregister((gdev)) #else /* * gpiolib_cdev_register() indirectly calls device_add(), which is still * required even when cdev is not selected. */ -#define gcdev_register(gdev, devt) device_add(&(gdev)->dev) +#define gcdev_register(gc, devt) device_add(&(gc)->gpiodev->dev) #define gcdev_unregister(gdev) device_del(&(gdev)->dev) #endif =20 @@ -897,8 +897,9 @@ static const struct device_type gpio_dev_type =3D { * An initial reference count has been held in gpiochip_add_data_with_key(= ). * The caller should drop the reference via gpio_device_put() on errors. */ -static int gpiochip_setup_dev(struct gpio_device *gdev) +static int gpiochip_setup_dev(struct gpio_chip *gc) { + struct gpio_device *gdev =3D gc->gpiodev; struct fwnode_handle *fwnode =3D dev_fwnode(&gdev->dev); int ret; =20 @@ -911,11 +912,11 @@ static int gpiochip_setup_dev(struct gpio_device *gde= v) if (fwnode && !fwnode->dev) fwnode_dev_initialized(fwnode, false); =20 - ret =3D gcdev_register(gdev, gpio_devt); + ret =3D gcdev_register(gc, gpio_devt); if (ret) return ret; =20 - ret =3D gpiochip_sysfs_register(gdev); + ret =3D gpiochip_sysfs_register(gc); if (ret) goto err_remove_device; =20 @@ -962,13 +963,22 @@ static void machine_gpiochip_add(struct gpio_chip *gc) static void gpiochip_setup_devs(void) { struct gpio_device *gdev; + struct gpio_chip *gc; int ret; =20 guard(srcu)(&gpio_devices_srcu); =20 list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { - ret =3D gpiochip_setup_dev(gdev); + guard(srcu)(&gdev->srcu); + + gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + if (!gc) { + dev_err(&gdev->dev, "Underlying GPIO chip is gone\n"); + continue; + } + + ret =3D gpiochip_setup_dev(gc); if (ret) { gpio_device_put(gdev); dev_err(&gdev->dev, @@ -1226,7 +1236,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, * (i.e., `gpio_bus_type` is ready). Otherwise, defer until later. */ if (gpiolib_initialized) { - ret =3D gpiochip_setup_dev(gdev); + ret =3D gpiochip_setup_dev(gc); if (ret) goto err_teardown_shared; } --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A83C31A044; Fri, 13 Feb 2026 09:31:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975078; cv=none; b=ncsT83phnt/Sn/al26fWXx3AdfO1A1SOXAlpCctJaBJE6mm+8bqUlY67IRoQh4PDQsvdypb+Asm0RCOhMBtOQZWT1b5jyiobbtwN8Nm2MKj5XR/DNE6ufJOQJV1TBnZkCrc/poVEMUPBpAWnLHnlKkK5ce4wSK0l6dECV8pDcpI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975078; c=relaxed/simple; bh=MhNx3S0dVlpNxKMRcdobUk3hHUbH0H41bs4+2RGrNYw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cOkkvWDs4B7sPL+nMTE0SnpTfPto9x2cSiqQHvds1jpe43/YL8jMdIZoMtpjZ4GJFKBVFZjosZG1iH4jjNKB3Uj6RizRIEEgpLk4emGn3gGSSLhXtpP+Z9k5Txe+69pdZjiLFxbx8YWwkkaZJdnSuyzsCAEk5gVmLaMmmPRUzSA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TWrwKmsz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TWrwKmsz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F1429C19421; Fri, 13 Feb 2026 09:31:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975077; bh=MhNx3S0dVlpNxKMRcdobUk3hHUbH0H41bs4+2RGrNYw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TWrwKmszBLe/Bar8C4Mt8P2JxMjERmVpyNENpy0vWefh6rLl8F/jQzCpGL/f2ff+1 IbgTE7zn12xKEzb6j/gNFYRnlsVPzfuKRlhSHtgXGkOZ02XuW1TNrn7aeZw2NwdA8k 3DtJC+aJQZe3xc+Eh0f+J0N7GwDAyS8C6e0j/xg66UmERfCvRKhV+uMVRGT/XSpVKP 2SwvsbIgc6Uhp4+dg9O/RiNFUFQch2BK2FAPYxJjW8ysRtewLdUrZ+3ZoOGLOmhXmD d6MFxCEk+2pBeCVkn8/54jXpPxPjQYv7AfVD0kfFwEp6ZdvpQ9Q6zPfxUQCA4VhHyo MFsXxqxjGpH1g== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 05/11] gpio: cdev: Don't check struct gpio_chip in gpio_chrdev_open() Date: Fri, 13 Feb 2026 09:29:52 +0000 Message-ID: <20260213092958.864411-6-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" It's harmless even if: chrdev_open() and cdev_device_del() run at the same time, and gpio_chrdev_open() gets called after the underlying GPIO chip has gone. The subsequent file operations check the availability of struct gpio_chip anyway. Don't check struct gpio_chip in gpio_chrdev_open(). Signed-off-by: Tzung-Bi Shih Reviewed-by: Linus Walleij --- v3: - No changes. v2: https://lore.kernel.org/all/20260203061059.975605-6-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-11-tzungbi@kernel.org drivers/gpio/gpiolib-cdev.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index b028198adba8..2e3484a89a3b 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2689,12 +2689,6 @@ static int gpio_chrdev_open(struct inode *inode, str= uct file *file) struct gpio_chardev_data *cdev; int ret =3D -ENOMEM; =20 - guard(srcu)(&gdev->srcu); - - /* Fail on open if the backing gpiochip is gone */ - if (!rcu_access_pointer(gdev->chip)) - return -ENODEV; - cdev =3D kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) return -ENOMEM; --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D64E4330D2F; Fri, 13 Feb 2026 09:31:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975080; cv=none; b=hVjB6aXpVM6dcRwXeLOGVWCvJ8+DjrMrqXShIvd0CTxkqAfy09FrRt7/ua7XRCRHaTsjJo3xOCOf50ttPMpg4ZGBKZ35VFE2MgLc9TzfR9o7vc2ep42LrTXRfb8Pr/7wCg1z5PM0f3xb3cFHJ2lMbIfjITdEzi+WmAcu4rYlz7o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975080; c=relaxed/simple; bh=e2rjlk7t7f4ZfFXrzmIQZo5qI3Y6tD4XAgPM3cvoa0o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YAd68liSMjt8aV4vK2GMiuHRR4CCENqedSdiKVAMhqUEyYYWYaUq7hyLzsl3iVBel0mDQOw+pJyqdvw+fUOmGpWhNoudoNx/3sdw4HgtXclAN+pTQrJizJgcO7npUGZF0cvmbxEC+TLRwW2cQ1x0x4OYkIqnItDlT0vuiqkDZ+U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fbBPFdb5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fbBPFdb5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EEA89C116C6; Fri, 13 Feb 2026 09:31:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975080; bh=e2rjlk7t7f4ZfFXrzmIQZo5qI3Y6tD4XAgPM3cvoa0o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fbBPFdb538bvYN5cXWUaJd5BouODIj8x/1byeXIP5kajQwi59A8W2F5B7pfcZHgOt 4vW6rEsMKK1RA8yOXjZKc8rS0lvuCiT2ffLweazioqf7WoG5+geACE8DYOqn5qrrk6 OOwS6v5Eu9IwSACsOzqRuDYxKVglcf/mox5otpm1ZGAeJtFt6W+h3/PtvdmvqTSwOc 5XdA4QBx4NkskPYatrqlxnn3Jnm6xZOuDcqXX6De85TTTeGvo5Y4ebEGg4TAdmWk53 sAANC9ZpDZa6tIhY8k61NUm4mteVcCZKnRsyCdjCy07PimHa+nQZBJ26403Rk77kGL l4IoIaaSJa/ZQ== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 06/11] selftests: gpio: Add gpio-cdev-uaf tests Date: Fri, 13 Feb 2026 09:29:53 +0000 Message-ID: <20260213092958.864411-7-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add tests for gpiolib-cdev to make sure accessing to dangling resources via the opening file descriptor won't crash the system after the underlying resource providers have gone. Signed-off-by: Tzung-Bi Shih Reviewed-by: Linus Walleij --- v3: - No changes. v2: https://lore.kernel.org/all/20260203061059.975605-7-tzungbi@kernel.org - Remove fdinfo test which is redundant. v1: https://lore.kernel.org/all/20260116081036.352286-12-tzungbi@kernel.org tools/testing/selftests/gpio/Makefile | 5 +- tools/testing/selftests/gpio/gpio-cdev-uaf.c | 292 ++++++++++++++++++ tools/testing/selftests/gpio/gpio-cdev-uaf.sh | 63 ++++ 3 files changed, 358 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/gpio/gpio-cdev-uaf.c create mode 100755 tools/testing/selftests/gpio/gpio-cdev-uaf.sh diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftest= s/gpio/Makefile index 7bfe315f7001..741ab21e1260 100644 --- a/tools/testing/selftests/gpio/Makefile +++ b/tools/testing/selftests/gpio/Makefile @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 =20 -TEST_PROGS :=3D gpio-mockup.sh gpio-sim.sh gpio-aggregator.sh +TEST_PROGS :=3D gpio-mockup.sh gpio-sim.sh gpio-aggregator.sh gpio-cdev-ua= f.sh TEST_FILES :=3D gpio-mockup-sysfs.sh -TEST_GEN_PROGS_EXTENDED :=3D gpio-mockup-cdev gpio-chip-info gpio-line-name +TEST_GEN_PROGS_EXTENDED :=3D gpio-mockup-cdev gpio-chip-info gpio-line-nam= e \ + gpio-cdev-uaf CFLAGS +=3D -O2 -g -Wall $(KHDR_INCLUDES) =20 include ../lib.mk diff --git a/tools/testing/selftests/gpio/gpio-cdev-uaf.c b/tools/testing/s= elftests/gpio/gpio-cdev-uaf.c new file mode 100644 index 000000000000..765d3cc4f0ef --- /dev/null +++ b/tools/testing/selftests/gpio/gpio-cdev-uaf.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * GPIO character device helper for UAF tests. + * + * Copyright 2026 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONFIGFS_DIR "/sys/kernel/config/gpio-sim" +#define PROCFS_DIR "/proc" + +static void print_usage(void) +{ + printf("usage:\n"); + printf(" gpio-cdev-uaf [chip|handle|event|req] [poll|read|ioctl]\n"); +} + +static int _create_chip(const char *name, int create) +{ + char path[64]; + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s", name); + + if (create) + return mkdir(path, 0755); + else + return rmdir(path); +} + +static int create_chip(const char *name) +{ + return _create_chip(name, 1); +} + +static void remove_chip(const char *name) +{ + _create_chip(name, 0); +} + +static int _create_bank(const char *chip_name, const char *name, int creat= e) +{ + char path[64]; + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s/%s", chip_name, name); + + if (create) + return mkdir(path, 0755); + else + return rmdir(path); +} + +static int create_bank(const char *chip_name, const char *name) +{ + return _create_bank(chip_name, name, 1); +} + +static void remove_bank(const char *chip_name, const char *name) +{ + _create_bank(chip_name, name, 0); +} + +static int _enable_chip(const char *name, int enable) +{ + char path[64]; + int fd, ret; + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s/live", name); + + fd =3D open(path, O_WRONLY); + if (fd =3D=3D -1) + return fd; + + if (enable) + ret =3D write(fd, "1", 1); + else + ret =3D write(fd, "0", 1); + + close(fd); + return ret =3D=3D 1 ? 0 : -1; +} + +static int enable_chip(const char *name) +{ + return _enable_chip(name, 1); +} + +static void disable_chip(const char *name) +{ + _enable_chip(name, 0); +} + +static int open_chip(const char *chip_name, const char *bank_name) +{ + char path[64], dev_name[32]; + int ret, fd; + + ret =3D create_chip(chip_name); + if (ret) { + fprintf(stderr, "failed to create chip\n"); + return ret; + } + + ret =3D create_bank(chip_name, bank_name); + if (ret) { + fprintf(stderr, "failed to create bank\n"); + goto err_remove_chip; + } + + ret =3D enable_chip(chip_name); + if (ret) { + fprintf(stderr, "failed to enable chip\n"); + goto err_remove_bank; + } + + snprintf(path, sizeof(path), CONFIGFS_DIR "/%s/%s/chip_name", + chip_name, bank_name); + + fd =3D open(path, O_RDONLY); + if (fd =3D=3D -1) { + ret =3D fd; + fprintf(stderr, "failed to open %s\n", path); + goto err_disable_chip; + } + + ret =3D read(fd, dev_name, sizeof(dev_name) - 1); + close(fd); + if (ret =3D=3D -1) { + fprintf(stderr, "failed to read %s\n", path); + goto err_disable_chip; + } + dev_name[ret] =3D '\0'; + if (ret && dev_name[ret - 1] =3D=3D '\n') + dev_name[ret - 1] =3D '\0'; + + snprintf(path, sizeof(path), "/dev/%s", dev_name); + + fd =3D open(path, O_RDWR); + if (fd =3D=3D -1) { + ret =3D fd; + fprintf(stderr, "failed to open %s\n", path); + goto err_disable_chip; + } + + return fd; +err_disable_chip: + disable_chip(chip_name); +err_remove_bank: + remove_bank(chip_name, bank_name); +err_remove_chip: + remove_chip(chip_name); + return ret; +} + +static void close_chip(const char *chip_name, const char *bank_name) +{ + disable_chip(chip_name); + remove_bank(chip_name, bank_name); + remove_chip(chip_name); +} + +static int test_poll(int fd) +{ + struct pollfd pfds; + + pfds.fd =3D fd; + pfds.events =3D POLLIN; + pfds.revents =3D 0; + + if (poll(&pfds, 1, 0) =3D=3D -1) + return -1; + + return (pfds.revents & ~(POLLHUP | POLLERR)) ? -1 : 0; +} + +static int test_read(int fd) +{ + char data; + + if (read(fd, &data, 1) =3D=3D -1 && errno =3D=3D ENODEV) + return 0; + return -1; +} + +static int test_ioctl(int fd) +{ + if (ioctl(fd, 0, NULL) =3D=3D -1 && errno =3D=3D ENODEV) + return 0; + return -1; +} + +int main(int argc, char **argv) +{ + int cfd, fd, ret; + int (*test_func)(int); + + if (argc !=3D 3) { + print_usage(); + return EXIT_FAILURE; + } + + if (strcmp(argv[1], "chip") =3D=3D 0 || + strcmp(argv[1], "event") =3D=3D 0 || + strcmp(argv[1], "req") =3D=3D 0) { + if (strcmp(argv[2], "poll") && + strcmp(argv[2], "read") && + strcmp(argv[2], "ioctl")) { + fprintf(stderr, "unknown command: %s\n", argv[2]); + return EXIT_FAILURE; + } + } else if (strcmp(argv[1], "handle") =3D=3D 0) { + if (strcmp(argv[2], "ioctl")) { + fprintf(stderr, "unknown command: %s\n", argv[2]); + return EXIT_FAILURE; + } + } else { + fprintf(stderr, "unknown command: %s\n", argv[1]); + return EXIT_FAILURE; + } + + if (strcmp(argv[2], "poll") =3D=3D 0) + test_func =3D test_poll; + else if (strcmp(argv[2], "read") =3D=3D 0) + test_func =3D test_read; + else /* strcmp(argv[2], "ioctl") =3D=3D 0 */ + test_func =3D test_ioctl; + + cfd =3D open_chip("chip", "bank"); + if (cfd =3D=3D -1) { + fprintf(stderr, "failed to open chip\n"); + return EXIT_FAILURE; + } + + /* Step 1: Hold a FD to the test target. */ + if (strcmp(argv[1], "chip") =3D=3D 0) { + fd =3D cfd; + } else if (strcmp(argv[1], "handle") =3D=3D 0) { + struct gpiohandle_request req =3D {0}; + + req.lines =3D 1; + if (ioctl(cfd, GPIO_GET_LINEHANDLE_IOCTL, &req) =3D=3D -1) { + fprintf(stderr, "failed to get handle FD\n"); + goto err_close_chip; + } + + close(cfd); + fd =3D req.fd; + } else if (strcmp(argv[1], "event") =3D=3D 0) { + struct gpioevent_request req =3D {0}; + + if (ioctl(cfd, GPIO_GET_LINEEVENT_IOCTL, &req) =3D=3D -1) { + fprintf(stderr, "failed to get event FD\n"); + goto err_close_chip; + } + + close(cfd); + fd =3D req.fd; + } else { /* strcmp(argv[1], "req") =3D=3D 0 */ + struct gpio_v2_line_request req =3D {0}; + + req.num_lines =3D 1; + if (ioctl(cfd, GPIO_V2_GET_LINE_IOCTL, &req) =3D=3D -1) { + fprintf(stderr, "failed to get req FD\n"); + goto err_close_chip; + } + + close(cfd); + fd =3D req.fd; + } + + /* Step 2: Free the chip. */ + close_chip("chip", "bank"); + + /* Step 3: Access the dangling FD to trigger UAF. */ + ret =3D test_func(fd); + close(fd); + return ret ? EXIT_FAILURE : EXIT_SUCCESS; +err_close_chip: + close(cfd); + close_chip("chip", "bank"); + return EXIT_FAILURE; +} diff --git a/tools/testing/selftests/gpio/gpio-cdev-uaf.sh b/tools/testing/= selftests/gpio/gpio-cdev-uaf.sh new file mode 100755 index 000000000000..6e47533019cf --- /dev/null +++ b/tools/testing/selftests/gpio/gpio-cdev-uaf.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright 2026 Google LLC + +BASE_DIR=3D`dirname $0` +MODULE=3D"gpio-cdev-uaf" + +fail() { + echo "$*" >&2 + echo "GPIO $MODULE test FAIL" + exit 1 +} + +skip() { + echo "$*" >&2 + echo "GPIO $MODULE test SKIP" + exit 4 +} + +# Load the gpio-sim module. This will pull in configfs if needed too. +modprobe gpio-sim || skip "unable to load the gpio-sim module" +# Make sure configfs is mounted at /sys/kernel/config. Wait a bit if neede= d. +for _ in `seq 5`; do + mountpoint -q /sys/kernel/config && break + mount -t configfs none /sys/kernel/config + sleep 0.1 +done +mountpoint -q /sys/kernel/config || \ + skip "configfs not mounted at /sys/kernel/config" + +echo "1. GPIO" + +echo "1.1. poll" +$BASE_DIR/gpio-cdev-uaf chip poll || fail "failed to test chip poll" +echo "1.2. read" +$BASE_DIR/gpio-cdev-uaf chip read || fail "failed to test chip read" +echo "1.3. ioctl" +$BASE_DIR/gpio-cdev-uaf chip ioctl || fail "failed to test chip ioctl" + +echo "2. linehandle" + +echo "2.1. ioctl" +$BASE_DIR/gpio-cdev-uaf handle ioctl || fail "failed to test handle ioctl" + +echo "3. lineevent" + +echo "3.1. read" +$BASE_DIR/gpio-cdev-uaf event read || fail "failed to test event read" +echo "3.2. poll" +$BASE_DIR/gpio-cdev-uaf event poll || fail "failed to test event poll" +echo "3.3. ioctl" +$BASE_DIR/gpio-cdev-uaf event ioctl || fail "failed to test event ioctl" + +echo "4. linereq" + +echo "4.1. read" +$BASE_DIR/gpio-cdev-uaf req read || fail "failed to test req read" +echo "4.2. poll" +$BASE_DIR/gpio-cdev-uaf req poll || fail "failed to test req poll" +echo "4.3. ioctl" +$BASE_DIR/gpio-cdev-uaf req ioctl || fail "failed to test req ioctl" + +echo "GPIO $MODULE test PASS" --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED35732FA0D; Fri, 13 Feb 2026 09:31:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975084; cv=none; b=fY5r2b7rx3AqVeBIWGpoGQk6OD/fgED40PQp2IhleGPCuJ11AlaR5zMSgJ4A90K/rZ1x5eQdhpoySIi3KVgyfdsRjip1uY2g36S1CpYxvL+eWJjH+Tes/i29Y22goMt80Op4BOwFL3WnCVfssxI1gWJKPBdUZUeeU4vmvlpZTX0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975084; c=relaxed/simple; bh=lOvVM0s0yLJNqglO3n3zKCRlmz00D9/9tjJ5GMv3RjA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CG6EisafcHklXUwnvXhkh9bsdV3mj0EEEhTea4GkqbTJGTcm9xKha5dzGGLhOkoQ2LeV9VavwrUDd/Wl+WFMXChsMmLmDTP3TsmV6YIowZGE7rb8D46CiM26yqe6upMNMzC18zF6TipZnw3fbYg9cmm3+7w3Oh4EVRdlgsWYW8s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PCboUjWN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PCboUjWN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EBE1DC19421; Fri, 13 Feb 2026 09:31:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975083; bh=lOvVM0s0yLJNqglO3n3zKCRlmz00D9/9tjJ5GMv3RjA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PCboUjWNXIBsPhFBy9G8zBOKrFO8/WfwUIKn++enI5Z0m7gs7D9eljeNQgMg2cTCf J5gdqHVzfIj1qT+AEqpatv8u4gEm7M5GE+Ap+jbJdcKNftkZs7jlbd1nJWQFlN3js0 RlD3VvLokn00reGLZMosApmb5vLN8Axg9UHJAwySlzlZSxJNo9ye/nSaKK4gUAtoCb 18wnYfYGYO+5c0e5iY6KofHzQ/DGp1+HyqArQphTbmg8ryUdKVSfhfynSjLVNpSHm0 q4OKcNokBcUUw1iRgYM/6/vIMGmPpPSzkMNelpisBw/3iBflgATl3ShZefXEwKPx+F 3FqGGecEORDkQ== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 07/11] gpio: Add revocable provider handle for struct gpio_chip Date: Fri, 13 Feb 2026 09:29:54 +0000 Message-ID: <20260213092958.864411-8-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The underlying chip can be removed asynchronously. `gdev->srcu` is used to ensure the synchronization before accessing `gdev->chip`. Revocable encapsulates the details. Add revocable provider handle for the corresponding struct gpio_chip in struct gpio_device so that it can start to hide the synchronization details. Signed-off-by: Tzung-Bi Shih --- v3: - Change revocable API usages accordingly. v2: https://lore.kernel.org/all/20260203061059.975605-8-tzungbi@kernel.org - Change usages accordingly after applying https://lore.kernel.org/all/20260129143733.45618-2-tzungbi@kernel.org. - Add __rcu for `chip_rp`. - Pass pointer of pointer to revocable_provider_revoke(). - Rebase accordingly after applying https://lore.kernel.org/all/20260203060210.972243-1-tzungbi@kernel.org. v1: https://lore.kernel.org/all/20260116081036.352286-13-tzungbi@kernel.org drivers/gpio/gpiolib.c | 16 ++++++++++++++-- drivers/gpio/gpiolib.h | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 74ee7bfb974c..7ef4dc4e6e9e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -869,6 +870,8 @@ static void gpiodev_release(struct device *dev) synchronize_srcu(&gdev->desc_srcu); cleanup_srcu_struct(&gdev->desc_srcu); =20 + if (gdev->chip_rp) + revocable_put(gdev->chip_rp); ida_free(&gpio_ida, gdev->id); kfree_const(gdev->label); kfree(gdev->descs); @@ -1115,6 +1118,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc,= void *data, goto err_put_device; } =20 + gdev->chip_rp =3D revocable_alloc(gc); + if (!gdev->chip_rp) { + ret =3D -ENOMEM; + goto err_put_device; + } + gdev->can_sleep =3D gc->can_sleep; rwlock_init(&gdev->line_state_lock); RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); @@ -1144,7 +1153,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, if (base < 0) { ret =3D base; base =3D 0; - goto err_put_device; + goto err_free_rp; } =20 /* @@ -1164,7 +1173,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, ret =3D gpiodev_add_to_list_unlocked(gdev); if (ret) { gpiochip_err(gc, "GPIO integer space overlap, cannot add chip\n"); - goto err_put_device; + goto err_free_rp; } } =20 @@ -1261,6 +1270,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, scoped_guard(mutex, &gpio_devices_lock) list_del_rcu(&gdev->list); synchronize_srcu(&gpio_devices_srcu); +err_free_rp: + revocable_revoke(gdev->chip_rp); err_put_device: gpio_device_put(gdev); goto err_print_message; @@ -1307,6 +1318,7 @@ void gpiochip_remove(struct gpio_chip *gc) /* Numb the device, cancelling all outstanding operations */ rcu_assign_pointer(gdev->chip, NULL); synchronize_srcu(&gdev->srcu); + revocable_revoke(gdev->chip_rp); gpio_device_teardown_shared(gdev); gpiochip_irqchip_remove(gc); acpi_gpiochip_remove(gc); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 3abb90385829..56643f40e87e 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -52,6 +52,7 @@ * @device_notifier: used to notify character device wait queues about the= GPIO * device being unregistered * @srcu: protects the pointer to the underlying GPIO chip + * @chip_rp: revocable provider handle for the corresponding struct gpio_c= hip. * @pin_ranges: range of pins served by the GPIO driver * * This state container holds most of the runtime variable data @@ -79,6 +80,7 @@ struct gpio_device { struct workqueue_struct *line_state_wq; struct blocking_notifier_head device_notifier; struct srcu_struct srcu; + struct revocable *chip_rp; =20 #ifdef CONFIG_PINCTRL /* --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EED27342CA7; Fri, 13 Feb 2026 09:31:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975087; cv=none; b=d+sEIxpNvboiOqZOQRHy8H5X7K1msCQ6ZInFnYEmQTawne0oZjGLn0OTObwvVgJxpczRuIGdfN7syaHp2K1b34kkgg5C2XBFFgHSb+ZCuEpEHgwCM4wKCVLs2ejHs8s4YXwi1T26Jyy5AJGb51kOXZ42OVtt3+ukrzpvZWT6XXE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975087; c=relaxed/simple; bh=tUJZiJKQBfBigmMk6Pe8ka6NjX4yQ1Z38jqocLE+8Qs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MNcUIRXu5wZyQUilrW+sJL5PT/MB5Qw8jn0X/laHgQeoTf87nSjbswEyA3x5YdKqHFu+j71ijvEKycP3hRp8BmNPrpCfEKWRSNeBhmOiTiJMMoThjRJmuAGDizgYBuSFpRvkidQzzv+sHvrJ65CVPFbCYHjlixX0F6uz6CvhVfo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WNTrb9sg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WNTrb9sg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E969BC116C6; Fri, 13 Feb 2026 09:31:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975086; bh=tUJZiJKQBfBigmMk6Pe8ka6NjX4yQ1Z38jqocLE+8Qs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WNTrb9sg7prnP8BhIbE8SOF7hf+UYw1Nc3FTKKk5r+i47cgAOHtSuhCYrq/H9EwgM VkRUu5EGCRVfNwY7Zlr+cTIRPmZgO9YNKmsoJOCxfQqrrrEEhNmIeau4AElI7+i8Ru fK/q7mQB4/kUYfPn8n2N/RheDD+1zvOxS4P4gwR2+Kj1GuVFdagOqlbo6gpmumSuXs qaBEN0emqvmYWymgioE4jDVZ7coaggLEIDOFiKZi8daLdNtHLNrxSPjtzRJxTpN7zy TyLbyvgcaiIwVghXaKfLGZf4o5hSbBPUPQyWqZm9I2R5tzVpE46qERjVH8hbSBThzR 5Q8aIISuSVcMg== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 08/11] gpio: cdev: Leverage revocable for accessing struct gpio_chip Date: Fri, 13 Feb 2026 09:29:55 +0000 Message-ID: <20260213092958.864411-9-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for accessing the struct gpio_chip. Signed-off-by: Tzung-Bi Shih --- v3: - Change revocable API usages accordingly. v2: https://lore.kernel.org/all/20260203061059.975605-9-tzungbi@kernel.org - Change usages accordingly after applying https://lore.kernel.org/all/20260129143733.45618-4-tzungbi@kernel.org. - Preserve a local storage for `struct revocable`. - Combine multiple patches (see "v1:"). - Fix a race condition reported in https://lore.kernel.org/all/CAMRc=3DMcDaipt85OHm0MksLkuf6E79dY1uNSqqbcJno= QTUs81Pw@mail.gmail.com/ and analyzed in https://lore.kernel.org/all/aXEEUWwkxHZzCnaI@tzungbi-laptop/. In v1, the blocking_notifier_chain_unregister() will be skipped if the chip has been removed, leading an UAF in gpiolib_cdev_unregister(). In v2, it won't skip blocking_notifier_chain_unregister(). v1: - https://lore.kernel.org/all/20260116081036.352286-14-tzungbi@kernel.org - https://lore.kernel.org/all/20260116081036.352286-15-tzungbi@kernel.org - https://lore.kernel.org/all/20260116081036.352286-16-tzungbi@kernel.org - https://lore.kernel.org/all/20260116081036.352286-17-tzungbi@kernel.org - https://lore.kernel.org/all/20260116081036.352286-18-tzungbi@kernel.org drivers/gpio/gpiolib-cdev.c | 68 ++++++++++++++----------------------- 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 2e3484a89a3b..b491e2737ef2 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -210,11 +211,9 @@ static long linehandle_ioctl(struct file *file, unsign= ed int cmd, DECLARE_BITMAP(vals, GPIOHANDLES_MAX); unsigned int i; int ret; + struct gpio_chip *gc; =20 - guard(srcu)(&lh->gdev->srcu); - - if (!rcu_access_pointer(lh->gdev->chip)) - return -ENODEV; + revocable_try_access_or_return(lh->gdev->chip_rp, gc); =20 switch (cmd) { case GPIOHANDLE_GET_LINE_VALUES_IOCTL: @@ -1432,11 +1431,9 @@ static long linereq_ioctl(struct file *file, unsigne= d int cmd, { struct linereq *lr =3D file->private_data; void __user *ip =3D (void __user *)arg; + struct gpio_chip *gc; =20 - guard(srcu)(&lr->gdev->srcu); - - if (!rcu_access_pointer(lr->gdev->chip)) - return -ENODEV; + revocable_try_access_or_return(lr->gdev->chip_rp, gc); =20 switch (cmd) { case GPIO_V2_LINE_GET_VALUES_IOCTL: @@ -1463,10 +1460,10 @@ static __poll_t linereq_poll(struct file *file, { struct linereq *lr =3D file->private_data; __poll_t events =3D 0; + struct gpio_chip *gc; =20 - guard(srcu)(&lr->gdev->srcu); - - if (!rcu_access_pointer(lr->gdev->chip)) + revocable_try_access_with(lr->gdev->chip_rp, gc); + if (!gc) return EPOLLHUP | EPOLLERR; =20 poll_wait(file, &lr->wait, wait); @@ -1485,11 +1482,9 @@ static ssize_t linereq_read(struct file *file, char = __user *buf, struct gpio_v2_line_event le; ssize_t bytes_read =3D 0; int ret; + struct gpio_chip *gc; =20 - guard(srcu)(&lr->gdev->srcu); - - if (!rcu_access_pointer(lr->gdev->chip)) - return -ENODEV; + revocable_try_access_or_return(lr->gdev->chip_rp, gc); =20 if (count < sizeof(le)) return -EINVAL; @@ -1781,10 +1776,10 @@ static __poll_t lineevent_poll(struct file *file, { struct lineevent_state *le =3D file->private_data; __poll_t events =3D 0; + struct gpio_chip *gc; =20 - guard(srcu)(&le->gdev->srcu); - - if (!rcu_access_pointer(le->gdev->chip)) + revocable_try_access_with(le->gdev->chip_rp, gc); + if (!gc) return EPOLLHUP | EPOLLERR; =20 poll_wait(file, &le->wait, wait); @@ -1819,11 +1814,9 @@ static ssize_t lineevent_read(struct file *file, cha= r __user *buf, ssize_t bytes_read =3D 0; ssize_t ge_size; int ret; + struct gpio_chip *gc; =20 - guard(srcu)(&le->gdev->srcu); - - if (!rcu_access_pointer(le->gdev->chip)) - return -ENODEV; + revocable_try_access_or_return(le->gdev->chip_rp, gc); =20 /* * When compatible system call is being used the struct gpioevent_data, @@ -1901,11 +1894,9 @@ static long lineevent_ioctl(struct file *file, unsig= ned int cmd, struct lineevent_state *le =3D file->private_data; void __user *ip =3D (void __user *)arg; struct gpiohandle_data ghd; + struct gpio_chip *gc; =20 - guard(srcu)(&le->gdev->srcu); - - if (!rcu_access_pointer(le->gdev->chip)) - return -ENODEV; + revocable_try_access_or_return(le->gdev->chip_rp, gc); =20 /* * We can get the value for an event line but not set it, @@ -2434,12 +2425,10 @@ static long gpio_ioctl(struct file *file, unsigned = int cmd, unsigned long arg) struct gpio_chardev_data *cdev =3D file->private_data; struct gpio_device *gdev =3D cdev->gdev; void __user *ip =3D (void __user *)arg; - - guard(srcu)(&gdev->srcu); + struct gpio_chip *gc; =20 /* We fail any subsequent ioctl():s when the chip is gone */ - if (!rcu_access_pointer(gdev->chip)) - return -ENODEV; + revocable_try_access_or_return(gdev->chip_rp, gc); =20 /* Fill in the struct and pass to userspace */ switch (cmd) { @@ -2497,12 +2486,9 @@ static void lineinfo_changed_func(struct work_struct= *work) * Pin functions are in general much more static and while it's * not 100% bullet-proof, it's good enough for most cases. */ - scoped_guard(srcu, &ctx->gdev->srcu) { - gc =3D srcu_dereference(ctx->gdev->chip, &ctx->gdev->srcu); - if (gc && - !pinctrl_gpio_can_use_line(gc, ctx->chg.info.offset)) + revocable_try_access_with_scoped(ctx->gdev->chip_rp, gc) + if (!pinctrl_gpio_can_use_line(gc, ctx->chg.info.offset)) ctx->chg.info.flags |=3D GPIO_V2_LINE_FLAG_USED; - } } =20 ret =3D kfifo_in_spinlocked(&ctx->cdev->events, &ctx->chg, 1, @@ -2583,10 +2569,10 @@ static __poll_t lineinfo_watch_poll(struct file *fi= le, { struct gpio_chardev_data *cdev =3D file->private_data; __poll_t events =3D 0; + struct gpio_chip *gc; =20 - guard(srcu)(&cdev->gdev->srcu); - - if (!rcu_access_pointer(cdev->gdev->chip)) + revocable_try_access_with(cdev->gdev->chip_rp, gc); + if (!gc) return EPOLLHUP | EPOLLERR; =20 poll_wait(file, &cdev->wait, pollt); @@ -2606,11 +2592,9 @@ static ssize_t lineinfo_watch_read(struct file *file= , char __user *buf, ssize_t bytes_read =3D 0; int ret; size_t event_size; + struct gpio_chip *gc; =20 - guard(srcu)(&cdev->gdev->srcu); - - if (!rcu_access_pointer(cdev->gdev->chip)) - return -ENODEV; + revocable_try_access_or_return(cdev->gdev->chip_rp, gc); =20 #ifndef CONFIG_GPIO_CDEV_V1 event_size =3D sizeof(struct gpio_v2_line_info_changed); --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D40622DC774; Fri, 13 Feb 2026 09:31:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975089; cv=none; b=l1RAaV4S0W+TznhdEBX1B29gF1z8jaeIP0o/MF/Po0utOnK3ItmDMijhJnRkiUP7bPZbkK0bNCzLD3q4OB+QaLGZLWso2l8gGzjtIi/vzZtpRzKv9lreS6G8aH8PmI+JF+YkIeomUr9X58kAVGCKovSFuJfofLLjsRIy7SKi6RE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975089; c=relaxed/simple; bh=xrZENLz4dIxYm05qchHPEj52css9L6e1PnU4QEDqYIU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VSSXOPlv6rIBp+6nOllXcRYvihwt/9UGn0QlMRZ95V/QgP7H/g5aiH0+3HsieVNSLELdsdAbYNbNEGA6PLK0H58Jlmjn9+p9/0Y8OCV4kAgLPbggGAFy1fQpV3VgkbdjYcPkzFmc+zUuQOUo1TvZqVPJBD09muWxc1czvjL0svw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aJWbFHe2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aJWbFHe2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E72D9C16AAE; Fri, 13 Feb 2026 09:31:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975089; bh=xrZENLz4dIxYm05qchHPEj52css9L6e1PnU4QEDqYIU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aJWbFHe2FPlh42eq2d9VlEXZdCY7m/tPUp+h2ZXwIYI0Q+AqUtFPHvqPK8kmMFfIj lO4KSqV5jsKckjUBAmgARyDyCUYVKVxIl8TyW51Mj534xXxcCKXmeePzKEfIrxOeYU DgEjaxvh2UnNExClCG7SCdDs0j4wlfE5DDjS4UcCLFrUAukQov1p4KrUyNPgUDdrdB OU8O6qLovciHPfjPbnq9p6lueXQkkOgSGlpfPJOhL5ZfqC/cvhoEw8GQBEkf1Sxidd N2wmadxzbSB4CkF90JFwp3T1TGd7Fde3f+OaSfTEWJYE+vIGHRpH46L4AqjXI09KW4 U3svKoSA3vWLw== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 09/11] gpio: Remove gpio_chip_guard by using revocable Date: Fri, 13 Feb 2026 09:29:56 +0000 Message-ID: <20260213092958.864411-10-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for accessing the struct gpio_chip instead of using gpio_chip_guard. Signed-off-by: Tzung-Bi Shih --- v3: - Change revocable API usages accordingly. v2: https://lore.kernel.org/all/20260203061059.975605-10-tzungbi@kernel.org - Separate from v1 for including gpio_chip_guard only. v1: https://lore.kernel.org/all/20260116081036.352286-23-tzungbi@kernel.org drivers/gpio/gpiolib-cdev.c | 9 +- drivers/gpio/gpiolib-sysfs.c | 30 +++---- drivers/gpio/gpiolib.c | 163 ++++++++++++++++------------------- drivers/gpio/gpiolib.h | 21 ----- 4 files changed, 89 insertions(+), 134 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index b491e2737ef2..2a61c4aa3e18 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2205,10 +2205,9 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *= desc, u32 debounce_period_us; unsigned long dflags; const char *label; + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return; + revocable_try_access_or_return_void(desc->gdev->chip_rp, gc); =20 memset(info, 0, sizeof(*info)); info->offset =3D gpiod_hwgpio(desc); @@ -2241,10 +2240,10 @@ static void gpio_desc_to_lineinfo(struct gpio_desc = *desc, test_bit(GPIOD_FLAG_IS_HOGGED, &dflags) || test_bit(GPIOD_FLAG_EXPORT, &dflags) || test_bit(GPIOD_FLAG_SYSFS, &dflags) || - !gpiochip_line_is_valid(guard.gc, info->offset)) { + !gpiochip_line_is_valid(gc, info->offset)) { info->flags |=3D GPIO_V2_LINE_FLAG_USED; } else if (!atomic) { - if (!pinctrl_gpio_can_use_line(guard.gc, info->offset)) + if (!pinctrl_gpio_can_use_line(gc, info->offset)) info->flags |=3D GPIO_V2_LINE_FLAG_USED; } =20 diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 3fdcfa0c7d42..9bacd89cba93 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -215,10 +215,9 @@ static int gpio_sysfs_request_irq(struct gpiod_data *d= ata, unsigned char flags) struct gpio_desc *desc =3D data->desc; unsigned long irq_flags; int ret; + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 data->irq =3D gpiod_to_irq(desc); if (data->irq < 0) @@ -244,7 +243,7 @@ static int gpio_sysfs_request_irq(struct gpiod_data *da= ta, unsigned char flags) * Remove this redundant call (along with the corresponding unlock) * when those drivers have been fixed. */ - ret =3D gpiochip_lock_as_irq(guard.gc, gpiod_hwgpio(desc)); + ret =3D gpiochip_lock_as_irq(gc, gpiod_hwgpio(desc)); if (ret < 0) goto err_clr_bits; =20 @@ -258,7 +257,7 @@ static int gpio_sysfs_request_irq(struct gpiod_data *da= ta, unsigned char flags) return 0; =20 err_unlock: - gpiochip_unlock_as_irq(guard.gc, gpiod_hwgpio(desc)); + gpiochip_unlock_as_irq(gc, gpiod_hwgpio(desc)); err_clr_bits: clear_bit(GPIOD_FLAG_EDGE_RISING, &desc->flags); clear_bit(GPIOD_FLAG_EDGE_FALLING, &desc->flags); @@ -273,14 +272,13 @@ static int gpio_sysfs_request_irq(struct gpiod_data *= data, unsigned char flags) static void gpio_sysfs_free_irq(struct gpiod_data *data) { struct gpio_desc *desc =3D data->desc; + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return; + revocable_try_access_or_return_void(desc->gdev->chip_rp, gc); =20 data->irq_flags =3D 0; free_irq(data->irq, data); - gpiochip_unlock_as_irq(guard.gc, gpiod_hwgpio(desc)); + gpiochip_unlock_as_irq(gc, gpiod_hwgpio(desc)); clear_bit(GPIOD_FLAG_EDGE_RISING, &desc->flags); clear_bit(GPIOD_FLAG_EDGE_FALLING, &desc->flags); } @@ -473,13 +471,12 @@ static DEVICE_ATTR_RO(ngpio); static int export_gpio_desc(struct gpio_desc *desc) { int offset, ret; + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 offset =3D gpiod_hwgpio(desc); - if (!gpiochip_line_is_valid(guard.gc, offset)) { + if (!gpiochip_line_is_valid(gc, offset)) { pr_debug_ratelimited("%s: GPIO %d masked\n", __func__, gpiod_hwgpio(desc)); return -EINVAL; @@ -732,6 +729,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction= _may_change) struct gpio_device *gdev; struct attribute **attrs; int status; + struct gpio_chip *gc; =20 /* can't export until sysfs is available ... */ if (!class_is_registered(&gpio_class)) { @@ -744,9 +742,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction= _may_change) return -EINVAL; } =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 if (test_and_set_bit(GPIOD_FLAG_EXPORT, &desc->flags)) return -EPERM; @@ -769,7 +765,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction= _may_change) =20 desc_data->desc =3D desc; mutex_init(&desc_data->mutex); - if (guard.gc->direction_input && guard.gc->direction_output) + if (gc->direction_input && gc->direction_output) desc_data->direction_can_change =3D direction_may_change; else desc_data->direction_can_change =3D false; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7ef4dc4e6e9e..34f2665a9311 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -449,14 +449,13 @@ int gpiod_get_direction(struct gpio_desc *desc) unsigned long flags; unsigned int offset; int ret; + struct gpio_chip *gc; =20 ret =3D validate_desc(desc, __func__); if (ret <=3D 0) return -EINVAL; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 offset =3D gpiod_hwgpio(desc); flags =3D READ_ONCE(desc->flags); @@ -469,7 +468,7 @@ int gpiod_get_direction(struct gpio_desc *desc) test_bit(GPIOD_FLAG_IS_OUT, &flags)) return 0; =20 - ret =3D gpiochip_get_direction(guard.gc, offset); + ret =3D gpiochip_get_direction(gc, offset); if (ret < 0) return ret; =20 @@ -2475,31 +2474,30 @@ int gpiod_request_commit(struct gpio_desc *desc, co= nst char *label) { unsigned int offset; int ret; + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 if (test_and_set_bit(GPIOD_FLAG_REQUESTED, &desc->flags)) return -EBUSY; =20 offset =3D gpiod_hwgpio(desc); - if (!gpiochip_line_is_valid(guard.gc, offset)) + if (!gpiochip_line_is_valid(gc, offset)) return -EINVAL; =20 /* NOTE: gpio_request() can be called in early boot, * before IRQs are enabled, for non-sleeping (SOC) GPIOs. */ =20 - if (guard.gc->request) { - ret =3D guard.gc->request(guard.gc, offset); + if (gc->request) { + ret =3D gc->request(gc, offset); if (ret > 0) ret =3D -EBADE; if (ret) goto out_clear_bit; } =20 - if (guard.gc->get_direction) + if (gc->get_direction) gpiod_get_direction(desc); =20 ret =3D desc_set_label(desc, label ? : "?"); @@ -2536,16 +2534,17 @@ int gpiod_request(struct gpio_desc *desc, const cha= r *label) void gpiod_free_commit(struct gpio_desc *desc) { unsigned long flags; + struct gpio_chip *gc; =20 might_sleep(); =20 - CLASS(gpio_chip_guard, guard)(desc); + revocable_try_access_or_return_void(desc->gdev->chip_rp, gc); =20 flags =3D READ_ONCE(desc->flags); =20 - if (guard.gc && test_bit(GPIOD_FLAG_REQUESTED, &flags)) { - if (guard.gc->free) - guard.gc->free(guard.gc, gpiod_hwgpio(desc)); + if (test_bit(GPIOD_FLAG_REQUESTED, &flags)) { + if (gc->free) + gc->free(gc, gpiod_hwgpio(desc)); =20 clear_bit(GPIOD_FLAG_ACTIVE_LOW, &flags); clear_bit(GPIOD_FLAG_REQUESTED, &flags); @@ -2697,15 +2696,14 @@ EXPORT_SYMBOL_GPL(gpiochip_free_own_desc); int gpio_do_set_config(struct gpio_desc *desc, unsigned long config) { int ret; + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 - if (!guard.gc->set_config) + if (!gc->set_config) return -ENOTSUPP; =20 - ret =3D guard.gc->set_config(guard.gc, gpiod_hwgpio(desc), config); + ret =3D gc->set_config(gc, gpiod_hwgpio(desc), config); if (ret > 0) ret =3D -EBADE; =20 @@ -2874,17 +2872,16 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input); int gpiod_direction_input_nonotify(struct gpio_desc *desc) { int ret =3D 0, dir; + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 /* * It is legal to have no .get() and .direction_input() specified if * the chip is output-only, but you can't specify .direction_input() * and not support the .get() operation, that doesn't make sense. */ - if (!guard.gc->get && guard.gc->direction_input) { + if (!gc->get && gc->direction_input) { gpiod_warn(desc, "%s: missing get() but have direction_input()\n", __func__); @@ -2897,11 +2894,10 @@ int gpiod_direction_input_nonotify(struct gpio_desc= *desc) * direction (if .get_direction() is supported) else we silently * assume we are in input mode after this. */ - if (guard.gc->direction_input) { - ret =3D gpiochip_direction_input(guard.gc, - gpiod_hwgpio(desc)); - } else if (guard.gc->get_direction) { - dir =3D gpiochip_get_direction(guard.gc, gpiod_hwgpio(desc)); + if (gc->direction_input) { + ret =3D gpiochip_direction_input(gc, gpiod_hwgpio(desc)); + } else if (gc->get_direction) { + dir =3D gpiochip_get_direction(gc, gpiod_hwgpio(desc)); if (dir < 0) return dir; =20 @@ -2941,31 +2937,28 @@ static int gpiochip_set(struct gpio_chip *gc, unsig= ned int offset, int value) static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int v= alue) { int val =3D !!value, ret =3D 0, dir; + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 /* * It's OK not to specify .direction_output() if the gpiochip is * output-only, but if there is then not even a .set() operation it * is pretty tricky to drive the output line. */ - if (!guard.gc->set && !guard.gc->direction_output) { + if (!gc->set && !gc->direction_output) { gpiod_warn(desc, "%s: missing set() and direction_output() operations\n", __func__); return -EIO; } =20 - if (guard.gc->direction_output) { - ret =3D gpiochip_direction_output(guard.gc, - gpiod_hwgpio(desc), val); + if (gc->direction_output) { + ret =3D gpiochip_direction_output(gc, gpiod_hwgpio(desc), val); } else { /* Check that we are in output mode if we can */ - if (guard.gc->get_direction) { - dir =3D gpiochip_get_direction(guard.gc, - gpiod_hwgpio(desc)); + if (gc->get_direction) { + dir =3D gpiochip_get_direction(gc, gpiod_hwgpio(desc)); if (dir < 0) return dir; =20 @@ -2980,7 +2973,7 @@ static int gpiod_direction_output_raw_commit(struct g= pio_desc *desc, int value) * If we can't actively set the direction, we are some * output-only chip, so just drive the output as desired. */ - ret =3D gpiochip_set(guard.gc, gpiod_hwgpio(desc), val); + ret =3D gpiochip_set(gc, gpiod_hwgpio(desc), val); if (ret) return ret; } @@ -3118,20 +3111,18 @@ int gpiod_direction_output_nonotify(struct gpio_des= c *desc, int value) int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long fla= gs) { int ret; + struct gpio_chip *gc; =20 VALIDATE_DESC(desc); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 - if (!guard.gc->en_hw_timestamp) { + if (!gc->en_hw_timestamp) { gpiod_warn(desc, "%s: hw ts not supported\n", __func__); return -ENOTSUPP; } =20 - ret =3D guard.gc->en_hw_timestamp(guard.gc, - gpiod_hwgpio(desc), flags); + ret =3D gc->en_hw_timestamp(gc, gpiod_hwgpio(desc), flags); if (ret) gpiod_warn(desc, "%s: hw ts request failed\n", __func__); =20 @@ -3151,20 +3142,18 @@ EXPORT_SYMBOL_GPL(gpiod_enable_hw_timestamp_ns); int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long fl= ags) { int ret; + struct gpio_chip *gc; =20 VALIDATE_DESC(desc); =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 - if (!guard.gc->dis_hw_timestamp) { + if (!gc->dis_hw_timestamp) { gpiod_warn(desc, "%s: hw ts not supported\n", __func__); return -ENOTSUPP; } =20 - ret =3D guard.gc->dis_hw_timestamp(guard.gc, gpiod_hwgpio(desc), - flags); + ret =3D gc->dis_hw_timestamp(gc, gpiod_hwgpio(desc), flags); if (ret) gpiod_warn(desc, "%s: hw ts release failed\n", __func__); =20 @@ -3424,31 +3413,29 @@ int gpiod_get_array_value_complex(bool raw, bool ca= n_sleep, unsigned long *mask, *bits; int first, j; =20 - CLASS(gpio_chip_guard, guard)(desc_array[i]); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc_array[i]->gdev->chip_rp, gc); =20 - if (likely(guard.gc->ngpio <=3D FASTPATH_NGPIO)) { + if (likely(gc->ngpio <=3D FASTPATH_NGPIO)) { mask =3D fastpath_mask; bits =3D fastpath_bits; } else { gfp_t flags =3D can_sleep ? GFP_KERNEL : GFP_ATOMIC; =20 - mask =3D bitmap_alloc(guard.gc->ngpio, flags); + mask =3D bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; =20 - bits =3D bitmap_alloc(guard.gc->ngpio, flags); + bits =3D bitmap_alloc(gc->ngpio, flags); if (!bits) { bitmap_free(mask); return -ENOMEM; } } =20 - bitmap_zero(mask, guard.gc->ngpio); + bitmap_zero(mask, gc->ngpio); =20 if (!can_sleep) - WARN_ON(guard.gc->can_sleep); + WARN_ON(gc->can_sleep); =20 /* collect all inputs belonging to the same chip */ first =3D i; @@ -3463,9 +3450,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_= sleep, i =3D find_next_zero_bit(array_info->get_mask, array_size, i); } while ((i < array_size) && - gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc)); + gpio_device_chip_cmp(desc_array[i]->gdev, gc)); =20 - ret =3D gpio_chip_get_multiple(guard.gc, mask, bits); + ret =3D gpio_chip_get_multiple(gc, mask, bits); if (ret) { if (mask !=3D fastpath_mask) bitmap_free(mask); @@ -3614,15 +3601,14 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_value); static int gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool v= alue) { int ret =3D 0, offset =3D gpiod_hwgpio(desc); + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 if (value) { - ret =3D gpiochip_direction_input(guard.gc, offset); + ret =3D gpiochip_direction_input(gc, offset); } else { - ret =3D gpiochip_direction_output(guard.gc, offset, 0); + ret =3D gpiochip_direction_output(gc, offset, 0); if (!ret) set_bit(GPIOD_FLAG_IS_OUT, &desc->flags); } @@ -3643,17 +3629,16 @@ static int gpio_set_open_drain_value_commit(struct = gpio_desc *desc, bool value) static int gpio_set_open_source_value_commit(struct gpio_desc *desc, bool = value) { int ret =3D 0, offset =3D gpiod_hwgpio(desc); + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 if (value) { - ret =3D gpiochip_direction_output(guard.gc, offset, 1); + ret =3D gpiochip_direction_output(gc, offset, 1); if (!ret) set_bit(GPIOD_FLAG_IS_OUT, &desc->flags); } else { - ret =3D gpiochip_direction_input(guard.gc, offset); + ret =3D gpiochip_direction_input(gc, offset); } trace_gpio_direction(desc_to_gpio(desc), !value, ret); if (ret < 0) @@ -3666,15 +3651,15 @@ static int gpio_set_open_source_value_commit(struct= gpio_desc *desc, bool value) =20 static int gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value) { + struct gpio_chip *gc; + if (unlikely(!test_bit(GPIOD_FLAG_IS_OUT, &desc->flags))) return -EPERM; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 trace_gpio_value(desc_to_gpio(desc), 0, value); - return gpiochip_set(guard.gc, gpiod_hwgpio(desc), value); + return gpiochip_set(gc, gpiod_hwgpio(desc), value); } =20 /* @@ -3769,31 +3754,29 @@ int gpiod_set_array_value_complex(bool raw, bool ca= n_sleep, unsigned long *mask, *bits; int count =3D 0; =20 - CLASS(gpio_chip_guard, guard)(desc_array[i]); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc_array[i]->gdev->chip_rp, gc); =20 - if (likely(guard.gc->ngpio <=3D FASTPATH_NGPIO)) { + if (likely(gc->ngpio <=3D FASTPATH_NGPIO)) { mask =3D fastpath_mask; bits =3D fastpath_bits; } else { gfp_t flags =3D can_sleep ? GFP_KERNEL : GFP_ATOMIC; =20 - mask =3D bitmap_alloc(guard.gc->ngpio, flags); + mask =3D bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; =20 - bits =3D bitmap_alloc(guard.gc->ngpio, flags); + bits =3D bitmap_alloc(gc->ngpio, flags); if (!bits) { bitmap_free(mask); return -ENOMEM; } } =20 - bitmap_zero(mask, guard.gc->ngpio); + bitmap_zero(mask, gc->ngpio); =20 if (!can_sleep) - WARN_ON(guard.gc->can_sleep); + WARN_ON(gc->can_sleep); =20 do { struct gpio_desc *desc =3D desc_array[i]; @@ -3832,10 +3815,10 @@ int gpiod_set_array_value_complex(bool raw, bool ca= n_sleep, i =3D find_next_zero_bit(array_info->set_mask, array_size, i); } while ((i < array_size) && - gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc)); + gpio_device_chip_cmp(desc_array[i]->gdev, gc)); /* push collected bits to outputs */ if (count !=3D 0) { - ret =3D gpiochip_set_multiple(guard.gc, mask, bits); + ret =3D gpiochip_set_multiple(gc, mask, bits); if (ret) return ret; } @@ -5051,18 +5034,16 @@ int gpiod_hog(struct gpio_desc *desc, const char *n= ame, struct gpio_desc *local_desc; int hwnum; int ret; + struct gpio_chip *gc; =20 - CLASS(gpio_chip_guard, guard)(desc); - if (!guard.gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 if (test_and_set_bit(GPIOD_FLAG_IS_HOGGED, &desc->flags)) return 0; =20 hwnum =3D gpiod_hwgpio(desc); =20 - local_desc =3D gpiochip_request_own_desc(guard.gc, hwnum, name, - lflags, dflags); + local_desc =3D gpiochip_request_own_desc(gc, hwnum, name, lflags, dflags); if (IS_ERR(local_desc)) { clear_bit(GPIOD_FLAG_IS_HOGGED, &desc->flags); ret =3D PTR_ERR(local_desc); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 56643f40e87e..a254a57f37f5 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -224,27 +224,6 @@ struct gpio_desc { =20 #define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) =3D=3D -ENOE= NT) =20 -struct gpio_chip_guard { - struct gpio_device *gdev; - struct gpio_chip *gc; - int idx; -}; - -DEFINE_CLASS(gpio_chip_guard, - struct gpio_chip_guard, - srcu_read_unlock(&_T.gdev->srcu, _T.idx), - ({ - struct gpio_chip_guard _guard; - - _guard.gdev =3D desc->gdev; - _guard.idx =3D srcu_read_lock(&_guard.gdev->srcu); - _guard.gc =3D srcu_dereference(_guard.gdev->chip, - &_guard.gdev->srcu); - - _guard; - }), - struct gpio_desc *desc) - int gpiod_request(struct gpio_desc *desc, const char *label); int gpiod_request_commit(struct gpio_desc *desc, const char *label); void gpiod_free(struct gpio_desc *desc); --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 054A6330B27; Fri, 13 Feb 2026 09:31:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975093; cv=none; b=lMuU3q2AyKp8k36+GrBMq6QPeZ2KzH5elRSW1SmgqI1idNsZ/TVMRA6N7arG3+IgUbIS8FNCv0dTtnWzaHHZJUKi+EOEgpEPxDuzOGGHY54E5Vi6KsLKMoV2e4didmCBrFhDISRp6b/XkzVGUiptaHdy+BTivOH5PDiFMMrgd+M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975093; c=relaxed/simple; bh=sc68Y2yfU7vJPsAs/fppEoHXv0dQsgkbHlyNAxyY/KQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RLFvViXWw5NgbOZRh7Jva5EqYlTRe390bhOWO6p8qi06mPYWmlC7+Z0wd9cSTI21GOWdMgCT7l/JyRy8ZGNfXlhzBwB++WSnYrJX8zlfwPSpQWBb4/NyDXh1omHGpdIqJlJqtgFyHRSvWNY4KOCInFP/urJd70QFp1tZrb0dhZk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GMBJTlbQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GMBJTlbQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1B14AC16AAE; Fri, 13 Feb 2026 09:31:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975092; bh=sc68Y2yfU7vJPsAs/fppEoHXv0dQsgkbHlyNAxyY/KQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GMBJTlbQSoMbGuLvCNfO7N884adZYuIlKQDbzSiU0o0QVR9nSSFfFkPx3UCogq+Cn XfVQvFDnmcL7soAQnDHouOcYXVZj9vLWi6o/C5dPDbOkmAV8e1TEUeD6fV7Qj+7ZKg e6+Flw5JWGIplEsm/fjknKLfax9HvXiwosZgo9Lk+k3iWSciFPAac40Ft7F6TpuXxo fJXByL2vGxWf+nFpeCxRkw3FdSBOXcNgl40TdXxSobPLET9YD2sc5ls4X9cWBa0deF Nk/KvyZuCYE9fmkHfzEcxVC6KI0+IRN7DifOT/DZEB/Dro+wbdfO8iP/FXf0MiraVZ 27JpTACoiU5Og== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 10/11] gpio: Leverage revocable for accessing struct gpio_chip Date: Fri, 13 Feb 2026 09:29:57 +0000 Message-ID: <20260213092958.864411-11-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Struct gpio_device now provides a revocable provider to the underlying struct gpio_chip. Leverage revocable for accessing the struct gpio_chip. Signed-off-by: Tzung-Bi Shih --- v3: - Change revocable API usages accordingly. v2: https://lore.kernel.org/all/20260203061059.975605-11-tzungbi@kernel.org - Separate from v1(a) for excluding gpio_chip_guard and combine v1(b). v1(a): - https://lore.kernel.org/all/20260116081036.352286-23-tzungbi@kernel.org v1(b): - https://lore.kernel.org/all/20260116081036.352286-19-tzungbi@kernel.org drivers/gpio/gpiolib.c | 60 +++++++++++++----------------------------- 1 file changed, 18 insertions(+), 42 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 34f2665a9311..2ba78add3417 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -338,7 +338,10 @@ EXPORT_SYMBOL(gpio_device_get_label); */ struct gpio_chip *gpio_device_get_chip(struct gpio_device *gdev) { - return rcu_dereference_check(gdev->chip, 1); + struct gpio_chip *gc; + + revocable_try_access_with(gdev->chip_rp, gc); + return gc; } EXPORT_SYMBOL_GPL(gpio_device_get_chip); =20 @@ -556,9 +559,7 @@ static struct gpio_desc *gpio_name_to_desc(const char *= const name) =20 list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + revocable_try_access_with(gdev->chip_rp, gc); if (!gc) continue; =20 @@ -972,9 +973,7 @@ static void gpiochip_setup_devs(void) =20 list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + revocable_try_access_with(gdev->chip_rp, gc); if (!gc) { dev_err(&gdev->dev, "Underlying GPIO chip is gone\n"); continue; @@ -1378,11 +1377,11 @@ struct gpio_device *gpio_device_find(const void *da= ta, if (!device_is_registered(&gdev->dev)) continue; =20 - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + revocable_try_access_with(gdev->chip_rp, gc); + if (!gc) + continue; =20 - if (gc && match(gc, data)) + if (match(gc, data)) return gpio_device_get(gdev); } =20 @@ -3310,18 +3309,10 @@ static int gpio_chip_get_value(struct gpio_chip *gc= , const struct gpio_desc *des =20 static int gpiod_get_raw_value_commit(const struct gpio_desc *desc) { - struct gpio_device *gdev; struct gpio_chip *gc; int value; =20 - /* FIXME Unable to use gpio_chip_guard due to const desc. */ - gdev =3D desc->gdev; - - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 value =3D gpio_chip_get_value(gc, desc); value =3D value < 0 ? value : !!value; @@ -3360,9 +3351,10 @@ static int gpio_chip_get_multiple(struct gpio_chip *= gc, /* The 'other' chip must be protected with its GPIO device's SRCU. */ static bool gpio_device_chip_cmp(struct gpio_device *gdev, struct gpio_chi= p *gc) { - guard(srcu)(&gdev->srcu); + struct gpio_chip *chip; =20 - return gc =3D=3D srcu_dereference(gdev->chip, &gdev->srcu); + revocable_try_access_with(gdev->chip_rp, chip); + return chip ? chip =3D=3D gc : false; } =20 int gpiod_get_array_value_complex(bool raw, bool can_sleep, @@ -3385,11 +3377,7 @@ int gpiod_get_array_value_complex(bool raw, bool can= _sleep, if (!can_sleep) WARN_ON(array_info->gdev->can_sleep); =20 - guard(srcu)(&array_info->gdev->srcu); - gc =3D srcu_dereference(array_info->gdev->chip, - &array_info->gdev->srcu); - if (!gc) - return -ENODEV; + revocable_try_access_or_return(array_info->gdev->chip_rp, gc); =20 ret =3D gpio_chip_get_multiple(gc, array_info->get_mask, value_bitmap); @@ -3726,11 +3714,7 @@ int gpiod_set_array_value_complex(bool raw, bool can= _sleep, return -EPERM; } =20 - guard(srcu)(&array_info->gdev->srcu); - gc =3D srcu_dereference(array_info->gdev->chip, - &array_info->gdev->srcu); - if (!gc) - return -ENODEV; + revocable_try_access_or_return(array_info->gdev->chip_rp, gc); =20 if (!raw && !bitmap_empty(array_info->invert_mask, array_size)) bitmap_xor(value_bitmap, value_bitmap, @@ -4024,7 +4008,6 @@ EXPORT_SYMBOL_GPL(gpiod_is_shared); */ int gpiod_to_irq(const struct gpio_desc *desc) { - struct gpio_device *gdev; struct gpio_chip *gc; int offset; int ret; @@ -4033,12 +4016,7 @@ int gpiod_to_irq(const struct gpio_desc *desc) if (ret <=3D 0) return -EINVAL; =20 - gdev =3D desc->gdev; - /* FIXME Cannot use gpio_chip_guard due to const desc. */ - guard(srcu)(&gdev->srcu); - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); - if (!gc) - return -ENODEV; + revocable_try_access_or_return(desc->gdev->chip_rp, gc); =20 offset =3D gpiod_hwgpio(desc); if (gc->to_irq) { @@ -5413,9 +5391,7 @@ static int gpiolib_seq_show(struct seq_file *s, void = *v) if (priv->newline) seq_putc(s, '\n'); =20 - guard(srcu)(&gdev->srcu); - - gc =3D srcu_dereference(gdev->chip, &gdev->srcu); + revocable_try_access_with(gdev->chip_rp, gc); if (!gc) { seq_printf(s, "%s: (dangling chip)\n", dev_name(&gdev->dev)); return 0; --=20 2.53.0.310.g728cabbaf7-goog From nobody Thu Apr 2 09:14:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1501834D4F1; Fri, 13 Feb 2026 09:31:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975096; cv=none; b=eRK7bk6OFlyoPRCf9wQGMewX9dI+qmMZFIXwSEWhGE9iAxfEk5nbrRdDMinsAC2sA4jRMj4D/P+4KYVhYsjRpeVJmq4V/urlreLRJ4ykQhKa2FUpiVRQIMPwrEEwYT7Mh8A0LhKz2iHw1DLhmZOcPr7wHBJCkqIqrhhCIX9zF3s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770975096; c=relaxed/simple; bh=HELCfPtNvCvEoazpaboPAkrUFqcVe3WmgWs+WHvPHis=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qoq4UdfYFZ0kNv55m4v2xNFwI8Y7rm4njQskaRZ7nrAXD/2NzxYf9wYdFaP7v0l41B4FgZ5j4XEUacOlssJ+gN+dU+VN/PNNTCuE4RCsbFQCbJpLDsj8iaQKdQ1BHAT1Gu2BJ78KjoHeMM9CWSVHScNX6E7yAhgjiA2AB91GdwU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PTeHzrz7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PTeHzrz7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1832EC2BC86; Fri, 13 Feb 2026 09:31:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770975095; bh=HELCfPtNvCvEoazpaboPAkrUFqcVe3WmgWs+WHvPHis=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PTeHzrz7fBmNzxotEJYS7hqWo2i21aU5yS451f2gH4/xkQC65J7JEaSfuZGwdEp5h qaRw7SH2+YHJ0Rk5gqCgL3oitiq+K51odE8tuTAeeEgp0d17UyPa0HZ8ae5wphzFaW lK+sU9wfAR3J5aTT+riG+cP75ynvcG2RU1WDeSQv+exRBfecv1A3VBDzrnN4sUCPi3 i2lmYTCSj3ZBMF7fDJ2EZplvqZIUTErpa9VUGxj7axVVGeDT/Iy8GNjWPN2wynTXag AO7PGO4RDDfwNAOWi7Els9HNOtwzbfDr2Fs2QrmZ8tCRzve1DKP3RX4ohb0iPkfpDr FoBArUrhNA9Rw== From: Tzung-Bi Shih To: Bartosz Golaszewski , Linus Walleij Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Jonathan Corbet , Shuah Khan , Laurent Pinchart , Wolfram Sang , Jason Gunthorpe , Johan Hovold , "Paul E . McKenney" , Dan Williams , chrome-platform@lists.linux.dev, tzungbi@kernel.org, linux-gpio@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 11/11] gpio: Remove unused `chip` and `srcu` in struct gpio_device Date: Fri, 13 Feb 2026 09:29:58 +0000 Message-ID: <20260213092958.864411-12-tzungbi@kernel.org> X-Mailer: git-send-email 2.53.0.310.g728cabbaf7-goog In-Reply-To: <20260213092958.864411-1-tzungbi@kernel.org> References: <20260213092958.864411-1-tzungbi@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" `chip` and `srcu` in struct gpio_device are unused as their usages are replaced to use revocable. Remove them. Signed-off-by: Tzung-Bi Shih --- v3: - No changes. v2: https://lore.kernel.org/all/20260203061059.975605-12-tzungbi@kernel.org - No changes. v1: https://lore.kernel.org/all/20260116081036.352286-24-tzungbi@kernel.org drivers/gpio/gpiolib.c | 26 +------------------------- drivers/gpio/gpiolib.h | 4 ---- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2ba78add3417..01be9f6978f2 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -423,8 +423,6 @@ static int gpiochip_get_direction(struct gpio_chip *gc,= unsigned int offset) { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (WARN_ON(!gc->get_direction)) return -EOPNOTSUPP; =20 @@ -875,7 +873,6 @@ static void gpiodev_release(struct device *dev) ida_free(&gpio_ida, gdev->id); kfree_const(gdev->label); kfree(gdev->descs); - cleanup_srcu_struct(&gdev->srcu); kfree(gdev); } =20 @@ -1076,14 +1073,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc,= void *data, goto err_free_gdev; gdev->id =3D ret; =20 - ret =3D init_srcu_struct(&gdev->srcu); - if (ret) - goto err_free_ida; - rcu_assign_pointer(gdev->chip, gc); - ret =3D init_srcu_struct(&gdev->desc_srcu); if (ret) - goto err_cleanup_gdev_srcu; + goto err_free_ida; =20 ret =3D dev_set_name(&gdev->dev, GPIOCHIP_NAME "%d", gdev->id); if (ret) @@ -1276,8 +1268,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, = void *data, =20 err_cleanup_desc_srcu: cleanup_srcu_struct(&gdev->desc_srcu); -err_cleanup_gdev_srcu: - cleanup_srcu_struct(&gdev->srcu); err_free_ida: ida_free(&gpio_ida, gdev->id); err_free_gdev: @@ -1314,8 +1304,6 @@ void gpiochip_remove(struct gpio_chip *gc) synchronize_srcu(&gpio_devices_srcu); =20 /* Numb the device, cancelling all outstanding operations */ - rcu_assign_pointer(gdev->chip, NULL); - synchronize_srcu(&gdev->srcu); revocable_revoke(gdev->chip_rp); gpio_device_teardown_shared(gdev); gpiochip_irqchip_remove(gc); @@ -2815,8 +2803,6 @@ static int gpiochip_direction_input(struct gpio_chip = *gc, unsigned int offset) { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (WARN_ON(!gc->direction_input)) return -EOPNOTSUPP; =20 @@ -2832,8 +2818,6 @@ static int gpiochip_direction_output(struct gpio_chip= *gc, unsigned int offset, { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (WARN_ON(!gc->direction_output)) return -EOPNOTSUPP; =20 @@ -2921,8 +2905,6 @@ static int gpiochip_set(struct gpio_chip *gc, unsigne= d int offset, int value) { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (WARN_ON(unlikely(!gc->set))) return -EOPNOTSUPP; =20 @@ -3270,8 +3252,6 @@ static int gpiochip_get(struct gpio_chip *gc, unsigne= d int offset) { int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - /* Make sure this is called after checking for gc->get(). */ ret =3D gc->get(gc, offset); if (ret > 1) @@ -3323,8 +3303,6 @@ static int gpiod_get_raw_value_commit(const struct gp= io_desc *desc) static int gpio_chip_get_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { - lockdep_assert_held(&gc->gpiodev->srcu); - if (gc->get_multiple) { int ret; =20 @@ -3668,8 +3646,6 @@ static int gpiochip_set_multiple(struct gpio_chip *gc, unsigned int i; int ret; =20 - lockdep_assert_held(&gc->gpiodev->srcu); - if (gc->set_multiple) { ret =3D gc->set_multiple(gc, mask, bits); if (ret > 0) diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index a254a57f37f5..6a97d9726c20 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -28,7 +28,6 @@ * @chrdev: character device for the GPIO device * @id: numerical ID number for the GPIO chip * @owner: helps prevent removal of modules exporting active GPIOs - * @chip: pointer to the corresponding gpiochip, holding static * data for this device * @descs: array of ngpio descriptors. * @valid_mask: If not %NULL, holds bitmask of GPIOs which are valid to be @@ -51,7 +50,6 @@ * process context * @device_notifier: used to notify character device wait queues about the= GPIO * device being unregistered - * @srcu: protects the pointer to the underlying GPIO chip * @chip_rp: revocable provider handle for the corresponding struct gpio_c= hip. * @pin_ranges: range of pins served by the GPIO driver * @@ -65,7 +63,6 @@ struct gpio_device { struct cdev chrdev; int id; struct module *owner; - struct gpio_chip __rcu *chip; struct gpio_desc *descs; unsigned long *valid_mask; struct srcu_struct desc_srcu; @@ -79,7 +76,6 @@ struct gpio_device { rwlock_t line_state_lock; struct workqueue_struct *line_state_wq; struct blocking_notifier_head device_notifier; - struct srcu_struct srcu; struct revocable *chip_rp; =20 #ifdef CONFIG_PINCTRL --=20 2.53.0.310.g728cabbaf7-goog