From patchwork Sat Dec 16 00:16:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 754999 Received: from mail-ot1-f41.google.com (mail-ot1-f41.google.com [209.85.210.41]) (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 B72187E; Sat, 16 Dec 2023 00:17:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cNJ6Xl5t" Received: by mail-ot1-f41.google.com with SMTP id 46e09a7af769-6d9d209c9bbso1067849a34.0; Fri, 15 Dec 2023 16:17:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702685831; x=1703290631; 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=PTxELzBwupC8Xz+32EFInaDy3vYRWVZIbpGqotXqvaA=; b=cNJ6Xl5tDMMMycN6t++A5HNZx2huslZClv3Hq3KTwfII62ADTGVkWmtmCuLqlT4eva QRpRPNetpOHcsoFsyunBF1Z1Tv8hP0jSD7O129VxnDvL9h/vskwf+PJBUglItxzi40ir rhwIQmX9jgb+DhcDxyoMec5wm7/tppaGGYHq9hBa/K2v3f2aR5RaJuh6TEA/0c8y5KpP fa7yma7jCPUrPmfrpQzUvDVt8fqtE9Tx4W4T/N5So/PXH50aRiLM4akcaL/wsh/EdQsQ 7FkvBUV2Tfn5hhrupuPrmxMTBzLKA/vXWIBkw4Eb+bkHuzo3odHLD47xJk4EYDyEpCO2 YAsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702685831; x=1703290631; 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=PTxELzBwupC8Xz+32EFInaDy3vYRWVZIbpGqotXqvaA=; b=wEEbmxin+5kVBZNo+H9bNsUCDy1I/w+8KSm89AqynkbcNtr6fP3yoWp6fjKurrSocJ 7MvsO+dvASFqo3Hg7MpzNZgDJqSXxoShsxCityWsE+1E8X3tiPBIfjCRySKBBa70V/1M aywj4BivR/jTYUIjkuMVpSJksqVZaEtwVdyqRLjMEnxiKPttI3QZt6p5MwDH7Qc7lomB aNFOle61DWGW9yUtcXgmkATCIv4GuRAaIo/NcZHcXeKeiAQxmbh5ttuPQDx/5VqV5SId hLfnuLJI5nAytXyuh8rEQNP81yx1bkHUR0IkQs03T+eQqkhmzOtUcM0yejYA9d5rRdu4 BouA== X-Gm-Message-State: AOJu0Ywv+547eXfqn26p1533omNQf/jyadTgDanlzzkpPE3EoyzTClwn FkxLtKkHqzX8Atwxgx75DUym77qM51I= X-Google-Smtp-Source: AGHT+IEi6zKKvaYacGgV8Cs2ETmu5ZZZ8ce361Xvca0GAlbFjA+EQ5qlniJm3FgqCGFB4FZapiP51g== X-Received: by 2002:a9d:76d7:0:b0:6d9:d36a:8cc0 with SMTP id p23-20020a9d76d7000000b006d9d36a8cc0mr11881486otl.28.1702685831493; Fri, 15 Dec 2023 16:17:11 -0800 (PST) Received: from rigel.home.arpa (60-241-235-125.tpgi.com.au. [60.241.235.125]) by smtp.gmail.com with ESMTPSA id ei39-20020a056a0080e700b006cbef269712sm14176124pfb.9.2023.12.15.16.17.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Dec 2023 16:17:11 -0800 (PST) From: Kent Gibson To: linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, brgl@bgdev.pl, linus.walleij@linaro.org, andy@kernel.org Cc: Kent Gibson Subject: [PATCH v4 1/5] gpiolib: cdev: relocate debounce_period_us from struct gpio_desc Date: Sat, 16 Dec 2023 08:16:48 +0800 Message-Id: <20231216001652.56276-2-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231216001652.56276-1-warthog618@gmail.com> References: <20231216001652.56276-1-warthog618@gmail.com> Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Store the debounce period for a requested line locally, rather than in the debounce_period_us field in the gpiolib struct gpio_desc. Add a global tree of lines containing supplemental line information to make the debounce period available to be reported by the GPIO_V2_GET_LINEINFO_IOCTL and the line change notifier. Signed-off-by: Kent Gibson Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib-cdev.c | 154 ++++++++++++++++++++++++++++++------ 1 file changed, 132 insertions(+), 22 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 02ffda6c1e51..47197f6339c4 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -461,6 +463,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) /** * struct line - contains the state of a requested line + * @node: to store the object in supinfo_tree if supplemental * @desc: the GPIO descriptor for this line. * @req: the corresponding line request * @irq: the interrupt triggered in response to events on this GPIO @@ -473,6 +476,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) * @line_seqno: the seqno for the current edge event in the sequence of * events for this line. * @work: the worker that implements software debouncing + * @debounce_period_us: the debounce period in microseconds * @sw_debounced: flag indicating if the software debouncer is active * @level: the current debounced physical level of the line * @hdesc: the Hardware Timestamp Engine (HTE) descriptor @@ -481,6 +485,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) * @last_seqno: the last sequence number before debounce period expires */ struct line { + struct rb_node node; struct gpio_desc *desc; /* * -- edge detector specific fields -- @@ -514,6 +519,15 @@ struct line { * -- debouncer specific fields -- */ struct delayed_work work; + /* + * debounce_period_us is accessed by debounce_irq_handler() and + * process_hw_ts() which are disabled when modified by + * debounce_setup(), edge_detector_setup() or edge_detector_stop() + * or can live with a stale version when updated by + * edge_detector_update(). + * The modifying functions are themselves mutually exclusive. + */ + unsigned int debounce_period_us; /* * sw_debounce is accessed by linereq_set_config(), which is the * only setter, and linereq_get_values(), which can live with a @@ -546,6 +560,17 @@ struct line { #endif /* CONFIG_HTE */ }; +/* + * a rbtree of the struct lines containing supplemental info. + * Used to populate gpio_v2_line_info with cdev specific fields not contained + * in the struct gpio_desc. + * A line is determined to contain supplemental information by + * line_is_supplemental(). + */ +static struct rb_root supinfo_tree = RB_ROOT; +/* covers supinfo_tree */ +static DEFINE_SPINLOCK(supinfo_lock); + /** * struct linereq - contains the state of a userspace line request * @gdev: the GPIO device the line request pertains to @@ -575,6 +600,95 @@ struct linereq { struct line lines[] __counted_by(num_lines); }; +static void supinfo_insert(struct line *line) +{ + struct rb_node **new = &(supinfo_tree.rb_node), *parent = NULL; + struct line *entry; + + guard(spinlock)(&supinfo_lock); + + while (*new) { + entry = container_of(*new, struct line, node); + + parent = *new; + if (line->desc < entry->desc) { + new = &((*new)->rb_left); + } else if (line->desc > entry->desc) { + new = &((*new)->rb_right); + } else { + /* this should never happen */ + WARN(1, "duplicate line inserted"); + return; + } + } + + rb_link_node(&line->node, parent, new); + rb_insert_color(&line->node, &supinfo_tree); +} + +static void supinfo_erase(struct line *line) +{ + guard(spinlock)(&supinfo_lock); + + rb_erase(&line->node, &supinfo_tree); +} + +static struct line *supinfo_find(struct gpio_desc *desc) +{ + struct rb_node *node = supinfo_tree.rb_node; + struct line *line; + + while (node) { + line = container_of(node, struct line, node); + if (desc < line->desc) + node = node->rb_left; + else if (desc > line->desc) + node = node->rb_right; + else + return line; + } + return NULL; +} + +static void supinfo_to_lineinfo(struct gpio_desc *desc, + struct gpio_v2_line_info *info) +{ + struct gpio_v2_line_attribute *attr; + struct line *line; + + guard(spinlock)(&supinfo_lock); + + line = supinfo_find(desc); + if (!line) + return; + + attr = &info->attrs[info->num_attrs]; + attr->id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE; + attr->debounce_period_us = READ_ONCE(line->debounce_period_us); + info->num_attrs++; +} + +static inline bool line_is_supplemental(struct line *line) +{ + return READ_ONCE(line->debounce_period_us); +} + +static void line_set_debounce_period(struct line *line, + unsigned int debounce_period_us) +{ + bool was_suppl = line_is_supplemental(line); + + WRITE_ONCE(line->debounce_period_us, debounce_period_us); + + if (line_is_supplemental(line) == was_suppl) + return; + + if (was_suppl) + supinfo_erase(line); + else + supinfo_insert(line); +} + #define GPIO_V2_LINE_BIAS_FLAGS \ (GPIO_V2_LINE_FLAG_BIAS_PULL_UP | \ GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN | \ @@ -723,7 +837,7 @@ static enum hte_return process_hw_ts(struct hte_ts_data *ts, void *p) line->total_discard_seq++; line->last_seqno = ts->seq; mod_delayed_work(system_wq, &line->work, - usecs_to_jiffies(READ_ONCE(line->desc->debounce_period_us))); + usecs_to_jiffies(READ_ONCE(line->debounce_period_us))); } else { if (unlikely(ts->seq < line->line_seqno)) return HTE_CB_HANDLED; @@ -864,7 +978,7 @@ static irqreturn_t debounce_irq_handler(int irq, void *p) struct line *line = p; mod_delayed_work(system_wq, &line->work, - usecs_to_jiffies(READ_ONCE(line->desc->debounce_period_us))); + usecs_to_jiffies(READ_ONCE(line->debounce_period_us))); return IRQ_HANDLED; } @@ -946,7 +1060,7 @@ static int debounce_setup(struct line *line, unsigned int debounce_period_us) /* try hardware */ ret = gpiod_set_debounce(line->desc, debounce_period_us); if (!ret) { - WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); + line_set_debounce_period(line, debounce_period_us); return ret; } if (ret != -ENOTSUPP) @@ -1025,8 +1139,7 @@ static void edge_detector_stop(struct line *line) cancel_delayed_work_sync(&line->work); WRITE_ONCE(line->sw_debounced, 0); WRITE_ONCE(line->edflags, 0); - if (line->desc) - WRITE_ONCE(line->desc->debounce_period_us, 0); + line_set_debounce_period(line, 0); /* do not change line->level - see comment in debounced_value() */ } @@ -1051,7 +1164,7 @@ static int edge_detector_setup(struct line *line, ret = debounce_setup(line, debounce_period_us); if (ret) return ret; - WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); + line_set_debounce_period(line, debounce_period_us); } /* detection disabled or sw debouncer will provide edge detection */ @@ -1093,12 +1206,12 @@ static int edge_detector_update(struct line *line, gpio_v2_line_config_debounce_period(lc, line_idx); if ((active_edflags == edflags) && - (READ_ONCE(line->desc->debounce_period_us) == debounce_period_us)) + (READ_ONCE(line->debounce_period_us) == debounce_period_us)) return 0; /* sw debounced and still will be...*/ if (debounce_period_us && READ_ONCE(line->sw_debounced)) { - WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); + line_set_debounce_period(line, debounce_period_us); return 0; } @@ -1573,6 +1686,7 @@ static ssize_t linereq_read(struct file *file, char __user *buf, static void linereq_free(struct linereq *lr) { + struct line *line; unsigned int i; if (lr->device_unregistered_nb.notifier_call) @@ -1580,10 +1694,14 @@ static void linereq_free(struct linereq *lr) &lr->device_unregistered_nb); for (i = 0; i < lr->num_lines; i++) { - if (lr->lines[i].desc) { - edge_detector_stop(&lr->lines[i]); - gpiod_free(lr->lines[i].desc); - } + line = &lr->lines[i]; + if (!line->desc) + continue; + + edge_detector_stop(line); + if (line_is_supplemental(line)) + supinfo_erase(line); + gpiod_free(line->desc); } kfifo_free(&lr->events); kfree(lr->label); @@ -2274,8 +2392,6 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, struct gpio_chip *gc = desc->gdev->chip; bool ok_for_pinctrl; unsigned long flags; - u32 debounce_period_us; - unsigned int num_attrs = 0; memset(info, 0, sizeof(*info)); info->offset = gpio_chip_hwgpio(desc); @@ -2341,14 +2457,6 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, else if (test_bit(FLAG_EVENT_CLOCK_HTE, &desc->flags)) info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE; - debounce_period_us = READ_ONCE(desc->debounce_period_us); - if (debounce_period_us) { - info->attrs[num_attrs].id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE; - info->attrs[num_attrs].debounce_period_us = debounce_period_us; - num_attrs++; - } - info->num_attrs = num_attrs; - spin_unlock_irqrestore(&gpio_lock, flags); } @@ -2455,6 +2563,7 @@ static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip, return -EBUSY; } gpio_desc_to_lineinfo(desc, &lineinfo); + supinfo_to_lineinfo(desc, &lineinfo); if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) { if (watch) @@ -2545,6 +2654,7 @@ static int lineinfo_changed_notify(struct notifier_block *nb, chg.event_type = action; chg.timestamp_ns = ktime_get_ns(); gpio_desc_to_lineinfo(desc, &chg.info); + supinfo_to_lineinfo(desc, &chg.info); ret = kfifo_in_spinlocked(&cdev->events, &chg, 1, &cdev->wait.lock); if (ret) From patchwork Sat Dec 16 00:16:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 755731 Received: from mail-pf1-f176.google.com (mail-pf1-f176.google.com [209.85.210.176]) (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 291711846; Sat, 16 Dec 2023 00:17:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="SMLShOQ0" Received: by mail-pf1-f176.google.com with SMTP id d2e1a72fcca58-6d26eef7438so1372363b3a.0; Fri, 15 Dec 2023 16:17:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702685843; x=1703290643; 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=82YLVhideuyQljRWJu1rWLIQMnIXOza47pBdqrDT1ns=; b=SMLShOQ0wCpRNJz76PuJMREn0HG8WGo/3AAA1NQYMSLbIZWPQtTFrwanv+jhMfda7r e0B1lndR40h1qHRSChyAX5RRwcDrC4ZbVDK8DZZ6N4OMzYVPIw1qfixUCAwLXv6Wostd 4t9ywI1df5nKFwGJjo8woqYcFldnuXSMRfJHmmA7BXjqYY32CezXw6lvgOMMNv0d31mo yUC5525SuX+TbJlH3N3eEl/9km576v2FL4l+egSKPhJuumrBmiIk1GhfAbUZGmdqcQbv CFzF913HXxRVmnpPBSqSHb5+2NU58tT4WV3fGYspwaA9Jg3Bfw4bUifmOSS6JkaPRR0I 7REw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702685843; x=1703290643; 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=82YLVhideuyQljRWJu1rWLIQMnIXOza47pBdqrDT1ns=; b=qX4VvxpX2BuMA3WdVjk/yqjmWBFiALhJvLi0mUxTeM5bWc50WsWvczwZUZEnV2zeVa mpmWFFOufSlGDGf/y1dILy1Ew0TlFFxJC6up7ji1kTmkybBwBsi8xwW5FCsiRkJyXTk4 RT3j0HGocHY31BmCN1kILP/i+NEyxV5PDgHi5dQfAKRpwvQz0h4/nWFam7hkRsuXd4ku C8zObi7YojZK9+YAdJbAkue12kSb0o/xXMQUSujKwetMNUbrjJTdG6UULplLj9jGJC0K Xx9CebgPibw4fbVyAG3YKZA+8zjYlSfUaQ6ry6fIqpEeK3TNt1LYrv85suSxvAsR5Mp6 FQ3A== X-Gm-Message-State: AOJu0YxQcHpZOwsV5/AoLIqeRVmkr68xZhtaZgcuCpCwkAr5tGeWTC1P QZI9u0UekLKMmYdmSJ2I5n406bEF/j8= X-Google-Smtp-Source: AGHT+IERK85bB3U/DXt/+OtJeOPr7ccOnDYSF8H2KZnTW0ignVhiDP/rD34UFnzmGhfLOfPrbGS+Gg== X-Received: by 2002:a05:6a21:998a:b0:190:cab:b3d4 with SMTP id ve10-20020a056a21998a00b001900cabb3d4mr14893959pzb.30.1702685843154; Fri, 15 Dec 2023 16:17:23 -0800 (PST) Received: from rigel.home.arpa (60-241-235-125.tpgi.com.au. [60.241.235.125]) by smtp.gmail.com with ESMTPSA id ei39-20020a056a0080e700b006cbef269712sm14176124pfb.9.2023.12.15.16.17.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Dec 2023 16:17:22 -0800 (PST) From: Kent Gibson To: linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, brgl@bgdev.pl, linus.walleij@linaro.org, andy@kernel.org Cc: Kent Gibson Subject: [PATCH v4 2/5] gpiolib: remove debounce_period_us from struct gpio_desc Date: Sat, 16 Dec 2023 08:16:49 +0800 Message-Id: <20231216001652.56276-3-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231216001652.56276-1-warthog618@gmail.com> References: <20231216001652.56276-1-warthog618@gmail.com> Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 cdev is the only user of the debounce_period_us field in struct gpio_desc, and it no longer uses it, so remove it. Signed-off-by: Kent Gibson Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib.c | 3 --- drivers/gpio/gpiolib.h | 5 ----- 2 files changed, 8 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4e190be75dc2..ca2216621619 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2344,9 +2344,6 @@ static bool gpiod_free_commit(struct gpio_desc *desc) clear_bit(FLAG_IS_HOGGED, &desc->flags); #ifdef CONFIG_OF_DYNAMIC desc->hog = NULL; -#endif -#ifdef CONFIG_GPIO_CDEV - WRITE_ONCE(desc->debounce_period_us, 0); #endif ret = true; } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 3ccacf3c1288..a4a2520b5f31 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -147,7 +147,6 @@ void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action); * @label: Name of the consumer * @name: Line name * @hog: Pointer to the device node that hogs this line (if any) - * @debounce_period_us: Debounce period in microseconds * * These are obtained using gpiod_get() and are preferable to the old * integer-based handles. @@ -185,10 +184,6 @@ struct gpio_desc { #ifdef CONFIG_OF_DYNAMIC struct device_node *hog; #endif -#ifdef CONFIG_GPIO_CDEV - /* debounce period in microseconds */ - unsigned int debounce_period_us; -#endif }; #define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) From patchwork Sat Dec 16 00:16:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 754998 Received: from mail-ot1-f52.google.com (mail-ot1-f52.google.com [209.85.210.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 16EFE7E; Sat, 16 Dec 2023 00:17:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HJookHIp" Received: by mail-ot1-f52.google.com with SMTP id 46e09a7af769-6d9e756cf32so1021686a34.2; Fri, 15 Dec 2023 16:17:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702685856; x=1703290656; 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=mKZEEfrVGHEaINRgT5nXSBcR8L7v728av3t9LqLhAJc=; b=HJookHIpxHJe8Hli+S3jDbiegenzYpZChTNYpn2aSP4A/XQ4GA3IDxt29FabCy8HdX HF5orFOo4Aq8Ob18BbgkA48woMWb9vriTr4DQibdqDctRx4xJXVIhLlDvBd0UJo3j0Zh RADbgP6JouQmKjZVaXUwBNurySYwj5Zs+Ik5jDYmeSp1V267BcBn+TBGcUAdxjL5BrCn wDUdzLoVBdRD12f8D2WrKlsOHF245sUbvp78QnKtWp8z22vUB1b0ydLztULcK2Uagtcs qcPy1W4Amc9epgUX1F07a0iIQWEEluTp7uj96DTkojTTWDvYmYufhjVNLVchV7PhIreh BLaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702685856; x=1703290656; 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=mKZEEfrVGHEaINRgT5nXSBcR8L7v728av3t9LqLhAJc=; b=cjFCNPhpRQd9xaV/yr0+DjBR6xZuKihHo+hYWkE5I28RVQd+9sNqFJups9LyAU+yMW q7LuBZOjo17nrDsIrAr6h7/l60usXXbVlU8vGWs8wjpx02vf8Uuy1XMrIUlDhgNwxBDa 5gz0vin9vfn1OrTNRE83Ld27QLYEJHuWsPfKdpSv/IUXSCylIcSuV4vbLOLyDaNJwW8p kHDWx3IrYYeUKkEvUHi98V7odVZUsVrsJUouxxArCbAATGlnb7KWiymswM6NrhyAhUzt dU1BZctsRehbPinwMJHk+fyOGCOOTbM7tU/UetefN9UtFifgUA/K800+vCZ/6l5D7SD6 h+Yg== X-Gm-Message-State: AOJu0Yyo7maq4oyuF/31WpFvFjwgJp+Thnj2UqMAapDsKdrRMY/5fU1+ 5LljpuLl0BpOjjEUhA3o7zeophGs3Lg= X-Google-Smtp-Source: AGHT+IE9S/f4JdRtSHw6xSuIiPfAao3z+M4Uof0IpR7Rhx/YfeC91InXjnWqkSkMVvCNGHcMgLeeIw== X-Received: by 2002:a05:6830:33d3:b0:6d9:e0c8:3e04 with SMTP id q19-20020a05683033d300b006d9e0c83e04mr11316425ott.11.1702685855984; Fri, 15 Dec 2023 16:17:35 -0800 (PST) Received: from rigel.home.arpa (60-241-235-125.tpgi.com.au. [60.241.235.125]) by smtp.gmail.com with ESMTPSA id ei39-20020a056a0080e700b006cbef269712sm14176124pfb.9.2023.12.15.16.17.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Dec 2023 16:17:35 -0800 (PST) From: Kent Gibson To: linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, brgl@bgdev.pl, linus.walleij@linaro.org, andy@kernel.org Cc: Kent Gibson Subject: [PATCH v4 3/5] gpiolib: cdev: reduce locking in gpio_desc_to_lineinfo() Date: Sat, 16 Dec 2023 08:16:50 +0800 Message-Id: <20231216001652.56276-4-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231216001652.56276-1-warthog618@gmail.com> References: <20231216001652.56276-1-warthog618@gmail.com> Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Reduce the time holding the gpio_lock by snapshotting the desc flags, rather than testing them individually while holding the lock. Accept that the calculation of the used field is inherently racy, and only check the availability of the line from pinctrl if other checks pass, so avoiding the check for lines that are otherwise in use. Signed-off-by: Kent Gibson Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib-cdev.c | 74 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 47197f6339c4..8c174dda622d 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2390,74 +2390,72 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, struct gpio_v2_line_info *info) { struct gpio_chip *gc = desc->gdev->chip; - bool ok_for_pinctrl; - unsigned long flags; + unsigned long dflags; memset(info, 0, sizeof(*info)); info->offset = gpio_chip_hwgpio(desc); - /* - * This function takes a mutex so we must check this before taking - * the spinlock. - * - * FIXME: find a non-racy way to retrieve this information. Maybe a - * lock common to both frameworks? - */ - ok_for_pinctrl = pinctrl_gpio_can_use_line(gc, info->offset); + scoped_guard(spinlock_irqsave, &gpio_lock) { + if (desc->name) + strscpy(info->name, desc->name, sizeof(info->name)); - spin_lock_irqsave(&gpio_lock, flags); + if (desc->label) + strscpy(info->consumer, desc->label, + sizeof(info->consumer)); - if (desc->name) - strscpy(info->name, desc->name, sizeof(info->name)); - - if (desc->label) - strscpy(info->consumer, desc->label, sizeof(info->consumer)); + dflags = READ_ONCE(desc->flags); + } /* - * Userspace only need to know that the kernel is using this GPIO so - * it can't use it. + * Userspace only need know that the kernel is using this GPIO so it + * can't use it. + * The calculation of the used flag is slightly racy, as it may read + * desc, gc and pinctrl state without a lock covering all three at + * once. Worst case if the line is in transition and the calculation + * is inconsistent then it looks to the user like they performed the + * read on the other side of the transition - but that can always + * happen. + * The definitive test that a line is available to userspace is to + * request it. */ - info->flags = 0; - if (test_bit(FLAG_REQUESTED, &desc->flags) || - test_bit(FLAG_IS_HOGGED, &desc->flags) || - test_bit(FLAG_USED_AS_IRQ, &desc->flags) || - test_bit(FLAG_EXPORT, &desc->flags) || - test_bit(FLAG_SYSFS, &desc->flags) || + if (test_bit(FLAG_REQUESTED, &dflags) || + test_bit(FLAG_IS_HOGGED, &dflags) || + test_bit(FLAG_USED_AS_IRQ, &dflags) || + test_bit(FLAG_EXPORT, &dflags) || + test_bit(FLAG_SYSFS, &dflags) || !gpiochip_line_is_valid(gc, info->offset) || - !ok_for_pinctrl) + !pinctrl_gpio_can_use_line(gc, info->offset)) info->flags |= GPIO_V2_LINE_FLAG_USED; - if (test_bit(FLAG_IS_OUT, &desc->flags)) + if (test_bit(FLAG_IS_OUT, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_OUTPUT; else info->flags |= GPIO_V2_LINE_FLAG_INPUT; - if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) + if (test_bit(FLAG_ACTIVE_LOW, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_ACTIVE_LOW; - if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) + if (test_bit(FLAG_OPEN_DRAIN, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_OPEN_DRAIN; - if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) + if (test_bit(FLAG_OPEN_SOURCE, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_OPEN_SOURCE; - if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) + if (test_bit(FLAG_BIAS_DISABLE, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_BIAS_DISABLED; - if (test_bit(FLAG_PULL_DOWN, &desc->flags)) + if (test_bit(FLAG_PULL_DOWN, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN; - if (test_bit(FLAG_PULL_UP, &desc->flags)) + if (test_bit(FLAG_PULL_UP, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP; - if (test_bit(FLAG_EDGE_RISING, &desc->flags)) + if (test_bit(FLAG_EDGE_RISING, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_EDGE_RISING; - if (test_bit(FLAG_EDGE_FALLING, &desc->flags)) + if (test_bit(FLAG_EDGE_FALLING, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; - if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &desc->flags)) + if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME; - else if (test_bit(FLAG_EVENT_CLOCK_HTE, &desc->flags)) + else if (test_bit(FLAG_EVENT_CLOCK_HTE, &dflags)) info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE; - - spin_unlock_irqrestore(&gpio_lock, flags); } struct gpio_chardev_data { From patchwork Sat Dec 16 00:16:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 755730 Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) (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 E29C129CA; Sat, 16 Dec 2023 00:17:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jrEA1z7V" Received: by mail-pf1-f178.google.com with SMTP id d2e1a72fcca58-6ce7c1b07e1so1054998b3a.2; Fri, 15 Dec 2023 16:17:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702685865; x=1703290665; 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=jCz017gwGhwzQemSmR9uwl3+atXn6JgAccEYbOS8Vz0=; b=jrEA1z7V8EUXik+ITlhFkCQWfNs0fAU8m0WPOCMhMznDqTKI3E72KJxL3amdMNbdbf 68pZRaJILpuNuP0rL/N3zH+bO3cnJt7tA0M6mGN9/rDNdLxcca4a90ReTunvWEleqD4C OvHYKGDlZTqQ3lo4rAbX0arqRlH76GzKuSc7keXBM2ANA5U+Kl2se35skDSr9oKbnuqd kMP5XRHFWPMdtimAAFO1af+iOyFC8D6jDYNAbtqVpV9tZujYG3oCcWwAwo96Zn1hjqEG o1CtzkXvKTuBeRTD+w5VA6bq96oanMunuRaxF7gElIKXIrNVXibnqQzV+8RwC32ST4RH 6hyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702685865; x=1703290665; 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=jCz017gwGhwzQemSmR9uwl3+atXn6JgAccEYbOS8Vz0=; b=jq1kUuSAzFaD5yDQMY1qcm0nZp4jb6C70A0e+T1BKyLL05PFX1ukbgdFzC+5tyKxci yItGLeWlAeg34FJZRo5MaVvP5MXdNnIfCoDwrEiOViOpF534dzrWd3K4AbIUrwQNV52z 3Z88tlxGEiQuZaHE4yHNMPGp/eUHFF98ol9NBjyzmW4uE6gsdnIZFRXK04LkY5ckqTzr PKrjc9wc/5Ekddcq5hi2ZcgJ+zLfNpWMfbsgO9/Y1VRDann507dpZ3yTBW1TR2k8DkvE rpNeCvRYTqrZNb8waayDatgM9NXrkRQSDvoMp0A65z8DM4D7zpbe3R3Nzy23J5Uv4yb0 x2AA== X-Gm-Message-State: AOJu0Ywwl1m8k+xsiQFPNPFLX0cexLbO0+wNfaZOhPfLd2W1V/Qwz2N0 BrlkHsBLUgkCl/2t66oeA19QrPYGITU= X-Google-Smtp-Source: AGHT+IE1SrmWuyPYeIU50E6reCQRGGtLNE/UHrB92CvISutTmsF8VirHEJTcOWc2VCYwjjxskSs66w== X-Received: by 2002:a05:6a20:b297:b0:18b:844d:778f with SMTP id ei23-20020a056a20b29700b0018b844d778fmr10927402pzb.12.1702685865093; Fri, 15 Dec 2023 16:17:45 -0800 (PST) Received: from rigel.home.arpa (60-241-235-125.tpgi.com.au. [60.241.235.125]) by smtp.gmail.com with ESMTPSA id ei39-20020a056a0080e700b006cbef269712sm14176124pfb.9.2023.12.15.16.17.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Dec 2023 16:17:44 -0800 (PST) From: Kent Gibson To: linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, brgl@bgdev.pl, linus.walleij@linaro.org, andy@kernel.org Cc: Kent Gibson Subject: [PATCH v4 4/5] gpiolib: cdev: fully adopt guard() and scoped_guard() Date: Sat, 16 Dec 2023 08:16:51 +0800 Message-Id: <20231216001652.56276-5-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231216001652.56276-1-warthog618@gmail.com> References: <20231216001652.56276-1-warthog618@gmail.com> Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Use guard() or scoped_guard() for critical sections rather than discrete lock/unlock pairs. Signed-off-by: Kent Gibson Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib-cdev.c | 139 ++++++++++++++---------------------- 1 file changed, 55 insertions(+), 84 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 8c174dda622d..68fa9714e643 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -739,13 +739,13 @@ static void linereq_put_event(struct linereq *lr, { bool overflow = false; - spin_lock(&lr->wait.lock); - if (kfifo_is_full(&lr->events)) { - overflow = true; - kfifo_skip(&lr->events); + scoped_guard(spinlock, &lr->wait.lock) { + if (kfifo_is_full(&lr->events)) { + overflow = true; + kfifo_skip(&lr->events); + } + kfifo_in(&lr->events, le, 1); } - kfifo_in(&lr->events, le, 1); - spin_unlock(&lr->wait.lock); if (!overflow) wake_up_poll(&lr->wait, EPOLLIN); else @@ -1478,18 +1478,13 @@ static long linereq_set_values_unlocked(struct linereq *lr, static long linereq_set_values(struct linereq *lr, void __user *ip) { struct gpio_v2_line_values lv; - int ret; if (copy_from_user(&lv, ip, sizeof(lv))) return -EFAULT; - mutex_lock(&lr->config_mutex); + guard(mutex)(&lr->config_mutex); - ret = linereq_set_values_unlocked(lr, &lv); - - mutex_unlock(&lr->config_mutex); - - return ret; + return linereq_set_values_unlocked(lr, &lv); } static long linereq_set_config_unlocked(struct linereq *lr, @@ -1547,13 +1542,9 @@ static long linereq_set_config(struct linereq *lr, void __user *ip) if (ret) return ret; - mutex_lock(&lr->config_mutex); + guard(mutex)(&lr->config_mutex); - ret = linereq_set_config_unlocked(lr, &lc); - - mutex_unlock(&lr->config_mutex); - - return ret; + return linereq_set_config_unlocked(lr, &lc); } static long linereq_ioctl_unlocked(struct file *file, unsigned int cmd, @@ -1635,28 +1626,22 @@ static ssize_t linereq_read_unlocked(struct file *file, char __user *buf, return -EINVAL; do { - spin_lock(&lr->wait.lock); - if (kfifo_is_empty(&lr->events)) { - if (bytes_read) { - spin_unlock(&lr->wait.lock); - return bytes_read; + scoped_guard(spinlock, &lr->wait.lock) { + if (kfifo_is_empty(&lr->events)) { + if (bytes_read) + return bytes_read; + + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + ret = wait_event_interruptible_locked(lr->wait, + !kfifo_is_empty(&lr->events)); + if (ret) + return ret; } - if (file->f_flags & O_NONBLOCK) { - spin_unlock(&lr->wait.lock); - return -EAGAIN; - } - - ret = wait_event_interruptible_locked(lr->wait, - !kfifo_is_empty(&lr->events)); - if (ret) { - spin_unlock(&lr->wait.lock); - return ret; - } + ret = kfifo_out(&lr->events, &le, 1); } - - ret = kfifo_out(&lr->events, &le, 1); - spin_unlock(&lr->wait.lock); if (ret != 1) { /* * This should never happen - we were holding the @@ -2006,28 +1991,22 @@ static ssize_t lineevent_read_unlocked(struct file *file, char __user *buf, return -EINVAL; do { - spin_lock(&le->wait.lock); - if (kfifo_is_empty(&le->events)) { - if (bytes_read) { - spin_unlock(&le->wait.lock); - return bytes_read; + scoped_guard(spinlock, &le->wait.lock) { + if (kfifo_is_empty(&le->events)) { + if (bytes_read) + return bytes_read; + + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + ret = wait_event_interruptible_locked(le->wait, + !kfifo_is_empty(&le->events)); + if (ret) + return ret; } - if (file->f_flags & O_NONBLOCK) { - spin_unlock(&le->wait.lock); - return -EAGAIN; - } - - ret = wait_event_interruptible_locked(le->wait, - !kfifo_is_empty(&le->events)); - if (ret) { - spin_unlock(&le->wait.lock); - return ret; - } + ret = kfifo_out(&le->events, &ge, 1); } - - ret = kfifo_out(&le->events, &ge, 1); - spin_unlock(&le->wait.lock); if (ret != 1) { /* * This should never happen - we were holding the lock @@ -2721,38 +2700,30 @@ static ssize_t lineinfo_watch_read_unlocked(struct file *file, char __user *buf, #endif do { - spin_lock(&cdev->wait.lock); - if (kfifo_is_empty(&cdev->events)) { - if (bytes_read) { - spin_unlock(&cdev->wait.lock); - return bytes_read; - } + scoped_guard(spinlock, &cdev->wait.lock) { + if (kfifo_is_empty(&cdev->events)) { + if (bytes_read) + return bytes_read; - if (file->f_flags & O_NONBLOCK) { - spin_unlock(&cdev->wait.lock); - return -EAGAIN; - } + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; - ret = wait_event_interruptible_locked(cdev->wait, - !kfifo_is_empty(&cdev->events)); - if (ret) { - spin_unlock(&cdev->wait.lock); - return ret; + ret = wait_event_interruptible_locked(cdev->wait, + !kfifo_is_empty(&cdev->events)); + if (ret) + return ret; } - } #ifdef CONFIG_GPIO_CDEV_V1 - /* must be after kfifo check so watch_abi_version is set */ - if (atomic_read(&cdev->watch_abi_version) == 2) - event_size = sizeof(struct gpio_v2_line_info_changed); - else - event_size = sizeof(struct gpioline_info_changed); - if (count < event_size) { - spin_unlock(&cdev->wait.lock); - return -EINVAL; - } + /* must be after kfifo check so watch_abi_version is set */ + if (atomic_read(&cdev->watch_abi_version) == 2) + event_size = sizeof(struct gpio_v2_line_info_changed); + else + event_size = sizeof(struct gpioline_info_changed); + if (count < event_size) + return -EINVAL; #endif - ret = kfifo_out(&cdev->events, &event, 1); - spin_unlock(&cdev->wait.lock); + ret = kfifo_out(&cdev->events, &event, 1); + } if (ret != 1) { ret = -EIO; break; From patchwork Sat Dec 16 00:16:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 754997 Received: from mail-pf1-f169.google.com (mail-pf1-f169.google.com [209.85.210.169]) (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 720134A13; Sat, 16 Dec 2023 00:17:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Sdgzobg+" Received: by mail-pf1-f169.google.com with SMTP id d2e1a72fcca58-6d2350636d6so1169466b3a.2; Fri, 15 Dec 2023 16:17:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702685877; x=1703290677; 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=arlg1YXcHM8i0YCMKhN2VPucJk96xE9TSorG5ozqY0w=; b=Sdgzobg+2DjohfekdmISv6HffMYqMl+d/ZVN7JOvrf4pCy8vqQQPNeaBN4xyftTW0Q e9SZc9WMAxfMC8AMDtyYTUbKLkq4NzU1Y1SeDyazdYL4ZvQlSpdZfDV9x53mlVveMVd/ JK3PYP9JxQlBZ55yhcqbbO493/uBDGN3UhjMPJjXIPTfjgnYRYCfgB8odxjQ6I9WJEqd gl1imEOMP7nP7BXiZfjL1XIfkULodH1IU3tjO09yfudF3Cl3aHw22EmUwwFrnXlSB+Qg qNpQ9BplkgnbSoo/YP62ZaL753sq3rlo2zgvTudymDnZTK5HrvULxLlzTpSjhodecju6 qyQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702685877; x=1703290677; 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=arlg1YXcHM8i0YCMKhN2VPucJk96xE9TSorG5ozqY0w=; b=WxdWpf5f9XZ2s0R6UfRHCelgzFIg/spQ8KgyIXN/6AU6i4PwCnxeM+E4ATlHyjmYNm Q3f2YPu3m34NrDFpX/P0rS9/6jngd2oCxBCuXB8vAq0P+DO9/f/lhrNGqH3ZeB69EFF9 9sAeMG1by/5kZUzM8W3PTje4fj3rJDczwB9XwKU1JQxxiG/XGjsy4NilQKwsb50o7pYB 4O/O7FARJYtFDb75E0WYAgvfNZtprZqi7TViinp+3O5hCwCjlssnbvNg4Mo5eMx7JGih VlAth9pyCn1CsjKP2V4DBcbVcdc5oe6T3aMfIPaX82+qTvgYfiMTUTSDxXiBhyy7GXHK 3+gA== X-Gm-Message-State: AOJu0Yxzo4k3H+ntIO23kTtgFlYgrKSTMCyu/c75jBJxOQhOPTxjZ+I3 Wl31VZdTIjNZjBKoibIkgoqibc+me2I= X-Google-Smtp-Source: AGHT+IHKy674ZILkp6H5Vj33/9bMKBqwD5yv4RkEDkfO6DW2WyydELW0Uzvl25IM0CjVNQ2ULeIVSQ== X-Received: by 2002:a05:6a00:1148:b0:6cd:fcef:5d94 with SMTP id b8-20020a056a00114800b006cdfcef5d94mr13769217pfm.16.1702685877459; Fri, 15 Dec 2023 16:17:57 -0800 (PST) Received: from rigel.home.arpa (60-241-235-125.tpgi.com.au. [60.241.235.125]) by smtp.gmail.com with ESMTPSA id ei39-20020a056a0080e700b006cbef269712sm14176124pfb.9.2023.12.15.16.17.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Dec 2023 16:17:57 -0800 (PST) From: Kent Gibson To: linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, brgl@bgdev.pl, linus.walleij@linaro.org, andy@kernel.org Cc: Kent Gibson Subject: [PATCH v4 5/5] gpiolib: cdev: improve documentation of get/set values Date: Sat, 16 Dec 2023 08:16:52 +0800 Message-Id: <20231216001652.56276-6-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231216001652.56276-1-warthog618@gmail.com> References: <20231216001652.56276-1-warthog618@gmail.com> Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add documentation of the algorithm used to perform scatter/gather of the requested lines and values in linereq_get_values() and linereq_set_values_unlocked() to improve maintainability. Signed-off-by: Kent Gibson Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib-cdev.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 68fa9714e643..d4953787f361 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -1385,9 +1385,18 @@ static long linereq_get_values(struct linereq *lr, void __user *ip) if (copy_from_user(&lv, ip, sizeof(lv))) return -EFAULT; + /* + * gpiod_get_array_value_complex() requires compacted desc and val + * arrays, rather than the sparse ones in lv. + * Calculation of num_get and construction of the desc array is + * optimized to avoid allocation for the desc array for the common + * num_get == 1 case. + */ + /* scan requested lines to calculate the subset to get */ for (num_get = 0, i = 0; i < lr->num_lines; i++) { if (lv.mask & BIT_ULL(i)) { num_get++; + /* capture desc for the num_get == 1 case */ descs = &lr->lines[i].desc; } } @@ -1396,6 +1405,7 @@ static long linereq_get_values(struct linereq *lr, void __user *ip) return -EINVAL; if (num_get != 1) { + /* build compacted desc array */ descs = kmalloc_array(num_get, sizeof(*descs), GFP_KERNEL); if (!descs) return -ENOMEM; @@ -1416,6 +1426,7 @@ static long linereq_get_values(struct linereq *lr, void __user *ip) lv.bits = 0; for (didx = 0, i = 0; i < lr->num_lines; i++) { + /* unpack compacted vals for the response */ if (lv.mask & BIT_ULL(i)) { if (lr->lines[i].sw_debounced) val = debounced_value(&lr->lines[i]); @@ -1441,14 +1452,25 @@ static long linereq_set_values_unlocked(struct linereq *lr, unsigned int i, didx, num_set; int ret; + /* + * gpiod_set_array_value_complex() requires compacted desc and val + * arrays, rather than the sparse ones in lv. + * Calculation of num_set and construction of the descs and vals arrays + * is optimized to minimize scanning the lv->mask, and to avoid + * allocation for the desc array for the common num_set == 1 case. + */ bitmap_zero(vals, GPIO_V2_LINES_MAX); + /* scan requested lines to determine the subset to be set */ for (num_set = 0, i = 0; i < lr->num_lines; i++) { if (lv->mask & BIT_ULL(i)) { + /* setting inputs is not allowed */ if (!test_bit(FLAG_IS_OUT, &lr->lines[i].desc->flags)) return -EPERM; + /* add to compacted values */ if (lv->bits & BIT_ULL(i)) __set_bit(num_set, vals); num_set++; + /* capture desc for the num_set == 1 case */ descs = &lr->lines[i].desc; } } @@ -1456,7 +1478,7 @@ static long linereq_set_values_unlocked(struct linereq *lr, return -EINVAL; if (num_set != 1) { - /* build compacted desc array and values */ + /* build compacted desc array */ descs = kmalloc_array(num_set, sizeof(*descs), GFP_KERNEL); if (!descs) return -ENOMEM;