From patchwork Thu Dec 14 09:58:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 754680 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZslGmxTD" Received: from mail-oi1-x236.google.com (mail-oi1-x236.google.com [IPv6:2607:f8b0:4864:20::236]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1F45E93; Thu, 14 Dec 2023 01:58:35 -0800 (PST) Received: by mail-oi1-x236.google.com with SMTP id 5614622812f47-3ba04b9b103so3676221b6e.0; Thu, 14 Dec 2023 01:58:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702547914; x=1703152714; 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=9gJi4LxvmNnRwy+ZXLJeCQFxn2HJX+TXcVbWnXB+RB0=; b=ZslGmxTDknzAIBVEHhviJPGEAKItCXpBjtQvU8th/J/RBFfVJ3zUQLH5OZv5Jnn2dH 5jWqyiBvPU8NeVvd6TV3GM/p8U21q32Pt3F5OMJGXyHPcA75U24AIMhv/ixRyAWp4Hat HukkllAmefGb/Hu0AVeZYTCfR0YmLT2ioHm2n0w3bFZaU49qLCAGyOgQ3c5cUvk9UT2S PgM15zrrQ3lIofrP8J1t3/5PSrdilVTfN1gkljzG3sCWt3fGrvLPZRcOwAU/agYwoWyO j/a5bLhMT0O7Rn8SIkSDJgTbL9Kmrg4/4WB7x6Njn/3CRkLgpf4CR/XYtLHR6ouzxlZ5 2XmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702547914; x=1703152714; 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=9gJi4LxvmNnRwy+ZXLJeCQFxn2HJX+TXcVbWnXB+RB0=; b=r2PtzdXSjt+qqmhunGaDv/smSeDbu6InASoqJrjR7EZRFM/8bMqZ/TmnQq7ciPZ/Gt lOIr7cYL+hrUac/0FczYPdbyqSDofmM8Bsdhj27VPaRfeIBLOQHInyw5atGkal9nzgHs rfKBMeVhCMppTOJxdwHPgO1aFDAPo+5zlPCTe3GR61iVRNIvB27Ex5Yrog6HOJKbm/q1 vcmjYG8SDEPSez82hw6AZ4uWoqxGRdLncTHaWQGJ12ENeQcSWhB2powOkxLLUPWGJ3sz hqnqSljCVxwtOewssK+pEnu+2yUbVeGv6HAnVsj2bwMwM6IGu7gGWHcpaKiloGrpN5lO 2ooA== X-Gm-Message-State: AOJu0YzzrfTM9T90yUNGbVdHa2Vf8qq5bWxHLc3oVuiH0hcn2o84jsBV Yn50LEjSgypyrtsBRf7vwO+DFG7n5JU= X-Google-Smtp-Source: AGHT+IF9JCW4aaRTiN+oCbIXxGVa2QxUq/ANw53mDpDLla2LTeF/YwQ3KRQibJtJ3QvHIayOfU1SPQ== X-Received: by 2002:a05:6808:1443:b0:3a7:2390:3583 with SMTP id x3-20020a056808144300b003a723903583mr12511147oiv.38.1702547914214; Thu, 14 Dec 2023 01:58:34 -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 r2-20020a1709028bc200b001bc6e6069a6sm922807plo.122.2023.12.14.01.58.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Dec 2023 01:58:33 -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 v2 1/5] gpiolib: cdev: adopt scoped_guard() Date: Thu, 14 Dec 2023 17:58:10 +0800 Message-Id: <20231214095814.132400-2-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231214095814.132400-1-warthog618@gmail.com> References: <20231214095814.132400-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 scoped_guard for critical sections rather than distinct lock/unlock pairs. Signed-off-by: Kent Gibson --- drivers/gpio/gpiolib-cdev.c | 140 +++++++++++++++--------------------- 1 file changed, 57 insertions(+), 83 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 02ffda6c1e51..d03698812f61 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -625,13 +625,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 @@ -1370,11 +1370,8 @@ static long linereq_set_values(struct linereq *lr, void __user *ip) if (copy_from_user(&lv, ip, sizeof(lv))) return -EFAULT; - mutex_lock(&lr->config_mutex); - - ret = linereq_set_values_unlocked(lr, &lv); - - mutex_unlock(&lr->config_mutex); + scoped_guard(mutex, &lr->config_mutex) + ret = linereq_set_values_unlocked(lr, &lv); return ret; } @@ -1434,11 +1431,8 @@ static long linereq_set_config(struct linereq *lr, void __user *ip) if (ret) return ret; - mutex_lock(&lr->config_mutex); - - ret = linereq_set_config_unlocked(lr, &lc); - - mutex_unlock(&lr->config_mutex); + scoped_guard(mutex, &lr->config_mutex) + ret = linereq_set_config_unlocked(lr, &lc); return ret; } @@ -1522,28 +1516,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; - } - - if (file->f_flags & O_NONBLOCK) { - spin_unlock(&lr->wait.lock); - return -EAGAIN; + 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; } - 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 @@ -1888,28 +1876,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 @@ -2613,38 +2595,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; - } - - if (file->f_flags & O_NONBLOCK) { - spin_unlock(&cdev->wait.lock); - return -EAGAIN; - } - - ret = wait_event_interruptible_locked(cdev->wait, - !kfifo_is_empty(&cdev->events)); - if (ret) { - spin_unlock(&cdev->wait.lock); - return ret; + scoped_guard(spinlock, &cdev->wait.lock) { + if (kfifo_is_empty(&cdev->events)) { + if (bytes_read) + return bytes_read; + + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + 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 Thu Dec 14 09:58:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 754073 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aJcI1KGG" Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 969AC11A; Thu, 14 Dec 2023 01:58:45 -0800 (PST) Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-1d331f12f45so19658245ad.2; Thu, 14 Dec 2023 01:58:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702547925; x=1703152725; 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=Md3WJ0oNs1hZ2BPjMh8r7Ze0V2gO4q2OZDPAOTLVPAw=; b=aJcI1KGGsdo63y+3eY8cZXxcVB9lUSeSmY0SYhGYYwZPsYkNwfXurTfgICNJX/sEXF 1SnGknoI5DSGQfcwG2zi2zK2eAepdGelTeLEvf1P9E4h23FmbP41XnY5uv/B0Q+nGMmf fJGe619+FX8ox/0tXI4LaoksGCVWRNsgsBqiewZhD0z1g4oOQKLC4rp0c7EZ5sQRTPQX 4naPFutX/gELQJFhHuraQkLGLOHEWhtL5udEk0CKJDyEqSDPHd6DHuOJpUb7GPEDVBgu yvtuAXcIasoUgxrcH/S2QX4P7zl9bEtSfKPUaQRoUGV/dCkAAPSzfeR4aotvi0U0dEvd JAig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702547925; x=1703152725; 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=Md3WJ0oNs1hZ2BPjMh8r7Ze0V2gO4q2OZDPAOTLVPAw=; b=QhYe9KB7GDEpxyO4ZL6iNWc4a9OoPz+E9/Ut7haDOSPpIPvUBZFykk1AnsCiaXpMvw 4DKh/WjABPTpgwyNKnqAE91OTtz7zyLx1FPHlabuLoE93SdAw5F9IEf7jWTwgnlKXvGA aRRNFsZ5FXu4ZYjMAB522Gl+rrF0CwZ3j3uEfm/7V76c+0KlMJMCrdTL39lP2CW8xCoX kRRMuq8xXRB+DGKp/njpx4jh6DHEGkQyVkBNqXi8HZvDnytzmS0keesVmzZEXc3tD6nn FSkpSnC9zTEEKkR9zWvqJ4lcw5pMvt5tXURpksgD6AsmhCJ1SyKYIF13RteJD8ui7F8H d7Qw== X-Gm-Message-State: AOJu0Yz3+1gQUubs4U1Ruv0+MAqTDx4ia/ebCudL0lvbO/QQdOIshz1D b8MRS3BiZ5f8055jSl2TYIhivR39ZOE= X-Google-Smtp-Source: AGHT+IHH2bs2g9tNEdezAHQ+gjqjs9Z9tbX7E+ZhKpw1/cFLa2qzfFM9kJ9txXOh/q4uuzjArxYHog== X-Received: by 2002:a17:902:db05:b0:1d0:9a64:e51f with SMTP id m5-20020a170902db0500b001d09a64e51fmr6062796plx.0.1702547924809; Thu, 14 Dec 2023 01:58:44 -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 r2-20020a1709028bc200b001bc6e6069a6sm922807plo.122.2023.12.14.01.58.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Dec 2023 01:58: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 v2 2/5] gpiolib: cdev: relocate debounce_period_us from struct gpio_desc Date: Thu, 14 Dec 2023 17:58:11 +0800 Message-Id: <20231214095814.132400-3-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231214095814.132400-1-warthog618@gmail.com> References: <20231214095814.132400-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 --- drivers/gpio/gpiolib-cdev.c | 167 +++++++++++++++++++++++++++++++----- 1 file changed, 145 insertions(+), 22 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index d03698812f61..7da3b3706547 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -461,6 +462,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 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 +475,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 +484,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 +518,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 +559,19 @@ struct line { #endif /* CONFIG_HTE */ }; +/* + * 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 { + /* a rbtree of the struct lines containing the supplemental info */ + struct rb_root tree; + /* covers tree */ + spinlock_t lock; +} supinfo; + /** * struct linereq - contains the state of a userspace line request * @gdev: the GPIO device the line request pertains to @@ -575,6 +601,100 @@ struct linereq { struct line lines[] __counted_by(num_lines); }; +static void supinfo_init(void) +{ + supinfo.tree = RB_ROOT; + spin_lock_init(&supinfo.lock); +} + +static void supinfo_insert(struct line *line) +{ + struct rb_node **new = &(supinfo.tree.rb_node), *parent = NULL; + struct line *entry; + + scoped_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) +{ + scoped_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; + + scoped_guard(spinlock, &supinfo.lock) { + line = supinfo_find(desc); + if (line) { + 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 +843,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 +984,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 +1066,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 +1145,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 +1170,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 +1212,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; } @@ -1561,6 +1680,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) @@ -1568,10 +1688,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); @@ -2256,8 +2380,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); @@ -2323,14 +2445,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); } @@ -2437,6 +2551,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) @@ -2527,6 +2642,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) @@ -2786,3 +2902,10 @@ void gpiolib_cdev_unregister(struct gpio_device *gdev) cdev_device_del(&gdev->chrdev, &gdev->dev); blocking_notifier_call_chain(&gdev->device_notifier, 0, NULL); } + +static int __init gpiolib_cdev_init(void) +{ + supinfo_init(); + return 0; +} +postcore_initcall(gpiolib_cdev_init); From patchwork Thu Dec 14 09:58:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 754679 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IvwKkqDF" Received: from mail-yw1-x112b.google.com (mail-yw1-x112b.google.com [IPv6:2607:f8b0:4864:20::112b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E92DC112; Thu, 14 Dec 2023 01:58:55 -0800 (PST) Received: by mail-yw1-x112b.google.com with SMTP id 00721157ae682-5e2cfece112so15108177b3.2; Thu, 14 Dec 2023 01:58:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702547935; x=1703152735; 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=QOksdqNs08pbi9TocVeWukoOqtj/lhUt0q7v2+r1tcg=; b=IvwKkqDFvQ79fSJcSUACq+Zzt8AZ7u804/Fl/HbTtt/3P/tJ01Sm6VazoSnAwfGvJv 5iwZjTQOi8lVjlmwfPTFDHSjG6T/d6/pbhYeMKwVWF8nciE0d26ge+INz5Nl/RZ0gHQI 0UKNwdSXw8JPUOB7otdkVXB2k0/TpUEYl2JJktWE+aM2RGVMw07G+fnHIBa0uEW/nOmN 6OHRDMbyk/qBOsan6fMm5mtzuWsH9WA13MJLgQkjyPcKLjrhshSXc8S7/A9Zr6ZMaqxy 7FPjos/WP6/aHNNSPhvDCiED6QLEhyzRh6Txdw7C3zdA22THfx/6YSe3m0xXeG3N8syW 40hw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702547935; x=1703152735; 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=QOksdqNs08pbi9TocVeWukoOqtj/lhUt0q7v2+r1tcg=; b=fpD0v/GHmhoVanaMRvNFksR1RA38k0/+mYvul7hXro2J/6UjbudcWrTuTA+p16Sekr RH++wypEkZpvrfzF5GG+Yo+Rs+IOlbLIuUUXX8NGT2nB1IHbfPwPeGqoVNWspNwGyX54 k68jiLJMFKhOv7C/gqTAb2ovZqKEEvsFpt16nwdF9ZhL0lsRe9+ByZkloRcQix4V7aWB LJyn2eBtKgljAxvdeMsiNW37Vhs67OMrhVdqobp1UTKise3aOa/C9ofymgc7MmlkTDEo dZ4q79iCoXh+3PAAp2TZgGfS0x8QtcawBeKCAEaOUyXyBNhjeNVWr+RtAvavGYSoqzIV z7Zg== X-Gm-Message-State: AOJu0Yw+rZSuCuRnUt0hDV6otVn9q2tCYyea66wfCZBnugPg+A3UqcUw sXtSk8janvYlO16rzSnHs9Zxtd43U78= X-Google-Smtp-Source: AGHT+IE4O7DjJhqUVlsakmDVEsoUcqbLt+ADyUOQJRGKR3JVlLeYk1aXb9JApzurKr8NS/499GQegw== X-Received: by 2002:a81:6042:0:b0:5d8:e5e8:b775 with SMTP id u63-20020a816042000000b005d8e5e8b775mr7562773ywb.15.1702547934961; Thu, 14 Dec 2023 01:58:54 -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 r2-20020a1709028bc200b001bc6e6069a6sm922807plo.122.2023.12.14.01.58.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Dec 2023 01:58:54 -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 v2 3/5] gpiolib: remove debounce_period_us from struct gpio_desc Date: Thu, 14 Dec 2023 17:58:12 +0800 Message-Id: <20231214095814.132400-4-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231214095814.132400-1-warthog618@gmail.com> References: <20231214095814.132400-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 --- 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 95d2a7b2ea3e..b1e81a561141 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2330,9 +2330,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 Thu Dec 14 09:58:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 754072 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DNYFr3aC" Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E96A1114; Thu, 14 Dec 2023 01:59:08 -0800 (PST) Received: by mail-pl1-x62f.google.com with SMTP id d9443c01a7336-1d098b87eeeso71339295ad.0; Thu, 14 Dec 2023 01:59:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702547948; x=1703152748; 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=FGiGfD+/fY4XI4R5gDWMpTDZ9kiH8OA3IkETS/R7xgk=; b=DNYFr3aCXnBXiMVzM9rtfCLVT2RefWVMBCTX1HS3MIA2Wwx/znCO6gpN8tkxzhGfGG LOuvQYpp87l17pZeUcODQV14UGOIYDf4ECZgmVrEsmek9NVgrUHzNx4BqavnllDVXfbU w/dKikvrhOBc0rSH5G1mSigUE+pDSiWd5DLTXYXrWjetAtmdve2N46YBJ6b7hA2EC87r yw45Wyw7FsUBz9XZbmkKTseDPNMrMiQsdStV2Q6cZxsTpLVelv7C6LddWFu8X9OcBo8Y RqQwMw2O1RRcxRcMa1BkJd+zafuiT6xPf67C8qhzp88G1PNtLajHJaI2lU/vyw6FGB9Y Q5dA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702547948; x=1703152748; 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=FGiGfD+/fY4XI4R5gDWMpTDZ9kiH8OA3IkETS/R7xgk=; b=KDVACPEb0fvp4vn/tSQAyEHYXxmlw7Ao4IPv+hpcyrPyDR5EB+ZUeb+iHDFIQ0vsZ5 eD1cves3Dw5ixQVc+nmlAbU92tq70DmINt1Okt/sLt3dVtA6lvAFBpiYCwgeCw0R21ak Gw7c9T7l4n456dPqC53+tMkz6EOMEK2+fDGAuOQM/6YZREoQG9RKPHsUaEoryx/Tk3aF L1Pyon7LQCt1yFKdwfK50cdYE/LApuYPj2KNrIkbqf+Te0KHnpbHtLNFY36GLDsffwWG z0mD3v4h1Qmz57Fbfdpd5ckewEXXyfp3VwW773JVYYqbgIqT8tQr2vU56Bo+T0uB02Qa 8xzw== X-Gm-Message-State: AOJu0YzzNmntwG7YHFs0mCmKOs1G/Xj57M1zYF9bVfBUxr6ZKAZZ7xxi Qosr3yiJzM35h20GWUEFrslU0qvpvN8= X-Google-Smtp-Source: AGHT+IFJDoIRWpvhSguHfFYouUpZhCq5uPxqEAbwup02dcQY7LdehLjSbpxZmqegcVHRx403WDjdpg== X-Received: by 2002:a17:902:d58a:b0:1d3:766f:364e with SMTP id k10-20020a170902d58a00b001d3766f364emr41384plh.134.1702547948131; Thu, 14 Dec 2023 01:59:08 -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 r2-20020a1709028bc200b001bc6e6069a6sm922807plo.122.2023.12.14.01.59.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Dec 2023 01:59:07 -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 v2 4/5] gpiolib: cdev: reduce locking in gpio_desc_to_lineinfo() Date: Thu, 14 Dec 2023 17:58:13 +0800 Message-Id: <20231214095814.132400-5-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231214095814.132400-1-warthog618@gmail.com> References: <20231214095814.132400-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 --- drivers/gpio/gpiolib-cdev.c | 72 ++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 7da3b3706547..73262305de0f 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2378,74 +2378,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; 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)); + flags = 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, &flags) || + test_bit(FLAG_IS_HOGGED, &flags) || + test_bit(FLAG_USED_AS_IRQ, &flags) || + test_bit(FLAG_EXPORT, &flags) || + test_bit(FLAG_SYSFS, &flags) || !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, &flags)) 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, &flags)) info->flags |= GPIO_V2_LINE_FLAG_ACTIVE_LOW; - if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) + if (test_bit(FLAG_OPEN_DRAIN, &flags)) info->flags |= GPIO_V2_LINE_FLAG_OPEN_DRAIN; - if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) + if (test_bit(FLAG_OPEN_SOURCE, &flags)) info->flags |= GPIO_V2_LINE_FLAG_OPEN_SOURCE; - if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) + if (test_bit(FLAG_BIAS_DISABLE, &flags)) info->flags |= GPIO_V2_LINE_FLAG_BIAS_DISABLED; - if (test_bit(FLAG_PULL_DOWN, &desc->flags)) + if (test_bit(FLAG_PULL_DOWN, &flags)) info->flags |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN; - if (test_bit(FLAG_PULL_UP, &desc->flags)) + if (test_bit(FLAG_PULL_UP, &flags)) info->flags |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP; - if (test_bit(FLAG_EDGE_RISING, &desc->flags)) + if (test_bit(FLAG_EDGE_RISING, &flags)) info->flags |= GPIO_V2_LINE_FLAG_EDGE_RISING; - if (test_bit(FLAG_EDGE_FALLING, &desc->flags)) + if (test_bit(FLAG_EDGE_FALLING, &flags)) info->flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; - if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &desc->flags)) + if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &flags)) 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, &flags)) info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE; - - spin_unlock_irqrestore(&gpio_lock, flags); } struct gpio_chardev_data { From patchwork Thu Dec 14 09:58:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Gibson X-Patchwork-Id: 754678 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HYrx/Bmp" Received: from mail-pg1-x533.google.com (mail-pg1-x533.google.com [IPv6:2607:f8b0:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A82A0106; Thu, 14 Dec 2023 01:59:17 -0800 (PST) Received: by mail-pg1-x533.google.com with SMTP id 41be03b00d2f7-5c68da9d639so4551720a12.3; Thu, 14 Dec 2023 01:59:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702547957; x=1703152757; 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=lsNugrMTLdavqUaTzPaiiSqSEI8478i76rEA8WzTmjs=; b=HYrx/Bmpb0/ztK7gQIfH+pYDdKhH9068NrDelmWb32ex09PSBiCSxIns9wUk7fDv/1 RspvSfurCi4wdMylvOMbys0w3uIKh9yhk8B3UFeB+UlAd7IrDnVokzcjWTMKPTmdWKBz D/H7gwu6iC/CYr7sz33A6JSLOHeg3lG7jM5/VgIc3xsc5suXY/xXY0IGle+pOQbjTuB3 D5tBjphS9sK2oXV444Xpg7Petn+Gjldm9f6LTI3jaTtBE1+lsuEJC4cV7D4SUDs5QeMW 52PULRB40T9eKsfisxhToW7phjzkswYhfoofI0kWjOg4zi9SEK5WZdV67mxgHRp7hYE8 Y/bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702547957; x=1703152757; 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=lsNugrMTLdavqUaTzPaiiSqSEI8478i76rEA8WzTmjs=; b=IE1JGUxFWR3yqK6p74fNvJRi/BDmnliCW0+7CHDXBwx8yoj1hoWZBL66LDSDHdwdYy FO8HSsJOSkwJLUi3iQCbpFwwaVKeegTr2+Arbakx4xiuFw93LMZZXlqz9oeVFqvbFZlX 8QXBE02f+OMA7ZLwMQlz0fM259mvYySydGvmYYvwYVA+mTYkFo/CogAnHBWd03aqAfYf bFUSAa6hR2HSRSdM+6mVPsf2UK64n69n5B9xUhmjXnLmb7dKoEGKcsPnCM2XRXkVjUvt S+1yEMHPpViN2TQ6JXFZWau51peAN7a5R5NwNOtz5zETkKmMt7d/alVK6nJ34M/bcVjU rdFg== X-Gm-Message-State: AOJu0Ywt1NqzglXG1C3z8gKq3ydS/62GSIzoOWbevv4vcIB6eySUvyTE np6KUevDwX1pqxn1a6lBmxbR+ed6+b4= X-Google-Smtp-Source: AGHT+IGM+QUj5jfgwYUikQjoJ+FGUpcrZqFUvb0379eV8vCZ5ZbYeawfXIyV7Ry/FZdckig20vHtcQ== X-Received: by 2002:a17:902:c40a:b0:1cf:c37f:7158 with SMTP id k10-20020a170902c40a00b001cfc37f7158mr5879146plk.23.1702547956967; Thu, 14 Dec 2023 01:59:16 -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 r2-20020a1709028bc200b001bc6e6069a6sm922807plo.122.2023.12.14.01.59.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Dec 2023 01:59:16 -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 v2 5/5] gpiolib: cdev: improve documentation of get/set values Date: Thu, 14 Dec 2023 17:58:14 +0800 Message-Id: <20231214095814.132400-6-warthog618@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231214095814.132400-1-warthog618@gmail.com> References: <20231214095814.132400-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 --- 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 73262305de0f..27cfed748b0a 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -1391,9 +1391,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; } } @@ -1402,6 +1411,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; @@ -1422,6 +1432,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]); @@ -1447,14 +1458,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; } } @@ -1462,7 +1484,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;