From patchwork Thu Dec 21 18:43:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 757290 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9DE5F1F601 for ; Thu, 21 Dec 2023 18:43:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=bgdev.pl Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bgdev.pl Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bgdev-pl.20230601.gappssmtp.com header.i=@bgdev-pl.20230601.gappssmtp.com header.b="XARgSbdu" Received: by mail-wm1-f52.google.com with SMTP id 5b1f17b1804b1-40c339d2b88so11074275e9.3 for ; Thu, 21 Dec 2023 10:43:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20230601.gappssmtp.com; s=20230601; t=1703184202; x=1703789002; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4Q+b8wqRYdeT/k9zOecma8OzQDizS0i1OJX7YWZXzlI=; b=XARgSbduESI25dQ+m3yC9TGoNDJ5wTGbWexTt0rzwxyQJtwqAQipl5JM8JSrTnsDVN /iUrGFHiVWUJlzUk1AnTG/mpym2pd2TKJdJ7Bnp764vM4ztiCTZjZtO3woEufVfVHbva L3SfcND19OKQrt6JW1cfbAojKGgZD9rAtyCj/GBBcVDom4ADGP/JZjAQrPa8Fl4jGxZG X29JK4pXu/A4ED7PExFYJDFYicTpMStskNL/H6dIMlHQy6GsXJFyh28uqZzmIzsRiu2q KDO0jagMOAPUb+42uZ2yULaZ269Py4mure484qDhfMdVlNhlIxi01liK9Ass3hNlIBkJ tjtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703184202; x=1703789002; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4Q+b8wqRYdeT/k9zOecma8OzQDizS0i1OJX7YWZXzlI=; b=ZwMbCATf+oUjBc1uW4UXJSvqHLRiri3pVa/znwT4LAxTuG8DPZXxOMwDgDNFMSnrcw TKT3Pyuhq98XlB6wr6fsA06c5fJvzIcKYMVkj5zoDR+aD8McP4VL1dSMmU9ZDnq8Sqf9 VfF/f3TbszSj8FUl0LD9VFQHp3t4irBwS9WtJRj+aqjlPEirPrSdhMI+AHZJbSySfbYz 1FjB3Lff0KLcsG1Jy9lbC2JN/RL+BqzTFvAWnh3NjTL0j4s5Pl9cNee/Nj4LjjtO1Q6g xz7OnIlrZa24T33OF4MKdt51KDEz2pfxqpwbwOmiN2lRkobn7cm6MpdyYSZ1mom8ZUKv Bsvw== X-Gm-Message-State: AOJu0YzEyLI61HcpNzAf29Bb8KiFBn/oPNEfv4jViREg9SMmcp4KYqtX eX+KTeASPyn1lg55XwuFfEbhMq4BbdfVvw== X-Google-Smtp-Source: AGHT+IF0uPlgDGW1mQSUSQjVUv6wHrWs9d4zgygbAZgEleT0uOWDAR0Gl33bGvpoR6Ie9mooUPVFlw== X-Received: by 2002:a05:600c:19cf:b0:40d:3159:9303 with SMTP id u15-20020a05600c19cf00b0040d31599303mr80995wmq.155.1703184201920; Thu, 21 Dec 2023 10:43:21 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:7701:a2c3:cba4:74db]) by smtp.gmail.com with ESMTPSA id t20-20020a05600c199400b0040c42681fcesm4188059wmq.15.2023.12.21.10.43.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Dec 2023 10:43:21 -0800 (PST) From: Bartosz Golaszewski To: Linus Walleij , Andy Shevchenko , Kent Gibson Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Bartosz Golaszewski Subject: [PATCH 1/2] gpiolib: replace the GPIO device mutex with a read-write semaphore Date: Thu, 21 Dec 2023 19:43:15 +0100 Message-Id: <20231221184316.24506-2-brgl@bgdev.pl> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231221184316.24506-1-brgl@bgdev.pl> References: <20231221184316.24506-1-brgl@bgdev.pl> Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Bartosz Golaszewski There are only two spots where we modify (add to or remove objects from) the GPIO device list. Readers should be able to access it concurrently. Replace the mutex with a read-write semaphore and adjust the locking operations accordingly. Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-sysfs.c | 2 +- drivers/gpio/gpiolib.c | 18 +++++++++--------- drivers/gpio/gpiolib.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index ae4fc013b675..e4159344a0ea 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -771,7 +771,7 @@ int gpiochip_sysfs_register_all(void) struct gpio_device *gdev; int ret; - guard(mutex)(&gpio_devices_lock); + guard(rwsem_read)(&gpio_devices_sem); list_for_each_entry(gdev, &gpio_devices, list) { if (gdev->mockdev) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c9ca809b55de..1baeb6778ec6 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -98,7 +98,7 @@ static DEFINE_MUTEX(gpio_lookup_lock); static LIST_HEAD(gpio_lookup_list); LIST_HEAD(gpio_devices); -DEFINE_MUTEX(gpio_devices_lock); +DECLARE_RWSEM(gpio_devices_sem); static DEFINE_MUTEX(gpio_machine_hogs_mutex); static LIST_HEAD(gpio_machine_hogs); @@ -131,7 +131,7 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) { struct gpio_device *gdev; - scoped_guard(mutex, &gpio_devices_lock) { + scoped_guard(rwsem_read, &gpio_devices_sem) { list_for_each_entry(gdev, &gpio_devices, list) { if (gdev->base <= gpio && gdev->base + gdev->ngpio > gpio) @@ -415,7 +415,7 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name) if (!name) return NULL; - guard(mutex)(&gpio_devices_lock); + guard(rwsem_read)(&gpio_devices_sem); list_for_each_entry(gdev, &gpio_devices, list) { struct gpio_desc *desc; @@ -664,7 +664,7 @@ static void gpiodev_release(struct device *dev) { struct gpio_device *gdev = to_gpio_device(dev); - scoped_guard(mutex, &gpio_devices_lock) + scoped_guard(rwsem_write, &gpio_devices_sem) list_del(&gdev->list); ida_free(&gpio_ida, gdev->id); @@ -887,7 +887,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, gdev->ngpio = gc->ngpio; - scoped_guard(mutex, &gpio_devices_lock) { + scoped_guard(rwsem_write, &gpio_devices_sem) { /* * TODO: this allocates a Linux GPIO number base in the global * GPIO numberspace for this chip. In the long run we want to @@ -1017,7 +1017,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, goto err_print_message; } err_remove_from_list: - scoped_guard(mutex, &gpio_devices_lock) + scoped_guard(rwsem_write, &gpio_devices_sem) list_del(&gdev->list); err_free_label: kfree_const(gdev->label); @@ -1127,7 +1127,7 @@ struct gpio_device *gpio_device_find(void *data, */ might_sleep(); - guard(mutex)(&gpio_devices_lock); + guard(rwsem_read)(&gpio_devices_sem); list_for_each_entry(gdev, &gpio_devices, list) { if (gdev->chip && match(gdev->chip, data)) @@ -4745,7 +4745,7 @@ static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos) s->private = ""; - guard(mutex)(&gpio_devices_lock); + guard(rwsem_read)(&gpio_devices_sem); list_for_each_entry(gdev, &gpio_devices, list) { if (index-- == 0) @@ -4760,7 +4760,7 @@ static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos) struct gpio_device *gdev = v; void *ret = NULL; - scoped_guard(mutex, &gpio_devices_lock) { + scoped_guard(rwsem_read, &gpio_devices_sem) { if (list_is_last(&gdev->list, &gpio_devices)) ret = NULL; else diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 0ce7451a6b24..97df54abf57a 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -137,7 +137,7 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory); extern spinlock_t gpio_lock; extern struct list_head gpio_devices; -extern struct mutex gpio_devices_lock; +extern struct rw_semaphore gpio_devices_sem; void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action); From patchwork Thu Dec 21 18:43:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 757679 Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6D6B05B1ED for ; Thu, 21 Dec 2023 18:43:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=bgdev.pl Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bgdev.pl Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bgdev-pl.20230601.gappssmtp.com header.i=@bgdev-pl.20230601.gappssmtp.com header.b="KRjJ0okl" Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-40d2e56f3a6so6738575e9.1 for ; Thu, 21 Dec 2023 10:43:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20230601.gappssmtp.com; s=20230601; t=1703184203; x=1703789003; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=caPc62PO2k3hY6zqjKKh6pA90RRGF5zHw9ThpEEdfos=; b=KRjJ0oklKDGuSrumgM7nhjuxzhW4Vx/FVFns0wZP3k0OPQkhI0qtZYp4ns1rmWqAfs GB6As3AmVKs/NqZtgD5VRXE5GqWCBi3h4TsTKvkx3TC1S724yRyMzf5QH7PLRntRTYH2 C78PrXQ06eF9K9ckqyMKRoUsLE1xdiA86i8/kR+uG+lrk3Ox2D5L9TpV/+ZDLdYbMCyC yXxOIxZdKru6qHM/gd+JItDZL0AmyGwvDqOStJd9/ELUTeraI2Du3IMj9Tm6bhyfF/A2 bVVoAauoFxrLlUO1D9tMbNXr+qW+X3Y//SDa8kNQ3VBqkdt5leRNvc0qnzDNlCL6pyNV BCtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703184203; x=1703789003; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=caPc62PO2k3hY6zqjKKh6pA90RRGF5zHw9ThpEEdfos=; b=WJVCxEOpfKXR5hpJl4QwlNm8bEJBejujXRkkRwCz9lxdN05WCQ0ku6/9b2d7a2KtGp Hg+OWnL/eUxviTMoDI/XNyA+im5rQdKYTLDqSm3QqtNncS5ynZOOOQann/pC2usoTHik EglUqziyEFmRzPKeh//2BGaF74X+GKt93iIrz/QIzV3Yxs/KN3qhlFv0mux8N1bJd4kX JhGZc0qO/0qBzCul1DzXlgKBxy1Wg+lOInsVCONLIsrsAkG0zRGvJnT9XzfPq7v42PmN xI5zSal6iG/62ZYDRZWvOF78aB+d3Wz13FVpIt2AQrk9oisNaSgMOR7CsULe2bwn0VJG io1g== X-Gm-Message-State: AOJu0YzS48496KI2gyceV+QmZhPn5Lh/H5Moos6cVxXsOI9rIIPYhrac K2+z9MO291UnBiS4WRHjb/A3uRrAFLMFqg== X-Google-Smtp-Source: AGHT+IFbU5OLYMJJhjrDxQMIpLizL9R5CCWumfMpRONFOBqZt3EbyalrOJqABQxYouHoTeWtcDCtqA== X-Received: by 2002:a05:600c:190e:b0:40b:5e26:2379 with SMTP id j14-20020a05600c190e00b0040b5e262379mr78889wmq.42.1703184202724; Thu, 21 Dec 2023 10:43:22 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:7701:a2c3:cba4:74db]) by smtp.gmail.com with ESMTPSA id t20-20020a05600c199400b0040c42681fcesm4188059wmq.15.2023.12.21.10.43.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Dec 2023 10:43:22 -0800 (PST) From: Bartosz Golaszewski To: Linus Walleij , Andy Shevchenko , Kent Gibson Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Bartosz Golaszewski Subject: [PATCH 2/2] gpiolib: pin GPIO devices in place during descriptor lookup Date: Thu, 21 Dec 2023 19:43:16 +0100 Message-Id: <20231221184316.24506-3-brgl@bgdev.pl> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231221184316.24506-1-brgl@bgdev.pl> References: <20231221184316.24506-1-brgl@bgdev.pl> Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Bartosz Golaszewski There's time between when we locate the relevant descriptor during lookup and when we actually take the reference to its parent GPIO device where - if the GPIO device in question is removed - we'll end up with a dangling pointer to freed memory. Make sure devices cannot be removed until we hold a new reference to the device. Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1baeb6778ec6..8a15b8f6b50e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4147,27 +4147,33 @@ static struct gpio_desc *gpiod_find_and_request(struct device *consumer, struct gpio_desc *desc; int ret; - desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx, &flags, &lookupflags); - if (gpiod_not_found(desc) && platform_lookup_allowed) { + scoped_guard(rwsem_read, &gpio_devices_sem) { + desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx, + &flags, &lookupflags); + if (gpiod_not_found(desc) && platform_lookup_allowed) { + /* + * Either we are not using DT or ACPI, or their lookup + * did not return a result. In that case, use platform + * lookup as a fallback. + */ + dev_dbg(consumer, + "using lookup tables for GPIO lookup\n"); + desc = gpiod_find(consumer, con_id, idx, &lookupflags); + } + + if (IS_ERR(desc)) { + dev_dbg(consumer, "No GPIO consumer %s found\n", + con_id); + return desc; + } + /* - * Either we are not using DT or ACPI, or their lookup did not - * return a result. In that case, use platform lookup as a - * fallback. + * If a connection label was passed use that, else attempt to + * use the device name as label */ - dev_dbg(consumer, "using lookup tables for GPIO lookup\n"); - desc = gpiod_find(consumer, con_id, idx, &lookupflags); + ret = gpiod_request(desc, label); } - if (IS_ERR(desc)) { - dev_dbg(consumer, "No GPIO consumer %s found\n", con_id); - return desc; - } - - /* - * If a connection label was passed use that, else attempt to use - * the device name as label - */ - ret = gpiod_request(desc, label); if (ret) { if (!(ret == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) return ERR_PTR(ret);