From patchwork Thu Jan 9 11:50:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 207435 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AAF35C33CA3 for ; Thu, 9 Jan 2020 11:50:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 804E72072A for ; Thu, 9 Jan 2020 11:50:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=bgdev-pl.20150623.gappssmtp.com header.i=@bgdev-pl.20150623.gappssmtp.com header.b="SiG6Cc1m" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727701AbgAILum (ORCPT ); Thu, 9 Jan 2020 06:50:42 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:52596 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729049AbgAILuV (ORCPT ); Thu, 9 Jan 2020 06:50:21 -0500 Received: by mail-wm1-f67.google.com with SMTP id p9so2587249wmc.2 for ; Thu, 09 Jan 2020 03:50:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=wytPjSbZC28y5B3ceuqDy/iL3OfZmgStcvzlcuSAif8=; b=SiG6Cc1mpyfMT5NEAFeiRHSAjH7YMxA0RJXmD2ag9L8ctusuYKlQSObVqcCCaOwWNt N2XW1vYZ0qoUhc/03DANw2+Cm5eYlHweiiNHoztAoAkIV5EcvNVUhrHdERDaoxc9ThgN SeZf7mikebIAimCQD7yapsaO3XzWoQql83r1pqpuICz28x0Q7eaCQIBCc4pS7KqbuyWg pj45NMA+10OnXE8EtzGjmUylKCdnj5ax8ygZ5ZaLycyg2bHkcloAzvdWEi1j2pVdU21f uxR/0UOPeoJBjeMRBHjp5hm73gtCn/bA/fV5Jtk9sXyKWQw3JYh4YOiFY2nhzzMIopS0 r7qA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=wytPjSbZC28y5B3ceuqDy/iL3OfZmgStcvzlcuSAif8=; b=T1rQFa/JA1JqjIe0VZbj4kHDYqa4vl6X3GzJDXqz5Gg4IKgIZj9yW6ns6hnMAeIQSe QhZ/MVW0alQnstFBAzFovHMuKUdRRuZbDgfyakLDzZHy9BCGfKdd34uuuA5DQzJ3PeYU TOrjsrVy72Be1ZmQzcBfzkEqdsVxcYclqt8YlV1bIPiXSbhG1N24uLqheZLezBF/vao1 gjHAElSQjQkQ1glSi2pTlBuTB74RnLt8rFVmGSKMUK+LBX6A9jgLYq7vWjwcY6ovtgvK rZnPCGz6S5EB+J6IB+8pwrZqcye3G9d4TmtLvtQNh9VZDBDeIm4RhpFPP2DaeBX182do 8y0w== X-Gm-Message-State: APjAAAXVhwyB6wJmF1gibd80hdoHBMUQjRDxpMi8hknY231bWcGnJ30C lqToBBBdVMTXsmju4FE5EOU4WA== X-Google-Smtp-Source: APXvYqxSQ+7PJMz4DdsMYc5/fITw4V/NE80DtX2NZJzUz1MXy41a9JHFdcfTuyjSTQfEDe1VIBhRRQ== X-Received: by 2002:a1c:7901:: with SMTP id l1mr4334899wme.67.1578570619482; Thu, 09 Jan 2020 03:50:19 -0800 (PST) Received: from debian-brgl.home ([2a01:cb1d:af:5b00:6d6c:8493:1ab5:dad7]) by smtp.gmail.com with ESMTPSA id u16sm2574979wmj.41.2020.01.09.03.50.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Jan 2020 03:50:19 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Greg Kroah-Hartman , Andrew Morton Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Bartosz Golaszewski Subject: [PATCH v5 4/7] gpiolib: emit a debug message when adding events to a full kfifo Date: Thu, 9 Jan 2020 12:50:07 +0100 Message-Id: <20200109115010.27814-5-brgl@bgdev.pl> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20200109115010.27814-1-brgl@bgdev.pl> References: <20200109115010.27814-1-brgl@bgdev.pl> MIME-Version: 1.0 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski Currently if the line-event kfifo is full, we just silently drop any new events. Add a ratelimited debug message so that we at least have some trace in the kernel log of event overflow. Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 43c96e7cdc48..6b5d102dfb13 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -987,6 +987,8 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) 1, &le->wait.lock); if (ret) wake_up_poll(&le->wait, EPOLLIN); + else + pr_debug_ratelimited("event FIFO is full - event dropped\n"); return IRQ_HANDLED; } From patchwork Thu Jan 9 11:50:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 207436 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 75F38C33CA2 for ; Thu, 9 Jan 2020 11:50:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 42D592072A for ; Thu, 9 Jan 2020 11:50:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=bgdev-pl.20150623.gappssmtp.com header.i=@bgdev-pl.20150623.gappssmtp.com header.b="YHQt+wdH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729532AbgAILuh (ORCPT ); Thu, 9 Jan 2020 06:50:37 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:46462 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729126AbgAILuW (ORCPT ); Thu, 9 Jan 2020 06:50:22 -0500 Received: by mail-wr1-f65.google.com with SMTP id z7so6998424wrl.13 for ; Thu, 09 Jan 2020 03:50:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=dN7BC78Et1/WtU9AfhINNji0d8Qok1cjKZZH7ozfCDA=; b=YHQt+wdHTG0y1FPju1Gv7ptkbxnh36OU2vCoCpI13WJlQPB2c66f2nDiRE+FJSpKcF 6y7LIkueS0HWwWkrqSA63UekPgR4Cg3NhcT67G5kaeh8J32hbp7JOyEYWX6ciuMSdA3L rjgo3fgzt2kd/lOMLnUpZMODg3JGZ4C8Lzb5YwRaovy+XA0cz/KCKvExqAkTw0mMt4g7 I5OUnabVoKuPRzJyLDMf2GrY8q8gZryohq1WZNiV8Comtq8pfpfBxz1WbK1Qd0ewZNVp y4LEHWwUtMEdsJoPIKpzI1qmGFrqSo+6PW4p8xAIccSX3l10krj7xQ3m4jb8U0KNGuS8 UxRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=dN7BC78Et1/WtU9AfhINNji0d8Qok1cjKZZH7ozfCDA=; b=c2WI6drarhXZVxp4mXU1hS7s0a5yfdwS8ftv46YDlsZoYIGskS6SMDuIZBDudTMk2r erpDlvEdCNM90ppnbs3WSJJcsuGjDz5MkhPuayNU1x5mIB9tscAIKkU6nqL88onbwaWK IWomDgkdhiPIM6XUYARZ/qiIZqZb2UUfchuRtkZrtTDoDg6bHsZwnfjFHXNBLA4/bTO7 moUGEYpqytFmhuVaxaLaY3rilsPWAoBEe2jS45Jq2+4ppaEFTIyHfeiofgov8qBBxEIP szSUWmNKwziWgjC3Nvj+nbpf1R3e71U/7U/H7jTo8BuF7dwOV+bkw1sNAWyW/Bspdzj0 TxWA== X-Gm-Message-State: APjAAAXDvh1ZLcyG5E3G78fECxz2ZsNxLfMrCkYQzHjwXD1pdiZNtAOv vg3UzW0k4BEqBm1Xud3rBnKmuA== X-Google-Smtp-Source: APXvYqy0MEzvjy+aJtLYcic9hQ7b4x+4i7ptWYsKLoGRfulhrckZLCzfo9bcfPQR1jlyBISWcUkMvQ== X-Received: by 2002:a5d:44cd:: with SMTP id z13mr10639703wrr.104.1578570620777; Thu, 09 Jan 2020 03:50:20 -0800 (PST) Received: from debian-brgl.home ([2a01:cb1d:af:5b00:6d6c:8493:1ab5:dad7]) by smtp.gmail.com with ESMTPSA id u16sm2574979wmj.41.2020.01.09.03.50.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Jan 2020 03:50:20 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Greg Kroah-Hartman , Andrew Morton Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Bartosz Golaszewski Subject: [PATCH v5 5/7] gpiolib: provide a dedicated function for setting lineinfo Date: Thu, 9 Jan 2020 12:50:08 +0100 Message-Id: <20200109115010.27814-6-brgl@bgdev.pl> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20200109115010.27814-1-brgl@bgdev.pl> References: <20200109115010.27814-1-brgl@bgdev.pl> MIME-Version: 1.0 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski We'll soon be filling out the gpioline_info structure in multiple places. Add a separate function that given a gpio_desc sets all relevant fields. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib.c | 98 ++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6b5d102dfb13..00c1fce3c651 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1156,6 +1156,60 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) return ret; } +static void gpio_desc_to_lineinfo(struct gpio_desc *desc, + struct gpioline_info *info) +{ + struct gpio_chip *chip = desc->gdev->chip; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + if (desc->name) { + strncpy(info->name, desc->name, sizeof(info->name)); + info->name[sizeof(info->name) - 1] = '\0'; + } else { + info->name[0] = '\0'; + } + + if (desc->label) { + strncpy(info->consumer, desc->label, sizeof(info->consumer)); + info->consumer[sizeof(info->consumer) - 1] = '\0'; + } else { + info->consumer[0] = '\0'; + } + + /* + * Userspace only need to know that the kernel is using this GPIO so + * it can't use 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) || + !pinctrl_gpio_can_use_line(chip->base + info->line_offset)) + info->flags |= GPIOLINE_FLAG_KERNEL; + if (test_bit(FLAG_IS_OUT, &desc->flags)) + info->flags |= GPIOLINE_FLAG_IS_OUT; + if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) + info->flags |= GPIOLINE_FLAG_ACTIVE_LOW; + if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) + info->flags |= (GPIOLINE_FLAG_OPEN_DRAIN | + GPIOLINE_FLAG_IS_OUT); + if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) + info->flags |= (GPIOLINE_FLAG_OPEN_SOURCE | + GPIOLINE_FLAG_IS_OUT); + if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) + info->flags |= GPIOLINE_FLAG_BIAS_DISABLE; + if (test_bit(FLAG_PULL_DOWN, &desc->flags)) + info->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN; + if (test_bit(FLAG_PULL_UP, &desc->flags)) + info->flags |= GPIOLINE_FLAG_BIAS_PULL_UP; + + spin_unlock_irqrestore(&gpio_lock, flags); +} + /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ @@ -1196,49 +1250,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(desc)) return PTR_ERR(desc); - if (desc->name) { - strncpy(lineinfo.name, desc->name, - sizeof(lineinfo.name)); - lineinfo.name[sizeof(lineinfo.name)-1] = '\0'; - } else { - lineinfo.name[0] = '\0'; - } - if (desc->label) { - strncpy(lineinfo.consumer, desc->label, - sizeof(lineinfo.consumer)); - lineinfo.consumer[sizeof(lineinfo.consumer)-1] = '\0'; - } else { - lineinfo.consumer[0] = '\0'; - } - - /* - * Userspace only need to know that the kernel is using - * this GPIO so it can't use it. - */ - lineinfo.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) || - !pinctrl_gpio_can_use_line(chip->base + lineinfo.line_offset)) - lineinfo.flags |= GPIOLINE_FLAG_KERNEL; - if (test_bit(FLAG_IS_OUT, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_IS_OUT; - if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_ACTIVE_LOW; - if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) - lineinfo.flags |= (GPIOLINE_FLAG_OPEN_DRAIN | - GPIOLINE_FLAG_IS_OUT); - if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) - lineinfo.flags |= (GPIOLINE_FLAG_OPEN_SOURCE | - GPIOLINE_FLAG_IS_OUT); - if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_BIAS_DISABLE; - if (test_bit(FLAG_PULL_DOWN, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN; - if (test_bit(FLAG_PULL_UP, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_BIAS_PULL_UP; + gpio_desc_to_lineinfo(desc, &lineinfo); if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) return -EFAULT; From patchwork Thu Jan 9 11:50:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 207437 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0E38FC33CA2 for ; Thu, 9 Jan 2020 11:50:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C339A2072A for ; Thu, 9 Jan 2020 11:50:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=bgdev-pl.20150623.gappssmtp.com header.i=@bgdev-pl.20150623.gappssmtp.com header.b="WwsZWRk7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729039AbgAILu0 (ORCPT ); Thu, 9 Jan 2020 06:50:26 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:51344 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729199AbgAILuZ (ORCPT ); Thu, 9 Jan 2020 06:50:25 -0500 Received: by mail-wm1-f67.google.com with SMTP id d73so2587666wmd.1 for ; Thu, 09 Jan 2020 03:50:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ZU8xpfGCJYQ2oLL/99Zcc/U08gwl6OsAoQURuK+eP5w=; b=WwsZWRk7+2/kJTc8WvBSDebwuSuNojVNx5lV1Wp+PKJLRWvu6cZ2Thxw3aYpHfKVg9 HLcn4Giw1NKQMZ8Cv78jzYkm5qxHYvb2x72TwqGSMqdHNRz7CnsF9//OBNT1FYLXmE17 HrMOqtk1OZKQZGn9H6nrFnEk9z0Q+ZMF22PrLj36/8YNt6KZ9ULQfja+XA+X/9aPH6K6 sDwEQ9cCnN/rCrLrF+9v7/Mc+FpGgNbE/u6nPDyQFzq7+a/J/pem8/+DL7YgKlCRI0Bn Kiu6sWJjBvale10PzbH1rIVPexKSLzzMVRfWwvC6g2325fB3MXs78DyTUz8DcF8zgJ4h 4keQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZU8xpfGCJYQ2oLL/99Zcc/U08gwl6OsAoQURuK+eP5w=; b=Z2pvoZioLRpW6sQlp5GvB1n7TFgxbu6CGmPXfnALhC1ZGCmrijHkTb/nZIqg2oX8Yr ZczueZYfxGU4ks2dNOttzI/rZDuvLjFtyw430W54TOHNTKKe3eDY3gvd6ko8MijbyrDG 646rqE6TR5Es4m2x9dktxHWMbJ/tT+Lx+Kj6QQjHq/27d9fl6vDsTTDyQUEWQhdFzL7u vd4uuDJ7zDzFZ0PxEJIHBWNrZ/lsXksvqZCF3vXxmwhoZkX8In/Km1dyh0mST+ZEmMHX 5p8jdw+u7dNRJApGg/hjXaJQv8yX8GGryd7kLdcSQglyBGIVnw7+Uim6JUDHVOcrZU5h aN2A== X-Gm-Message-State: APjAAAVADuRN5Ulb9jSTg91B0VFZRrDOeX5kqsgdPGGfhw2uG1YncIca WPbRwNBpUMmcel4LuWPVtPqEAZwL5qI= X-Google-Smtp-Source: APXvYqw4QdR/4BomvxZM5+zdDP0SokN5PJiB5ql2Pn+0+K1CoeDF/DQHTrS1VYbKyYd7Fu+B7VHl+w== X-Received: by 2002:a7b:cc09:: with SMTP id f9mr4465175wmh.71.1578570622558; Thu, 09 Jan 2020 03:50:22 -0800 (PST) Received: from debian-brgl.home ([2a01:cb1d:af:5b00:6d6c:8493:1ab5:dad7]) by smtp.gmail.com with ESMTPSA id u16sm2574979wmj.41.2020.01.09.03.50.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Jan 2020 03:50:21 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Greg Kroah-Hartman , Andrew Morton Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Bartosz Golaszewski Subject: [PATCH v5 6/7] gpiolib: add new ioctl() for monitoring changes in line info Date: Thu, 9 Jan 2020 12:50:09 +0100 Message-Id: <20200109115010.27814-7-brgl@bgdev.pl> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20200109115010.27814-1-brgl@bgdev.pl> References: <20200109115010.27814-1-brgl@bgdev.pl> MIME-Version: 1.0 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski Currently there is no way for user-space to be informed about changes in status of GPIO lines e.g. when someone else requests the line or its config changes. We can only periodically re-read the line-info. This is fine for simple one-off user-space tools, but any daemon that provides a centralized access to GPIO chips would benefit hugely from an event driven line info synchronization. This patch adds a new ioctl() that allows user-space processes to reuse the file descriptor associated with the character device for watching any changes in line properties. Every such event contains the updated line information. Currently the events are generated on three types of status changes: when a line is requested, when it's released and when its config is changed. The first two are self-explanatory. For the third one: this will only happen when another user-space process calls the new SET_CONFIG ioctl() as any changes that can happen from within the kernel (i.e. set_transitory() or set_debounce()) are of no interest to user-space. Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 187 ++++++++++++++++++++++++++++++++++++-- drivers/gpio/gpiolib.h | 1 + include/uapi/linux/gpio.h | 30 ++++++ 3 files changed, 210 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 00c1fce3c651..72ed84d822bf 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -555,6 +555,9 @@ static long linehandle_set_config(struct linehandle_state *lh, if (ret) return ret; } + + atomic_notifier_call_chain(&desc->gdev->notifier, + GPIOLINE_CHANGED_CONFIG, desc); } return 0; } @@ -1210,14 +1213,25 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, spin_unlock_irqrestore(&gpio_lock, flags); } +struct gpio_chardev_data { + struct gpio_device *gdev; + wait_queue_head_t wait; + DECLARE_KFIFO(events, struct gpioline_info_changed, 32); + struct notifier_block lineinfo_changed_nb; + unsigned long *watched_lines; +}; + /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct gpio_device *gdev = filp->private_data; + struct gpio_chardev_data *priv = filp->private_data; + struct gpio_device *gdev = priv->gdev; struct gpio_chip *chip = gdev->chip; void __user *ip = (void __user *)arg; + struct gpio_desc *desc; + __u32 offset; /* We fail any subsequent ioctl():s when the chip is gone */ if (!chip) @@ -1239,9 +1253,9 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_to_user(ip, &chipinfo, sizeof(chipinfo))) return -EFAULT; return 0; - } else if (cmd == GPIO_GET_LINEINFO_IOCTL) { + } else if (cmd == GPIO_GET_LINEINFO_IOCTL || + cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) { struct gpioline_info lineinfo; - struct gpio_desc *desc; if (copy_from_user(&lineinfo, ip, sizeof(lineinfo))) return -EFAULT; @@ -1254,11 +1268,25 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) return -EFAULT; + + if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) + set_bit(desc_to_gpio(desc), priv->watched_lines); + return 0; } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) { return linehandle_create(gdev, ip); } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) { return lineevent_create(gdev, ip); + } else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) { + if (copy_from_user(&offset, ip, sizeof(offset))) + return -EFAULT; + + desc = gpiochip_get_desc(chip, offset); + if (IS_ERR(desc)) + return PTR_ERR(desc); + + clear_bit(desc_to_gpio(desc), &desc->flags); + return 0; } return -EINVAL; } @@ -1271,6 +1299,102 @@ static long gpio_ioctl_compat(struct file *filp, unsigned int cmd, } #endif +static struct gpio_chardev_data * +to_gpio_chardev_data(struct notifier_block *nb) +{ + return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb); +} + +static int lineinfo_changed_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct gpio_chardev_data *priv = to_gpio_chardev_data(nb); + struct gpioline_info_changed chg; + struct gpio_desc *desc = data; + int ret; + + if (!test_bit(desc_to_gpio(desc), priv->watched_lines)) + return NOTIFY_DONE; + + memset(&chg, 0, sizeof(chg)); + chg.info.line_offset = gpio_chip_hwgpio(desc); + chg.event_type = action; + chg.timestamp = ktime_get_real_ns(); + gpio_desc_to_lineinfo(desc, &chg.info); + + ret = kfifo_in_spinlocked(&priv->events, &chg, + 1, &priv->wait.lock); + if (ret) + wake_up_poll(&priv->wait, EPOLLIN); + else + pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n"); + + return NOTIFY_OK; +} + +static __poll_t lineinfo_watch_poll(struct file *filep, + struct poll_table_struct *pollt) +{ + struct gpio_chardev_data *priv = filep->private_data; + __poll_t events = 0; + + poll_wait(filep, &priv->wait, pollt); + + if (!kfifo_is_empty_spinlocked_noirqsave(&priv->events, + &priv->wait.lock)) + events = EPOLLIN | EPOLLRDNORM; + + return events; +} + +static ssize_t lineinfo_watch_read(struct file *filep, char __user *buf, + size_t count, loff_t *off) +{ + struct gpio_chardev_data *priv = filep->private_data; + struct gpioline_info_changed event; + ssize_t bytes_read = 0; + int ret; + + if (count < sizeof(event)) + return -EINVAL; + + do { + spin_lock(&priv->wait.lock); + if (kfifo_is_empty(&priv->events)) { + if (bytes_read) { + spin_unlock(&priv->wait.lock); + return bytes_read; + } + + if (filep->f_flags & O_NONBLOCK) { + spin_unlock(&priv->wait.lock); + return -EAGAIN; + } + + ret = wait_event_interruptible_locked(priv->wait, + !kfifo_is_empty(&priv->events)); + if (ret) { + spin_unlock(&priv->wait.lock); + return ret; + } + } + + ret = kfifo_out(&priv->events, &event, 1); + spin_unlock(&priv->wait.lock); + if (ret != 1) { + ret = -EIO; + break; + /* We should never get here. See lineevent_read(). */ + } + + if (copy_to_user(buf + bytes_read, &event, sizeof(event))) + return -EFAULT; + bytes_read += sizeof(event); + } while (count >= bytes_read + sizeof(event)); + + return bytes_read; +} + /** * gpio_chrdev_open() - open the chardev for ioctl operations * @inode: inode for this chardev @@ -1281,14 +1405,48 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp) { struct gpio_device *gdev = container_of(inode->i_cdev, struct gpio_device, chrdev); + struct gpio_chardev_data *priv; + int ret = -ENOMEM; /* Fail on open if the backing gpiochip is gone */ if (!gdev->chip) return -ENODEV; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL); + if (!priv->watched_lines) + goto out_free_priv; + + init_waitqueue_head(&priv->wait); + INIT_KFIFO(priv->events); + priv->gdev = gdev; + + priv->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify; + ret = atomic_notifier_chain_register(&gdev->notifier, + &priv->lineinfo_changed_nb); + if (ret) + goto out_free_bitmap; + get_device(&gdev->dev); - filp->private_data = gdev; + filp->private_data = priv; - return nonseekable_open(inode, filp); + ret = nonseekable_open(inode, filp); + if (ret) + goto out_unregister_notifier; + + return ret; + +out_unregister_notifier: + atomic_notifier_chain_unregister(&gdev->notifier, + &priv->lineinfo_changed_nb); +out_free_bitmap: + bitmap_free(priv->watched_lines); +out_free_priv: + kfree(priv); + return ret; } /** @@ -1299,17 +1457,23 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp) */ static int gpio_chrdev_release(struct inode *inode, struct file *filp) { - struct gpio_device *gdev = container_of(inode->i_cdev, - struct gpio_device, chrdev); + struct gpio_chardev_data *priv = filp->private_data; + struct gpio_device *gdev = priv->gdev; + bitmap_free(priv->watched_lines); + atomic_notifier_chain_unregister(&gdev->notifier, + &priv->lineinfo_changed_nb); put_device(&gdev->dev); + kfree(priv); + return 0; } - static const struct file_operations gpio_fileops = { .release = gpio_chrdev_release, .open = gpio_chrdev_open, + .poll = lineinfo_watch_poll, + .read = lineinfo_watch_read, .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = gpio_ioctl, @@ -1520,6 +1684,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, for (i = 0; i < chip->ngpio; i++) gdev->descs[i].gdev = gdev; + ATOMIC_INIT_NOTIFIER_HEAD(&gdev->notifier); + #ifdef CONFIG_PINCTRL INIT_LIST_HEAD(&gdev->pin_ranges); #endif @@ -2859,6 +3025,8 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) } done: spin_unlock_irqrestore(&gpio_lock, flags); + atomic_notifier_call_chain(&desc->gdev->notifier, + GPIOLINE_CHANGED_REQUESTED, desc); return ret; } @@ -2956,6 +3124,9 @@ static bool gpiod_free_commit(struct gpio_desc *desc) } spin_unlock_irqrestore(&gpio_lock, flags); + atomic_notifier_call_chain(&desc->gdev->notifier, + GPIOLINE_CHANGED_RELEASED, desc); + return ret; } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index a1cbeabadc69..8e3969616cfe 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -54,6 +54,7 @@ struct gpio_device { const char *label; void *data; struct list_head list; + struct atomic_notifier_head notifier; #ifdef CONFIG_PINCTRL /* diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h index 799cf823d493..10183d4d4276 100644 --- a/include/uapi/linux/gpio.h +++ b/include/uapi/linux/gpio.h @@ -59,6 +59,34 @@ struct gpioline_info { /* Maximum number of requested handles */ #define GPIOHANDLES_MAX 64 +/* Possible line status change events */ +enum { + GPIOLINE_CHANGED_REQUESTED = 1, + GPIOLINE_CHANGED_RELEASED, + GPIOLINE_CHANGED_CONFIG, +}; + +/** + * struct gpioline_info_changed - Information about a change in status + * of a GPIO line + * @info: updated line information + * @timestamp: estimate of time of status change occurrence, in nanoseconds + * and GPIOLINE_CHANGED_CONFIG + * @event_type: one of GPIOLINE_CHANGED_REQUESTED, GPIOLINE_CHANGED_RELEASED + * + * Note: struct gpioline_info embedded here has 32-bit alignment on its own, + * but it works fine with 64-bit alignment too. With its 72 byte size, we can + * guarantee there are no implicit holes between it and subsequent members. + * The 5-byte padding at the end makes sure we don't add any implicit padding + * at the end of the structure on 64-bit architectures. + */ +struct gpioline_info_changed { + struct gpioline_info info; + __u64 timestamp; + __u32 event_type; + __u32 padding[5]; /* for future use */ +}; + /* Linerequest flags */ #define GPIOHANDLE_REQUEST_INPUT (1UL << 0) #define GPIOHANDLE_REQUEST_OUTPUT (1UL << 1) @@ -176,6 +204,8 @@ struct gpioevent_data { #define GPIO_GET_CHIPINFO_IOCTL _IOR(0xB4, 0x01, struct gpiochip_info) #define GPIO_GET_LINEINFO_IOCTL _IOWR(0xB4, 0x02, struct gpioline_info) +#define GPIO_GET_LINEINFO_WATCH_IOCTL _IOWR(0xB4, 0x0b, struct gpioline_info) +#define GPIO_GET_LINEINFO_UNWATCH_IOCTL _IOWR(0xB4, 0x0c, __u32) #define GPIO_GET_LINEHANDLE_IOCTL _IOWR(0xB4, 0x03, struct gpiohandle_request) #define GPIO_GET_LINEEVENT_IOCTL _IOWR(0xB4, 0x04, struct gpioevent_request)