From patchwork Wed Sep 29 03:15:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 12524493 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B375C433EF for ; Wed, 29 Sep 2021 03:19:25 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0A1C96138F for ; Wed, 29 Sep 2021 03:19:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 0A1C96138F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=RsT5k59kKZ2/7g/nxjFGCtjCCPlso05oQ4IZUgBsT+c=; b=Dz2/fiZNgpgsUG 66wgcRNXv0cPMarzukqfZqYvQakFoZcwl9ayOS+z9NIOYqr8wDhQPzJFqrQvnVTEoZXjfTVrpKhM+ 3zPzVOU71EHTPKxmVVY+BwZ04bsONtGGzZUQNwnOPcNwC5j4k2SDPOK/zVNUyaGG6MNVKLMKB1dWp NuBmyk9AjoXbK8WYQqNcgnNlwZLcGfELNntKQPUf0bqyPM5ojrGA5oyPr9/BuxT0CRNLpE2aCn3YU wNm/BDNLlixFkpZdUw+a3V8l1uq8yQK+yQqSxDXOm6dE9Ef5sNfTY2mUlJ+Osx9WF2F9hqUCfF7tH qjh7YqslCWFhe1LEXCtQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5N-009kgo-HG; Wed, 29 Sep 2021 03:16:45 +0000 Received: from mail-pj1-x1034.google.com ([2607:f8b0:4864:20::1034]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5C-009keJ-10 for linux-arm-kernel@lists.infradead.org; Wed, 29 Sep 2021 03:16:35 +0000 Received: by mail-pj1-x1034.google.com with SMTP id il14-20020a17090b164e00b0019c7a7c362dso3099718pjb.0 for ; Tue, 28 Sep 2021 20:16:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+ZCX6l6rPkwSUwDGpanKFUA22NwjyP3olTKYpKgLOP0=; b=UBYDsbSmiAdeqzoK0lYePg387mljjtNkfOL5zjqunA1iTil8qkxyOh7m1yNojsPMeB ZQ30GEqz9lBqEVPxHRELpm1pB2RXwyvFDILe1/ljlImQFgYVYzld33Iwa1xycfy4qnFZ zwklNYSJ9EX39cb0w0QchKs5RB6G9FGkhdwO5R1eP5+3Y8rt9IaZ1cRaqjchbh+AXPtV uAXdOym7WBduGCQrUWJOM36WA+sRoFX5oacGACMo7MrElbmliu27g5BeDscAFcuh0A7a cChfJYYlSzGWORde4BgXfjId7W00M2KdGVpFWIqeGoCyTBIeBsdJLWZlW5yKI/eVahlZ H8hQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+ZCX6l6rPkwSUwDGpanKFUA22NwjyP3olTKYpKgLOP0=; b=cgXch9crCXQ5NM2ZJkK7b/mCVNXq4PXdF3nrgTUFCv48B24IG3nJ0NCVlHhvuTbHf0 +90tAkuxG/fsP4fLiViBhbKUNza0F+cppvECUIl7t70NnftTIj1bklgxrxzIe40pmgzr gbW2fXHLWuCh28EcNTdj4Iak0wRiR/Z0wX7rs2sLQjQupghwS/4Dq8e911hoQUgng9NB +uuS0ml781LsOeDg6V31uD95fKnrg5dpv0xyhrQ8B1OtZE5oG+r7bdRP4Qk9lhLKM2c2 EKbRxmbkQqmheVBJijYV+1yOlSfS10o8SEyNyEm6hbm75wpM4e6hJ05y5iWKcjyW7pYH dMrA== X-Gm-Message-State: AOAM533eUpz7weZZqRyJJChvuorajYYAUpBIqcgGNkPmamecyd5PnBXg EtLfBC1OXGstvDpy1R/BSUU= X-Google-Smtp-Source: ABdhPJw+pGXvad4GoCAkpWu5pR5c2sAi96CsuR8Ivvu1vBMAjxtRXb/rcDloD/HioA+ptVoLRixeew== X-Received: by 2002:a17:90a:9509:: with SMTP id t9mr2582652pjo.149.1632885393205; Tue, 28 Sep 2021 20:16:33 -0700 (PDT) Received: from localhost.localdomain ([156.146.35.76]) by smtp.gmail.com with ESMTPSA id 65sm464203pfv.210.2021.09.28.20.16.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Sep 2021 20:16:32 -0700 (PDT) From: William Breathitt Gray To: jic23@kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, kernel@pengutronix.de, a.fatoum@pengutronix.de, kamel.bouhara@bootlin.com, gwendal@chromium.org, alexandre.belloni@bootlin.com, david@lechnology.com, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, syednwaris@gmail.com, patrick.havelange@essensium.com, fabrice.gasnier@st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, o.rempel@pengutronix.de, jarkko.nikula@linux.intel.com, William Breathitt Gray Subject: [PATCH v17 1/9] counter: Move counter enums to uapi header Date: Wed, 29 Sep 2021 12:15:58 +0900 Message-Id: <962a5f2027fafcf4f77c10e1baf520463960d1ee.1632884256.git.vilhelm.gray@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210928_201634_118717_AD6EB49B X-CRM114-Status: GOOD ( 16.51 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This is in preparation for a subsequent patch implementing a character device interface for the Counter subsystem. Reviewed-by: David Lechner Signed-off-by: William Breathitt Gray --- MAINTAINERS | 1 + include/linux/counter.h | 42 +-------------------------- include/uapi/linux/counter.h | 56 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 41 deletions(-) create mode 100644 include/uapi/linux/counter.h diff --git a/MAINTAINERS b/MAINTAINERS index 8d1ea0299004..3c95ada1b830 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4820,6 +4820,7 @@ F: Documentation/ABI/testing/sysfs-bus-counter F: Documentation/driver-api/generic-counter.rst F: drivers/counter/ F: include/linux/counter.h +F: include/uapi/linux/counter.h CP2615 I2C DRIVER M: Bence Csókás diff --git a/include/linux/counter.h b/include/linux/counter.h index 445f22d8bfe2..7c9f7e23953a 100644 --- a/include/linux/counter.h +++ b/include/linux/counter.h @@ -9,6 +9,7 @@ #include #include #include +#include struct counter_device; struct counter_count; @@ -27,47 +28,6 @@ enum counter_comp_type { COUNTER_COMP_COUNT_MODE, }; -enum counter_scope { - COUNTER_SCOPE_DEVICE, - COUNTER_SCOPE_SIGNAL, - COUNTER_SCOPE_COUNT, -}; - -enum counter_count_direction { - COUNTER_COUNT_DIRECTION_FORWARD, - COUNTER_COUNT_DIRECTION_BACKWARD, -}; - -enum counter_count_mode { - COUNTER_COUNT_MODE_NORMAL, - COUNTER_COUNT_MODE_RANGE_LIMIT, - COUNTER_COUNT_MODE_NON_RECYCLE, - COUNTER_COUNT_MODE_MODULO_N, -}; - -enum counter_function { - COUNTER_FUNCTION_INCREASE, - COUNTER_FUNCTION_DECREASE, - COUNTER_FUNCTION_PULSE_DIRECTION, - COUNTER_FUNCTION_QUADRATURE_X1_A, - COUNTER_FUNCTION_QUADRATURE_X1_B, - COUNTER_FUNCTION_QUADRATURE_X2_A, - COUNTER_FUNCTION_QUADRATURE_X2_B, - COUNTER_FUNCTION_QUADRATURE_X4, -}; - -enum counter_signal_level { - COUNTER_SIGNAL_LEVEL_LOW, - COUNTER_SIGNAL_LEVEL_HIGH, -}; - -enum counter_synapse_action { - COUNTER_SYNAPSE_ACTION_NONE, - COUNTER_SYNAPSE_ACTION_RISING_EDGE, - COUNTER_SYNAPSE_ACTION_FALLING_EDGE, - COUNTER_SYNAPSE_ACTION_BOTH_EDGES, -}; - /** * struct counter_comp - Counter component node * @type: Counter component data type diff --git a/include/uapi/linux/counter.h b/include/uapi/linux/counter.h new file mode 100644 index 000000000000..6113938a6044 --- /dev/null +++ b/include/uapi/linux/counter.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Userspace ABI for Counter character devices + * Copyright (C) 2020 William Breathitt Gray + */ +#ifndef _UAPI_COUNTER_H_ +#define _UAPI_COUNTER_H_ + +/* Component scope definitions */ +enum counter_scope { + COUNTER_SCOPE_DEVICE, + COUNTER_SCOPE_SIGNAL, + COUNTER_SCOPE_COUNT, +}; + +/* Count direction values */ +enum counter_count_direction { + COUNTER_COUNT_DIRECTION_FORWARD, + COUNTER_COUNT_DIRECTION_BACKWARD, +}; + +/* Count mode values */ +enum counter_count_mode { + COUNTER_COUNT_MODE_NORMAL, + COUNTER_COUNT_MODE_RANGE_LIMIT, + COUNTER_COUNT_MODE_NON_RECYCLE, + COUNTER_COUNT_MODE_MODULO_N, +}; + +/* Count function values */ +enum counter_function { + COUNTER_FUNCTION_INCREASE, + COUNTER_FUNCTION_DECREASE, + COUNTER_FUNCTION_PULSE_DIRECTION, + COUNTER_FUNCTION_QUADRATURE_X1_A, + COUNTER_FUNCTION_QUADRATURE_X1_B, + COUNTER_FUNCTION_QUADRATURE_X2_A, + COUNTER_FUNCTION_QUADRATURE_X2_B, + COUNTER_FUNCTION_QUADRATURE_X4, +}; + +/* Signal values */ +enum counter_signal_level { + COUNTER_SIGNAL_LEVEL_LOW, + COUNTER_SIGNAL_LEVEL_HIGH, +}; + +/* Action mode values */ +enum counter_synapse_action { + COUNTER_SYNAPSE_ACTION_NONE, + COUNTER_SYNAPSE_ACTION_RISING_EDGE, + COUNTER_SYNAPSE_ACTION_FALLING_EDGE, + COUNTER_SYNAPSE_ACTION_BOTH_EDGES, +}; + +#endif /* _UAPI_COUNTER_H_ */ From patchwork Wed Sep 29 03:15:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 12524497 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F39DDC433F5 for ; Wed, 29 Sep 2021 03:19:53 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B99CA61352 for ; Wed, 29 Sep 2021 03:19:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org B99CA61352 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=6/yLE/B44FPx2y1wvhQB1YyQ1MDZC3+X4KeoWIMfGyE=; b=mfqkD6aitFuAR3 ZG7y8UqDlvkzgE089JO9Xjjuui039oshz6RO2N3Ba3PEGz2zU47aU4PTM770d9qq15myN/9JazW3z NdtusbQY7GP0NOBrkkOMrtFQZ+oHEUCh5A8KUpGhBkLialZPxONezXOhAZobDM5cyA5r4zi2q0ZJH C1kytOQ5MPQYh8mTtoshlxs43PcG5BnSr1AE4JISVU9SYMPri13khgAAzpHhBwg4g+kNayKUahF4Y QfycqvpiGXIlYzJBx/7/1sczFZEioomqD+VXKrjiJUZK/fOedFZEAVHOrHmp4jrOQz5nvUj8qmEIF 8tpRGoYU6Nzfjs4BttKw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5a-009kkR-CG; Wed, 29 Sep 2021 03:16:58 +0000 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5J-009kfr-4a for linux-arm-kernel@lists.infradead.org; Wed, 29 Sep 2021 03:16:44 +0000 Received: by mail-pj1-x1035.google.com with SMTP id d13-20020a17090ad3cd00b0019e746f7bd4so3229242pjw.0 for ; Tue, 28 Sep 2021 20:16:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+bRpU6n1iAH9gqwtDfvB5wkKUtfILjwjjf98s8iYqmE=; b=ZkPExHpG0mNnS2pBxcaqKJU0njKKbxX2Vnn0ZI47S9H3F7yKeEGIIVeaiILbHePfb1 K8ZqrTT8QMKolDpBsxiTcYhvz6Cl1CM592SJgHZJ4Sptma19z+1OgS56SubddeG8stgn lmQxyF9tky/6Cu5wSObJERs2fGl1inTeSg89aiTzSzstY2RMigXNTwVO7fMtaUPXdqFh Grq1aT+pEjqpHWX1AuDA60KOpdluqWZCWtGm+Clgf3HLrujee6xG0WJQDlo1TSijpZEZ SP1qbvFbLUFXS4mApsy2fPNgQNpXi48Pa49xjpWssX5RFmotLLT6ZD4ratK9lAwqCQ/Z ME6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+bRpU6n1iAH9gqwtDfvB5wkKUtfILjwjjf98s8iYqmE=; b=l7k6zWVlEL05LhK/aGjF1vkcY4+lfc6iIz69BPQQwbrc/w6GN8pGSQAgHUtRAzag6E gIi+DXe0jEAWFouLuq4g1y0PZTJs1SgbONmWbMQrPm0oE4xFNM4sY8cl8GupGixzV+wE u+eplC6up5IbX0wLa2WrDh1MqhKxRE1FmMMGre92YGbPlr8QRq/5S+YLDHllUrQM85zl OX/xZWiFoc1aldhXc8fDn+aTdWT3W6znuzAS9H1jp9iZ1KglA6FW/RhFqIn/DMLyXwVX xFPxub1pdexYTyLTjXlJyq8W2rAZqTKn0qJ35ssZdnMloantLr60x1nPJcdAZVHir9Fb HcWQ== X-Gm-Message-State: AOAM532OUClb1MqrIPkQTuWfQkipYFXPBCgS8UQ5TKIfpeP2G+Al/OZT YPQR/dWWLAkwHt7WkQLsVEY= X-Google-Smtp-Source: ABdhPJx9J0xr8yfMUQu2/4z3Sr0A0BB40Rv4vdeT5IMJjvlNtMdKG2/a6F8vdAaPRWeFnF0HPl898A== X-Received: by 2002:a17:90b:1041:: with SMTP id gq1mr3728950pjb.11.1632885400285; Tue, 28 Sep 2021 20:16:40 -0700 (PDT) Received: from localhost.localdomain ([156.146.35.76]) by smtp.gmail.com with ESMTPSA id 65sm464203pfv.210.2021.09.28.20.16.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Sep 2021 20:16:39 -0700 (PDT) From: William Breathitt Gray To: jic23@kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, kernel@pengutronix.de, a.fatoum@pengutronix.de, kamel.bouhara@bootlin.com, gwendal@chromium.org, alexandre.belloni@bootlin.com, david@lechnology.com, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, syednwaris@gmail.com, patrick.havelange@essensium.com, fabrice.gasnier@st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, o.rempel@pengutronix.de, jarkko.nikula@linux.intel.com, William Breathitt Gray , Dan Carpenter Subject: [PATCH v17 2/9] counter: Add character device interface Date: Wed, 29 Sep 2021 12:15:59 +0900 Message-Id: X-Mailer: git-send-email 2.33.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210928_201641_259712_B728E868 X-CRM114-Status: GOOD ( 30.88 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This patch introduces a character device interface for the Counter subsystem. Device data is exposed through standard character device read operations. Device data is gathered when a Counter event is pushed by the respective Counter device driver. Configuration is handled via ioctl operations on the respective Counter character device node. Cc: David Lechner Cc: Gwendal Grignou Cc: Dan Carpenter Cc: Oleksij Rempel Signed-off-by: William Breathitt Gray --- drivers/counter/Makefile | 2 +- drivers/counter/counter-chrdev.c | 578 +++++++++++++++++++++++++++++++ drivers/counter/counter-chrdev.h | 14 + drivers/counter/counter-core.c | 56 ++- include/linux/counter.h | 56 +++ include/uapi/linux/counter.h | 98 ++++++ 6 files changed, 798 insertions(+), 6 deletions(-) create mode 100644 drivers/counter/counter-chrdev.c create mode 100644 drivers/counter/counter-chrdev.h diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile index 1ab7e087fdc2..8fde6c100ebc 100644 --- a/drivers/counter/Makefile +++ b/drivers/counter/Makefile @@ -4,7 +4,7 @@ # obj-$(CONFIG_COUNTER) += counter.o -counter-y := counter-core.o counter-sysfs.o +counter-y := counter-core.o counter-sysfs.o counter-chrdev.o obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o diff --git a/drivers/counter/counter-chrdev.c b/drivers/counter/counter-chrdev.c new file mode 100644 index 000000000000..967c94ae95bb --- /dev/null +++ b/drivers/counter/counter-chrdev.c @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generic Counter character device interface + * Copyright (C) 2020 William Breathitt Gray + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "counter-chrdev.h" + +struct counter_comp_node { + struct list_head l; + struct counter_component component; + struct counter_comp comp; + void *parent; +}; + +#define counter_comp_read_is_equal(a, b) \ + (a.action_read == b.action_read || \ + a.device_u8_read == b.device_u8_read || \ + a.count_u8_read == b.count_u8_read || \ + a.signal_u8_read == b.signal_u8_read || \ + a.device_u32_read == b.device_u32_read || \ + a.count_u32_read == b.count_u32_read || \ + a.signal_u32_read == b.signal_u32_read || \ + a.device_u64_read == b.device_u64_read || \ + a.count_u64_read == b.count_u64_read || \ + a.signal_u64_read == b.signal_u64_read) + +#define counter_comp_read_is_set(comp) \ + (comp.action_read || \ + comp.device_u8_read || \ + comp.count_u8_read || \ + comp.signal_u8_read || \ + comp.device_u32_read || \ + comp.count_u32_read || \ + comp.signal_u32_read || \ + comp.device_u64_read || \ + comp.count_u64_read || \ + comp.signal_u64_read) + +static ssize_t counter_chrdev_read(struct file *filp, char __user *buf, + size_t len, loff_t *f_ps) +{ + struct counter_device *const counter = filp->private_data; + int err; + unsigned int copied; + + if (!counter->ops) + return -ENODEV; + + if (len < sizeof(struct counter_event)) + return -EINVAL; + + do { + if (kfifo_is_empty(&counter->events)) { + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + + err = wait_event_interruptible(counter->events_wait, + !kfifo_is_empty(&counter->events) || + !counter->ops); + if (err < 0) + return err; + if (!counter->ops) + return -ENODEV; + } + + if (mutex_lock_interruptible(&counter->events_lock)) + return -ERESTARTSYS; + err = kfifo_to_user(&counter->events, buf, len, &copied); + mutex_unlock(&counter->events_lock); + if (err < 0) + return err; + } while (!copied); + + return copied; +} + +static __poll_t counter_chrdev_poll(struct file *filp, + struct poll_table_struct *pollt) +{ + struct counter_device *const counter = filp->private_data; + __poll_t events = 0; + + if (!counter->ops) + return events; + + poll_wait(filp, &counter->events_wait, pollt); + + if (!kfifo_is_empty(&counter->events)) + events = EPOLLIN | EPOLLRDNORM; + + return events; +} + +static void counter_events_list_free(struct list_head *const events_list) +{ + struct counter_event_node *p, *n; + struct counter_comp_node *q, *o; + + list_for_each_entry_safe(p, n, events_list, l) { + /* Free associated component nodes */ + list_for_each_entry_safe(q, o, &p->comp_list, l) { + list_del(&q->l); + kfree(q); + } + + /* Free event node */ + list_del(&p->l); + kfree(p); + } +} + +static int counter_set_event_node(struct counter_device *const counter, + struct counter_watch *const watch, + const struct counter_comp_node *const cfg) +{ + struct counter_event_node *event_node; + int err = 0; + struct counter_comp_node *comp_node; + + /* Search for event in the list */ + list_for_each_entry(event_node, &counter->next_events_list, l) + if (event_node->event == watch->event && + event_node->channel == watch->channel) + break; + + /* If event is not already in the list */ + if (&event_node->l == &counter->next_events_list) { + /* Allocate new event node */ + event_node = kmalloc(sizeof(*event_node), GFP_KERNEL); + if (!event_node) + return -ENOMEM; + + /* Configure event node and add to the list */ + event_node->event = watch->event; + event_node->channel = watch->channel; + INIT_LIST_HEAD(&event_node->comp_list); + list_add(&event_node->l, &counter->next_events_list); + } + + /* Check if component watch has already been set before */ + list_for_each_entry(comp_node, &event_node->comp_list, l) + if (comp_node->parent == cfg->parent && + counter_comp_read_is_equal(comp_node->comp, cfg->comp)) { + err = -EINVAL; + goto exit_free_event_node; + } + + /* Allocate component node */ + comp_node = kmalloc(sizeof(*comp_node), GFP_KERNEL); + if (!comp_node) { + err = -ENOMEM; + goto exit_free_event_node; + } + *comp_node = *cfg; + + /* Add component node to event node */ + list_add_tail(&comp_node->l, &event_node->comp_list); + +exit_free_event_node: + /* Free event node if no one else is watching */ + if (list_empty(&event_node->comp_list)) { + list_del(&event_node->l); + kfree(event_node); + } + + return err; +} + +static int counter_enable_events(struct counter_device *const counter) +{ + unsigned long flags; + int err = 0; + + mutex_lock(&counter->n_events_list_lock); + spin_lock_irqsave(&counter->events_list_lock, flags); + + counter_events_list_free(&counter->events_list); + list_replace_init(&counter->next_events_list, + &counter->events_list); + + if (counter->ops->events_configure) + err = counter->ops->events_configure(counter); + + spin_unlock_irqrestore(&counter->events_list_lock, flags); + mutex_unlock(&counter->n_events_list_lock); + + return err; +} + +static int counter_disable_events(struct counter_device *const counter) +{ + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&counter->events_list_lock, flags); + + counter_events_list_free(&counter->events_list); + + if (counter->ops->events_configure) + err = counter->ops->events_configure(counter); + + spin_unlock_irqrestore(&counter->events_list_lock, flags); + + mutex_lock(&counter->n_events_list_lock); + + counter_events_list_free(&counter->next_events_list); + + mutex_unlock(&counter->n_events_list_lock); + + return err; +} + +static int counter_add_watch(struct counter_device *const counter, + const unsigned long arg) +{ + void __user *const uwatch = (void __user *)arg; + struct counter_watch watch; + struct counter_comp_node comp_node = {}; + size_t parent, id; + struct counter_comp *ext; + size_t num_ext; + int err = 0; + + if (copy_from_user(&watch, uwatch, sizeof(watch))) + return -EFAULT; + + if (watch.component.type == COUNTER_COMPONENT_NONE) + goto no_component; + + parent = watch.component.parent; + + /* Configure parent component info for comp node */ + switch (watch.component.scope) { + case COUNTER_SCOPE_DEVICE: + ext = counter->ext; + num_ext = counter->num_ext; + break; + case COUNTER_SCOPE_SIGNAL: + if (parent >= counter->num_signals) + return -EINVAL; + parent = array_index_nospec(parent, counter->num_signals); + + comp_node.parent = counter->signals + parent; + + ext = counter->signals[parent].ext; + num_ext = counter->signals[parent].num_ext; + break; + case COUNTER_SCOPE_COUNT: + if (parent >= counter->num_counts) + return -EINVAL; + parent = array_index_nospec(parent, counter->num_counts); + + comp_node.parent = counter->counts + parent; + + ext = counter->counts[parent].ext; + num_ext = counter->counts[parent].num_ext; + break; + default: + return -EINVAL; + } + + id = watch.component.id; + + /* Configure component info for comp node */ + switch (watch.component.type) { + case COUNTER_COMPONENT_SIGNAL: + if (watch.component.scope != COUNTER_SCOPE_SIGNAL) + return -EINVAL; + + comp_node.comp.type = COUNTER_COMP_SIGNAL_LEVEL; + comp_node.comp.signal_u32_read = counter->ops->signal_read; + break; + case COUNTER_COMPONENT_COUNT: + if (watch.component.scope != COUNTER_SCOPE_COUNT) + return -EINVAL; + + comp_node.comp.type = COUNTER_COMP_U64; + comp_node.comp.count_u64_read = counter->ops->count_read; + break; + case COUNTER_COMPONENT_FUNCTION: + if (watch.component.scope != COUNTER_SCOPE_COUNT) + return -EINVAL; + + comp_node.comp.type = COUNTER_COMP_FUNCTION; + comp_node.comp.count_u32_read = counter->ops->function_read; + break; + case COUNTER_COMPONENT_SYNAPSE_ACTION: + if (watch.component.scope != COUNTER_SCOPE_COUNT) + return -EINVAL; + if (id >= counter->counts[parent].num_synapses) + return -EINVAL; + id = array_index_nospec(id, counter->counts[parent].num_synapses); + + comp_node.comp.type = COUNTER_COMP_SYNAPSE_ACTION; + comp_node.comp.action_read = counter->ops->action_read; + comp_node.comp.priv = counter->counts[parent].synapses + id; + break; + case COUNTER_COMPONENT_EXTENSION: + if (id >= num_ext) + return -EINVAL; + id = array_index_nospec(id, num_ext); + + comp_node.comp = ext[id]; + break; + default: + return -EINVAL; + } + if (!counter_comp_read_is_set(comp_node.comp)) + return -EOPNOTSUPP; + +no_component: + mutex_lock(&counter->n_events_list_lock); + + if (counter->ops->watch_validate) { + err = counter->ops->watch_validate(counter, &watch); + if (err < 0) + goto err_exit; + } + + comp_node.component = watch.component; + + err = counter_set_event_node(counter, &watch, &comp_node); + +err_exit: + mutex_unlock(&counter->n_events_list_lock); + + return err; +} + +static long counter_chrdev_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct counter_device *const counter = filp->private_data; + int ret = -ENODEV; + + mutex_lock(&counter->ops_exist_lock); + + if (!counter->ops) + goto out_unlock; + + switch (cmd) { + case COUNTER_ADD_WATCH_IOCTL: + ret = counter_add_watch(counter, arg); + break; + case COUNTER_ENABLE_EVENTS_IOCTL: + ret = counter_enable_events(counter); + break; + case COUNTER_DISABLE_EVENTS_IOCTL: + ret = counter_disable_events(counter); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + +out_unlock: + mutex_unlock(&counter->ops_exist_lock); + + return ret; +} + +static int counter_chrdev_open(struct inode *inode, struct file *filp) +{ + struct counter_device *const counter = container_of(inode->i_cdev, + typeof(*counter), + chrdev); + + /* Ensure chrdev is not opened more than 1 at a time */ + if (!atomic_add_unless(&counter->chrdev_lock, 1, 1)) + return -EBUSY; + + get_device(&counter->dev); + filp->private_data = counter; + + return nonseekable_open(inode, filp); +} + +static int counter_chrdev_release(struct inode *inode, struct file *filp) +{ + struct counter_device *const counter = filp->private_data; + int ret = 0; + + mutex_lock(&counter->ops_exist_lock); + + if (!counter->ops) { + /* Free any lingering held memory */ + counter_events_list_free(&counter->events_list); + counter_events_list_free(&counter->next_events_list); + ret = -ENODEV; + goto out_unlock; + } + + ret = counter_disable_events(counter); + if (ret < 0) { + mutex_unlock(&counter->ops_exist_lock); + return ret; + } + +out_unlock: + mutex_unlock(&counter->ops_exist_lock); + + put_device(&counter->dev); + atomic_dec(&counter->chrdev_lock); + + return ret; +} + +static const struct file_operations counter_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = counter_chrdev_read, + .poll = counter_chrdev_poll, + .unlocked_ioctl = counter_chrdev_ioctl, + .open = counter_chrdev_open, + .release = counter_chrdev_release, +}; + +int counter_chrdev_add(struct counter_device *const counter) +{ + /* Initialize Counter events lists */ + INIT_LIST_HEAD(&counter->events_list); + INIT_LIST_HEAD(&counter->next_events_list); + spin_lock_init(&counter->events_list_lock); + mutex_init(&counter->n_events_list_lock); + init_waitqueue_head(&counter->events_wait); + mutex_init(&counter->events_lock); + + /* Initialize character device */ + atomic_set(&counter->chrdev_lock, 0); + cdev_init(&counter->chrdev, &counter_fops); + + /* Allocate Counter events queue */ + return kfifo_alloc(&counter->events, 64, GFP_KERNEL); +} + +void counter_chrdev_remove(struct counter_device *const counter) +{ + kfifo_free(&counter->events); +} + +static int counter_get_data(struct counter_device *const counter, + const struct counter_comp_node *const comp_node, + u64 *const value) +{ + const struct counter_comp *const comp = &comp_node->comp; + void *const parent = comp_node->parent; + u8 value_u8 = 0; + u32 value_u32 = 0; + int ret; + + if (comp_node->component.type == COUNTER_COMPONENT_NONE) + return 0; + + switch (comp->type) { + case COUNTER_COMP_U8: + case COUNTER_COMP_BOOL: + switch (comp_node->component.scope) { + case COUNTER_SCOPE_DEVICE: + ret = comp->device_u8_read(counter, &value_u8); + break; + case COUNTER_SCOPE_SIGNAL: + ret = comp->signal_u8_read(counter, parent, &value_u8); + break; + case COUNTER_SCOPE_COUNT: + ret = comp->count_u8_read(counter, parent, &value_u8); + break; + } + *value = value_u8; + return ret; + case COUNTER_COMP_SIGNAL_LEVEL: + case COUNTER_COMP_FUNCTION: + case COUNTER_COMP_ENUM: + case COUNTER_COMP_COUNT_DIRECTION: + case COUNTER_COMP_COUNT_MODE: + switch (comp_node->component.scope) { + case COUNTER_SCOPE_DEVICE: + ret = comp->device_u32_read(counter, &value_u32); + break; + case COUNTER_SCOPE_SIGNAL: + ret = comp->signal_u32_read(counter, parent, + &value_u32); + break; + case COUNTER_SCOPE_COUNT: + ret = comp->count_u32_read(counter, parent, &value_u32); + break; + } + *value = value_u32; + return ret; + case COUNTER_COMP_U64: + switch (comp_node->component.scope) { + case COUNTER_SCOPE_DEVICE: + return comp->device_u64_read(counter, value); + case COUNTER_SCOPE_SIGNAL: + return comp->signal_u64_read(counter, parent, value); + case COUNTER_SCOPE_COUNT: + return comp->count_u64_read(counter, parent, value); + default: + return -EINVAL; + } + case COUNTER_COMP_SYNAPSE_ACTION: + ret = comp->action_read(counter, parent, comp->priv, + &value_u32); + *value = value_u32; + return ret; + default: + return -EINVAL; + } +} + +/** + * counter_push_event - queue event for userspace reading + * @counter: pointer to Counter structure + * @event: triggered event + * @channel: event channel + * + * Note: If no one is watching for the respective event, it is silently + * discarded. + */ +void counter_push_event(struct counter_device *const counter, const u8 event, + const u8 channel) +{ + struct counter_event ev; + unsigned int copied = 0; + unsigned long flags; + struct counter_event_node *event_node; + struct counter_comp_node *comp_node; + + ev.timestamp = ktime_get_ns(); + ev.watch.event = event; + ev.watch.channel = channel; + + /* Could be in an interrupt context, so use a spin lock */ + spin_lock_irqsave(&counter->events_list_lock, flags); + + /* Search for event in the list */ + list_for_each_entry(event_node, &counter->events_list, l) + if (event_node->event == event && + event_node->channel == channel) + break; + + /* If event is not in the list */ + if (&event_node->l == &counter->events_list) + goto exit_early; + + /* Read and queue relevant comp for userspace */ + list_for_each_entry(comp_node, &event_node->comp_list, l) { + ev.watch.component = comp_node->component; + ev.status = -counter_get_data(counter, comp_node, &ev.value); + + copied += kfifo_in(&counter->events, &ev, 1); + } + +exit_early: + spin_unlock_irqrestore(&counter->events_list_lock, flags); + + if (copied) + wake_up_poll(&counter->events_wait, EPOLLIN); +} +EXPORT_SYMBOL_GPL(counter_push_event); diff --git a/drivers/counter/counter-chrdev.h b/drivers/counter/counter-chrdev.h new file mode 100644 index 000000000000..5529d16703c4 --- /dev/null +++ b/drivers/counter/counter-chrdev.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Counter character device interface + * Copyright (C) 2020 William Breathitt Gray + */ +#ifndef _COUNTER_CHRDEV_H_ +#define _COUNTER_CHRDEV_H_ + +#include + +int counter_chrdev_add(struct counter_device *const counter); +void counter_chrdev_remove(struct counter_device *const counter); + +#endif /* _COUNTER_CHRDEV_H_ */ diff --git a/drivers/counter/counter-core.c b/drivers/counter/counter-core.c index 3cda2c47bacb..5acc54539623 100644 --- a/drivers/counter/counter-core.c +++ b/drivers/counter/counter-core.c @@ -3,14 +3,22 @@ * Generic Counter interface * Copyright (C) 2020 William Breathitt Gray */ +#include #include #include +#include #include +#include #include #include #include +#include #include +#include +#include +#include +#include "counter-chrdev.h" #include "counter-sysfs.h" /* Provides a unique ID for each counter device */ @@ -18,6 +26,9 @@ static DEFINE_IDA(counter_ida); static void counter_device_release(struct device *dev) { + struct counter_device *const counter = dev_get_drvdata(dev); + + counter_chrdev_remove(counter); ida_free(&counter_ida, dev->id); } @@ -31,6 +42,8 @@ static struct bus_type counter_bus_type = { .dev_name = "counter", }; +static dev_t counter_devt; + /** * counter_register - register Counter to the system * @counter: pointer to Counter to register @@ -53,10 +66,13 @@ int counter_register(struct counter_device *const counter) if (id < 0) return id; + mutex_init(&counter->ops_exist_lock); + /* Configure device structure for Counter */ dev->id = id; dev->type = &counter_device_type; dev->bus = &counter_bus_type; + dev->devt = MKDEV(MAJOR(counter_devt), id); if (counter->parent) { dev->parent = counter->parent; dev->of_node = counter->parent->of_node; @@ -64,18 +80,22 @@ int counter_register(struct counter_device *const counter) device_initialize(dev); dev_set_drvdata(dev, counter); - /* Add Counter sysfs attributes */ err = counter_sysfs_add(counter); if (err < 0) goto err_free_id; - /* Add device to system */ - err = device_add(dev); + err = counter_chrdev_add(counter); if (err < 0) goto err_free_id; + err = cdev_device_add(&counter->chrdev, dev); + if (err < 0) + goto err_remove_chrdev; + return 0; +err_remove_chrdev: + counter_chrdev_remove(counter); err_free_id: put_device(dev); return err; @@ -93,7 +113,16 @@ void counter_unregister(struct counter_device *const counter) if (!counter) return; - device_unregister(&counter->dev); + cdev_device_del(&counter->chrdev, &counter->dev); + + mutex_lock(&counter->ops_exist_lock); + + counter->ops = NULL; + wake_up(&counter->events_wait); + + mutex_unlock(&counter->ops_exist_lock); + + put_device(&counter->dev); } EXPORT_SYMBOL_GPL(counter_unregister); @@ -127,13 +156,30 @@ int devm_counter_register(struct device *dev, } EXPORT_SYMBOL_GPL(devm_counter_register); +#define COUNTER_DEV_MAX 256 + static int __init counter_init(void) { - return bus_register(&counter_bus_type); + int err; + + err = bus_register(&counter_bus_type); + if (err < 0) + return err; + + err = alloc_chrdev_region(&counter_devt, 0, COUNTER_DEV_MAX, "counter"); + if (err < 0) + goto err_unregister_bus; + + return 0; + +err_unregister_bus: + bus_unregister(&counter_bus_type); + return err; } static void __exit counter_exit(void) { + unregister_chrdev_region(counter_devt, COUNTER_DEV_MAX); bus_unregister(&counter_bus_type); } diff --git a/include/linux/counter.h b/include/linux/counter.h index 7c9f7e23953a..22b14a552b1d 100644 --- a/include/linux/counter.h +++ b/include/linux/counter.h @@ -6,9 +6,14 @@ #ifndef _COUNTER_H_ #define _COUNTER_H_ +#include #include #include +#include +#include +#include #include +#include #include struct counter_device; @@ -199,6 +204,20 @@ struct counter_count { size_t num_ext; }; +/** + * struct counter_event_node - Counter Event node + * @l: list of current watching Counter events + * @event: event that triggers + * @channel: event channel + * @comp_list: list of components to watch when event triggers + */ +struct counter_event_node { + struct list_head l; + u8 event; + u8 channel; + struct list_head comp_list; +}; + /** * struct counter_ops - Callbacks from driver * @signal_read: optional read callback for Signals. The read level of @@ -222,6 +241,13 @@ struct counter_count { * @action_write: optional write callback for Synapse action modes. The * action mode to write for the respective Synapse is * passed in via the action parameter. + * @events_configure: optional write callback to configure events. The list of + * struct counter_event_node may be accessed via the + * events_list member of the counter parameter. + * @watch_validate: optional callback to validate a watch. The Counter + * component watch configuration is passed in via the watch + * parameter. A return value of 0 indicates a valid Counter + * component watch configuration. */ struct counter_ops { int (*signal_read)(struct counter_device *counter, @@ -245,6 +271,9 @@ struct counter_ops { struct counter_count *count, struct counter_synapse *synapse, enum counter_synapse_action action); + int (*events_configure)(struct counter_device *counter); + int (*watch_validate)(struct counter_device *counter, + const struct counter_watch *watch); }; /** @@ -260,6 +289,16 @@ struct counter_ops { * @num_ext: number of Counter device extensions specified in @ext * @priv: optional private data supplied by driver * @dev: internal device structure + * @chrdev: internal character device structure + * @events_list: list of current watching Counter events + * @events_list_lock: lock to protect Counter events list operations + * @next_events_list: list of next watching Counter events + * @n_events_list_lock: lock to protect Counter next events list operations + * @events: queue of detected Counter events + * @events_wait: wait queue to allow blocking reads of Counter events + * @events_lock: lock to protect Counter events queue read operations + * @chrdev_lock: lock to limit chrdev to a single open at a time + * @ops_exist_lock: lock to prevent use during removal */ struct counter_device { const char *name; @@ -278,12 +317,29 @@ struct counter_device { void *priv; struct device dev; + struct cdev chrdev; + struct list_head events_list; + spinlock_t events_list_lock; + struct list_head next_events_list; + struct mutex n_events_list_lock; + DECLARE_KFIFO_PTR(events, struct counter_event); + wait_queue_head_t events_wait; + struct mutex events_lock; + /* + * chrdev_lock is locked by counter_chrdev_open() and unlocked by + * counter_chrdev_release(), so a mutex is not possible here because + * chrdev_lock will invariably be held when returning to user space + */ + atomic_t chrdev_lock; + struct mutex ops_exist_lock; }; int counter_register(struct counter_device *const counter); void counter_unregister(struct counter_device *const counter); int devm_counter_register(struct device *dev, struct counter_device *const counter); +void counter_push_event(struct counter_device *const counter, const u8 event, + const u8 channel); #define COUNTER_COMP_DEVICE_U8(_name, _read, _write) \ { \ diff --git a/include/uapi/linux/counter.h b/include/uapi/linux/counter.h index 6113938a6044..d0aa95aeff7b 100644 --- a/include/uapi/linux/counter.h +++ b/include/uapi/linux/counter.h @@ -6,6 +6,19 @@ #ifndef _UAPI_COUNTER_H_ #define _UAPI_COUNTER_H_ +#include +#include + +/* Component type definitions */ +enum counter_component_type { + COUNTER_COMPONENT_NONE, + COUNTER_COMPONENT_SIGNAL, + COUNTER_COMPONENT_COUNT, + COUNTER_COMPONENT_FUNCTION, + COUNTER_COMPONENT_SYNAPSE_ACTION, + COUNTER_COMPONENT_EXTENSION, +}; + /* Component scope definitions */ enum counter_scope { COUNTER_SCOPE_DEVICE, @@ -13,6 +26,91 @@ enum counter_scope { COUNTER_SCOPE_COUNT, }; +/** + * struct counter_component - Counter component identification + * @type: component type (one of enum counter_component_type) + * @scope: component scope (one of enum counter_scope) + * @parent: parent ID (matching the ID suffix of the respective parent sysfs + * path as described by the ABI documentation file + * Documentation/ABI/testing/sysfs-bus-counter) + * @id: component ID (matching the ID provided by the respective *_component_id + * sysfs attribute of the desired component) + * + * For example, if the Count 2 ceiling extension of Counter device 4 is desired, + * set type equal to COUNTER_COMPONENT_EXTENSION, scope equal to + * COUNTER_COUNT_SCOPE, parent equal to 2, and id equal to the value provided by + * the respective /sys/bus/counter/devices/counter4/count2/ceiling_component_id + * sysfs attribute. + */ +struct counter_component { + __u8 type; + __u8 scope; + __u8 parent; + __u8 id; +}; + +/* Event type definitions */ +enum counter_event_type { + /* Count value increased past ceiling */ + COUNTER_EVENT_OVERFLOW, + /* Count value decreased past floor */ + COUNTER_EVENT_UNDERFLOW, + /* Count value increased past ceiling, or decreased past floor */ + COUNTER_EVENT_OVERFLOW_UNDERFLOW, + /* Count value reached threshold */ + COUNTER_EVENT_THRESHOLD, + /* Index signal detected */ + COUNTER_EVENT_INDEX, +}; + +/** + * struct counter_watch - Counter component watch configuration + * @component: component to watch when event triggers + * @event: event that triggers (one of enum counter_event_type) + * @channel: event channel (typically 0 unless the device supports concurrent + * events of the same type) + */ +struct counter_watch { + struct counter_component component; + __u8 event; + __u8 channel; +}; + +/* + * Queues a Counter watch for the specified event. + * + * The queued watches will not be applied until COUNTER_ENABLE_EVENTS_IOCTL is + * called. + */ +#define COUNTER_ADD_WATCH_IOCTL _IOW(0x3E, 0x00, struct counter_watch) +/* + * Enables monitoring the events specified by the Counter watches that were + * queued by COUNTER_ADD_WATCH_IOCTL. + * + * If events are already enabled, the new set of watches replaces the old one. + * Calling this ioctl also has the effect of clearing the queue of watches added + * by COUNTER_ADD_WATCH_IOCTL. + */ +#define COUNTER_ENABLE_EVENTS_IOCTL _IO(0x3E, 0x01) +/* + * Stops monitoring the previously enabled events. + */ +#define COUNTER_DISABLE_EVENTS_IOCTL _IO(0x3E, 0x02) + +/** + * struct counter_event - Counter event data + * @timestamp: best estimate of time of event occurrence, in nanoseconds + * @value: component value + * @watch: component watch configuration + * @status: return status (system error number) + */ +struct counter_event { + __aligned_u64 timestamp; + __aligned_u64 value; + struct counter_watch watch; + __u8 status; +}; + /* Count direction values */ enum counter_count_direction { COUNTER_COUNT_DIRECTION_FORWARD, From patchwork Wed Sep 29 03:16:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 12524499 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C293C433EF for ; Wed, 29 Sep 2021 03:20:06 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E9BF561247 for ; Wed, 29 Sep 2021 03:20:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org E9BF561247 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=rqgfDDtjTDUXRomvpby3XN76sV+NQ2hPedDDQe3TZJg=; b=tMvZjHGvxd9YLG G/OnYIZLzeagfDfxrxXFyLBb4C2yhoGINsTRawosev0sM/tX8KsFd3Ns5KQC33Hr3eDZBjgIZ+HWF 1vFv+uDn0kkAXuzmcDcV7Nr3qMJvoY7Q8kBiHZ+NCbDLEeM5aDWgDa/0T2vwveLSqSsapDNEKpLP6 mdJSKoqGlya/Ap91ZjVo8Sy8ePrXO59Kfe93Ki6UdZteDxoM67/duvyuibIiQlwXJm3ANvhmbIKS1 eLqlem8AF4pG3lU6Z8oH9hcRBjOE4uOiHa8NffCDvyUM/+GVg5rxkrJk5eI+/gc1abGfjzDLjRJtv 07G8a8tcTbZ5IbZxEE4w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5u-009kr5-5J; Wed, 29 Sep 2021 03:17:18 +0000 Received: from mail-pf1-x42a.google.com ([2607:f8b0:4864:20::42a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5P-009khe-Il for linux-arm-kernel@lists.infradead.org; Wed, 29 Sep 2021 03:16:49 +0000 Received: by mail-pf1-x42a.google.com with SMTP id n23so763923pfv.4 for ; Tue, 28 Sep 2021 20:16:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Q7EGeGlc3g3UDIDbbGLhO2X3OU7aZNwWkPtPyvxo14g=; b=HIflXNzE7mxlzeV4yFMuZX5F07sLBnNoIKi8a/rRfloVqlVQVWWesr9bfm9BnvIjDt pyU5WQGSMmcuZZrInUp3boMx1xkyiRCQpzzorNWkHbXjp3rv6myy4UghuucsUsZ9/nw1 PVSYor88fqVNATEGW5Ar3MnAqP5PDsu2Cr0Rmeg74JewERvAd7FXYc3Yp1Cc+NQqnGVb ur01oKcIGg5QjolmiHey8DxhYEvPe6ykeFerzpBQIgKWKg97piG/zPnTJfdZV98LNZDw mGU6ypIu2RPc7gCUPtWyZ9lW5jdkNeiVV/tsXtexg2AuLiXO40IzO1uoBjfa5FXCQbBa fjhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Q7EGeGlc3g3UDIDbbGLhO2X3OU7aZNwWkPtPyvxo14g=; b=iUGLAyI1aFUcTGeVbnSnONuKfm8dA5uYF1d10RXNuvZ0vDIsaR1yORApJo749A0+hY Y7Xhxx+C3FCP7/kevBRl/WfUjnJKGGJycvDyu8TFD4wqgUBxKck4cWIlOWBiO/YKRoXA CqxjLkgGkcM3n4bB0mzdzD3ibY9F2TVCey0dtm0xzb3PU/m7ew8LGVBtdOU+eoOYAGKJ 82q74X10LZrTFlNT+wNzWaAUUjEgUX2IKmXp5hVF28V/qVfRMHDivvqiZo3tgQCcTmQ0 3sF3iMwoB+ZsORDb9OP4CK8dxZZSTOIlq1VnLeGguUnKQY9kNLf5davjmusqDUDAzUwY MGMw== X-Gm-Message-State: AOAM532wR/FQCGcExx9Pw1xiXt0toHH9MDz2L162jvvk/vHbcuqfv2Ih 2evo9PAAWyzQRBbD9hLaMnY= X-Google-Smtp-Source: ABdhPJxlqipwJQ9qpSdLdWR9vR8UgL2mudNzS6+cjswPnvyZWupMp/FSYK5Kka7xTZSmzhdeJKtKcQ== X-Received: by 2002:aa7:9485:0:b0:44b:b7ff:85bd with SMTP id z5-20020aa79485000000b0044bb7ff85bdmr4603057pfk.20.1632885406703; Tue, 28 Sep 2021 20:16:46 -0700 (PDT) Received: from localhost.localdomain ([156.146.35.76]) by smtp.gmail.com with ESMTPSA id 65sm464203pfv.210.2021.09.28.20.16.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Sep 2021 20:16:46 -0700 (PDT) From: William Breathitt Gray To: jic23@kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, kernel@pengutronix.de, a.fatoum@pengutronix.de, kamel.bouhara@bootlin.com, gwendal@chromium.org, alexandre.belloni@bootlin.com, david@lechnology.com, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, syednwaris@gmail.com, patrick.havelange@essensium.com, fabrice.gasnier@st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, o.rempel@pengutronix.de, jarkko.nikula@linux.intel.com, William Breathitt Gray Subject: [PATCH v17 3/9] docs: counter: Document character device interface Date: Wed, 29 Sep 2021 12:16:00 +0900 Message-Id: <7a71dff2868195901d074ae2ec1b5611838d4b24.1632884256.git.vilhelm.gray@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210928_201647_694539_3815A2C2 X-CRM114-Status: GOOD ( 22.67 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This patch adds high-level documentation about the Counter subsystem character device interface. Signed-off-by: William Breathitt Gray --- Documentation/driver-api/generic-counter.rst | 177 ++++++++++++++---- .../userspace-api/ioctl/ioctl-number.rst | 1 + 2 files changed, 137 insertions(+), 41 deletions(-) diff --git a/Documentation/driver-api/generic-counter.rst b/Documentation/driver-api/generic-counter.rst index f6397218aa4c..25932dcb6e67 100644 --- a/Documentation/driver-api/generic-counter.rst +++ b/Documentation/driver-api/generic-counter.rst @@ -223,19 +223,6 @@ whether an input line is differential or single-ended) and instead focus on the core idea of what the data and process represent (e.g. position as interpreted from quadrature encoding data). -Userspace Interface -=================== - -Several sysfs attributes are generated by the Generic Counter interface, -and reside under the /sys/bus/counter/devices/counterX directory, where -counterX refers to the respective counter device. Please see -Documentation/ABI/testing/sysfs-bus-counter for detailed -information on each Generic Counter interface sysfs attribute. - -Through these sysfs attributes, programs and scripts may interact with -the Generic Counter paradigm Counts, Signals, and Synapses of respective -counter devices. - Driver API ========== @@ -388,16 +375,16 @@ userspace interface components:: / driver callbacks / ------------------- | - +---------------+ - | - V - +--------------------+ - | Counter sysfs | - +--------------------+ - | Translates to the | - | standard Counter | - | sysfs output | - +--------------------+ + +---------------+---------------+ + | | + V V + +--------------------+ +---------------------+ + | Counter sysfs | | Counter chrdev | + +--------------------+ +---------------------+ + | Translates to the | | Translates to the | + | standard Counter | | standard Counter | + | sysfs output | | character device | + +--------------------+ +---------------------+ Thereafter, data can be transferred directly between the Counter device driver and Counter userspace interface:: @@ -428,23 +415,30 @@ driver and Counter userspace interface:: / u64 / ---------- | - +---------------+ - | - V - +--------------------+ - | Counter sysfs | - +--------------------+ - | Translates to the | - | standard Counter | - | sysfs output | - |--------------------| - | Type: const char * | - | Value: "42" | - +--------------------+ - | - --------------- - / const char * / - --------------- + +---------------+---------------+ + | | + V V + +--------------------+ +---------------------+ + | Counter sysfs | | Counter chrdev | + +--------------------+ +---------------------+ + | Translates to the | | Translates to the | + | standard Counter | | standard Counter | + | sysfs output | | character device | + |--------------------| |---------------------| + | Type: const char * | | Type: u64 | + | Value: "42" | | Value: 42 | + +--------------------+ +---------------------+ + | | + --------------- ----------------------- + / const char * / / struct counter_event / + --------------- ----------------------- + | | + | V + | +-----------+ + | | read | + | +-----------+ + | \ Count: 42 / + | ----------- | V +--------------------------------------------------+ @@ -453,7 +447,7 @@ driver and Counter userspace interface:: \ Count: "42" / -------------------------------------------------- -There are three primary components involved: +There are four primary components involved: Counter device driver --------------------- @@ -473,3 +467,104 @@ and vice versa. Please refer to the ``Documentation/ABI/testing/sysfs-bus-counter`` file for a detailed breakdown of the available Generic Counter interface sysfs attributes. + +Counter chrdev +-------------- +Translates Counter events to the standard Counter character device; data +is transferred via standard character device read calls, while Counter +events are configured via ioctl calls. + +Sysfs Interface +=============== + +Several sysfs attributes are generated by the Generic Counter interface, +and reside under the ``/sys/bus/counter/devices/counterX`` directory, +where ``X`` is to the respective counter device id. Please see +``Documentation/ABI/testing/sysfs-bus-counter`` for detailed information +on each Generic Counter interface sysfs attribute. + +Through these sysfs attributes, programs and scripts may interact with +the Generic Counter paradigm Counts, Signals, and Synapses of respective +counter devices. + +Counter Character Device +======================== + +Counter character device nodes are created under the ``/dev`` directory +as ``counterX``, where ``X`` is the respective counter device id. +Defines for the standard Counter data types are exposed via the +userspace ``include/uapi/linux/counter.h`` file. + +Counter events +-------------- +Counter device drivers can support Counter events by utilizing the +``counter_push_event`` function:: + + void counter_push_event(struct counter_device *const counter, const u8 event, + const u8 channel); + +The event id is specified by the ``event`` parameter; the event channel +id is specified by the ``channel`` parameter. When this function is +called, the Counter data associated with the respective event is +gathered, and a ``struct counter_event`` is generated for each datum and +pushed to userspace. + +Counter events can be configured by users to report various Counter +data of interest. This can be conceptualized as a list of Counter +component read calls to perform. For example: + + +------------------------+------------------------+ + | COUNTER_EVENT_OVERFLOW | COUNTER_EVENT_INDEX | + +========================+========================+ + | Channel 0 | Channel 0 | + +------------------------+------------------------+ + | * Count 0 | * Signal 0 | + | * Count 1 | * Signal 0 Extension 0 | + | * Signal 3 | * Extension 4 | + | * Count 4 Extension 2 +------------------------+ + | * Signal 5 Extension 0 | Channel 1 | + | +------------------------+ + | | * Signal 4 | + | | * Signal 4 Extension 0 | + | | * Count 7 | + +------------------------+------------------------+ + +When ``counter_push_event(counter, COUNTER_EVENT_INDEX, 1)`` is called +for example, it will go down the list for the ``COUNTER_EVENT_INDEX`` +event channel 1 and execute the read callbacks for Signal 4, Signal 4 +Extension 0, and Count 7 -- the data returned for each is pushed to a +kfifo as a ``struct counter_event``, which userspace can retrieve via a +standard read operation on the respective character device node. + +Userspace +--------- +Userspace applications can configure Counter events via ioctl operations +on the Counter character device node. There following ioctl codes are +supported and provided by the ``linux/counter.h`` userspace header file: + +* :c:macro:`COUNTER_ADD_WATCH_IOCTL` + +* :c:macro:`COUNTER_ENABLE_EVENTS_IOCTL` + +* :c:macro:`COUNTER_DISABLE_EVENTS_IOCTL` + +To configure events to gather Counter data, users first populate a +``struct counter_watch`` with the relevant event id, event channel id, +and the information for the desired Counter component from which to +read, and then pass it via the ``COUNTER_ADD_WATCH_IOCTL`` ioctl +command. + +Note that an event can be watched without gathering Counter data by +setting the ``component.type`` member equal to +``COUNTER_COMPONENT_NONE``. With this configuration the Counter +character device will simply populate the event timestamps for those +respective ``struct counter_event`` elements and ignore the component +value. + +The ``COUNTER_ADD_WATCH_IOCTL`` command will buffer these Counter +watches. When ready, the ``COUNTER_ENABLE_EVENTS_IOCTL`` ioctl command +may be used to activate these Counter watches. + +Userspace applications can then execute a ``read`` operation (optionally +calling ``poll`` first) on the Counter character device node to retrieve +``struct counter_event`` elements with the desired data. diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 2e8134059c87..0ba463be6c58 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -88,6 +88,7 @@ Code Seq# Include File Comments 0x20 all drivers/cdrom/cm206.h 0x22 all scsi/sg.h +0x3E 00-0F linux/counter.h '!' 00-1F uapi/linux/seccomp.h '#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem From patchwork Wed Sep 29 03:16:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 12524501 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4DC59C433F5 for ; Wed, 29 Sep 2021 03:20:33 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1562361247 for ; Wed, 29 Sep 2021 03:20:33 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 1562361247 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=maVUa96Np65nobrErtKmoXz90YXf3TflOE9aiB/PbYo=; b=tD5/wjNxKAfWpG L5tg7ec+fZkX5Wu2agP0AkfnbVPSHi/mC8vv435CSLXh5Wr7TN+1bWVXLBgO5xhjHw3swsNfFL41Q SawkXeJUpmI6gLnMLERwgMHApQrB5ULC33dHSrrKphFFaI1AtnHFSOW2gMysgMyzfk3Ztm0RFOvOT MgDPu85lW/qvBHdiXq8uueSYbuitUIWFxac+kDTMeWyZP6WicLj8OR3cKls5BdF4JKcg06fskJJB8 lMpGbpOEpdkpDLkFwpQ8kzGJJB0LiLImOcXcmnfvq99igOYo0mT6upkmZ9v1IEhlBEy57ExmBbfpD tfUB2RqCSGYsdN2tOwcQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ6M-009l4t-EE; Wed, 29 Sep 2021 03:17:46 +0000 Received: from mail-pj1-x102d.google.com ([2607:f8b0:4864:20::102d]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5W-009kjE-1b for linux-arm-kernel@lists.infradead.org; Wed, 29 Sep 2021 03:16:56 +0000 Received: by mail-pj1-x102d.google.com with SMTP id v19so600408pjh.2 for ; Tue, 28 Sep 2021 20:16:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=I7q1KZGQrg9VSlOg55Y4jOv+nbaa+ZG4SOxiTCfz7+A=; b=c4YPx4QoCrd0LGbTXbyUsP5aDbIbvZS1byEnV0+QSmllLjdlS/W4H5oVGH5norE9W0 ItSVOzSGjeNvSisYf/MBeAseD5hc17VbXOZIYCBzzJ25BLuybrXTDNGJiEv1977rXPk6 HpgL1kJ/56+u68hhXeRPXEB7Q2XRL+KmwBbRBe80TJPtAuR/CUIo4JCppKW2Iog2SZn9 TdqpoVTP7O/kaeSxl39+wh2O40vLXPzJ9kPUK0eqwjkbmyHc8ZVWNgiCqaUBpEU09wF1 zVvG7dVTjeWzHN8OsiKI64BTT492xjV3h7HjietjExDSiV2NJHFefu+qxjtBRQ5jbbfd jTEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=I7q1KZGQrg9VSlOg55Y4jOv+nbaa+ZG4SOxiTCfz7+A=; b=SUnWnDLnRfLfkOtIB0YPd1S0onJwANl6yjm5HTKAV+5E9CM7Gqhaow4k9N+oKsenk0 SHqjqMNKlnD5IsQOE5tCeDWcVE/IlT8ujWUm/koOi+kD/4iq+VeKBwMCbkR+5gT7sAy+ 5i5fq09fichCzSQKOuGXqatDEdkixviDoL08Hepn3DAtSmqqS6+wJF+2lPKXuOw9YyCC 2AzTa5Rr+fQD0NIyr17A3abOL2O4koUM3OeIAJIMYOPus5itlRTOL42wBvF1VNkV+lwy L9rLzbAV60GvW8wQuHq67C5kx6VqX4R1JVDPAPSPLUQjiB4X1oeriHQyDbdw0Q3ahx3p 9vvA== X-Gm-Message-State: AOAM530zaHS3bHgkw4BRVsTcCqlhegFvdhL0naDl+L7vFQ0ufc/1NaxU Q2ZF98TlqnNvly6IEEUnvt4= X-Google-Smtp-Source: ABdhPJzmH04Xwn/NDpUAahm7FPyOQwWagt9o5ZJv6S5XukOPFvQ917pKQ9XMQmQDLQIV2X98MueLMA== X-Received: by 2002:a17:90a:8912:: with SMTP id u18mr3646172pjn.69.1632885413301; Tue, 28 Sep 2021 20:16:53 -0700 (PDT) Received: from localhost.localdomain ([156.146.35.76]) by smtp.gmail.com with ESMTPSA id 65sm464203pfv.210.2021.09.28.20.16.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Sep 2021 20:16:52 -0700 (PDT) From: William Breathitt Gray To: jic23@kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, kernel@pengutronix.de, a.fatoum@pengutronix.de, kamel.bouhara@bootlin.com, gwendal@chromium.org, alexandre.belloni@bootlin.com, david@lechnology.com, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, syednwaris@gmail.com, patrick.havelange@essensium.com, fabrice.gasnier@st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, o.rempel@pengutronix.de, jarkko.nikula@linux.intel.com, William Breathitt Gray , Pavel Machek Subject: [PATCH v17 4/9] tools/counter: Create Counter tools Date: Wed, 29 Sep 2021 12:16:01 +0900 Message-Id: <7c0f975ba098952122302d258ec9ffdef04befaf.1632884256.git.vilhelm.gray@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210928_201654_131199_001923EA X-CRM114-Status: GOOD ( 24.87 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This creates an example Counter program under tools/counter/* to exemplify the Counter character device interface. Cc: Pavel Machek Signed-off-by: William Breathitt Gray --- MAINTAINERS | 1 + tools/Makefile | 13 ++--- tools/counter/Build | 1 + tools/counter/Makefile | 53 +++++++++++++++++++ tools/counter/counter_example.c | 92 +++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 6 deletions(-) create mode 100644 tools/counter/Build create mode 100644 tools/counter/Makefile create mode 100644 tools/counter/counter_example.c diff --git a/MAINTAINERS b/MAINTAINERS index 3c95ada1b830..71082000046b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4821,6 +4821,7 @@ F: Documentation/driver-api/generic-counter.rst F: drivers/counter/ F: include/linux/counter.h F: include/uapi/linux/counter.h +F: tools/counter/ CP2615 I2C DRIVER M: Bence Csókás diff --git a/tools/Makefile b/tools/Makefile index 7e9d34ddd74c..5da1fde03a9a 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -12,6 +12,7 @@ help: @echo ' acpi - ACPI tools' @echo ' bpf - misc BPF tools' @echo ' cgroup - cgroup tools' + @echo ' counter - counter tools' @echo ' cpupower - a tool for all things x86 CPU power' @echo ' debugging - tools for debugging' @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' @@ -65,7 +66,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -cgroup firewire hv guest bootconfig spi usb virtio vm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE +cgroup counter firewire hv guest bootconfig spi usb virtio vm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE $(call descend,$@) bpf/%: FORCE @@ -100,7 +101,7 @@ freefall: FORCE kvm_stat: FORCE $(call descend,kvm/$@) -all: acpi cgroup cpupower gpio hv firewire liblockdep \ +all: acpi cgroup counter cpupower gpio hv firewire liblockdep \ perf selftests bootconfig spi turbostat usb \ virtio vm bpf x86_energy_perf_policy \ tmon freefall iio objtool kvm_stat wmi \ @@ -112,7 +113,7 @@ acpi_install: cpupower_install: $(call descend,power/$(@:_install=),install) -cgroup_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install: +cgroup_install counter_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install: $(call descend,$(@:_install=),install) liblockdep_install: @@ -133,7 +134,7 @@ freefall_install: kvm_stat_install: $(call descend,kvm/$(@:_install=),install) -install: acpi_install cgroup_install cpupower_install gpio_install \ +install: acpi_install cgroup_install counter_install cpupower_install gpio_install \ hv_install firewire_install iio_install liblockdep_install \ perf_install selftests_install turbostat_install usb_install \ virtio_install vm_install bpf_install x86_energy_perf_policy_install \ @@ -147,7 +148,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -cgroup_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: +cgroup_clean counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: $(call descend,$(@:_clean=),clean) liblockdep_clean: @@ -181,7 +182,7 @@ freefall_clean: build_clean: $(call descend,build,clean) -clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \ +clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_clean \ perf_clean selftests_clean turbostat_clean bootconfig_clean spi_clean usb_clean virtio_clean \ vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ diff --git a/tools/counter/Build b/tools/counter/Build new file mode 100644 index 000000000000..33f4a51d715e --- /dev/null +++ b/tools/counter/Build @@ -0,0 +1 @@ +counter_example-y += counter_example.o diff --git a/tools/counter/Makefile b/tools/counter/Makefile new file mode 100644 index 000000000000..5ebc195fd9c0 --- /dev/null +++ b/tools/counter/Makefile @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0 +include ../scripts/Makefile.include + +bindir ?= /usr/bin + +ifeq ($(srctree),) +srctree := $(patsubst %/,%,$(dir $(CURDIR))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +endif + +# Do not use make's built-in rules +# (this improves performance and avoids hard-to-debug behaviour); +MAKEFLAGS += -r + +override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include + +ALL_TARGETS := counter_example +ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) + +all: $(ALL_PROGRAMS) + +export srctree OUTPUT CC LD CFLAGS +include $(srctree)/tools/build/Makefile.include + +# +# We need the following to be outside of kernel tree +# +$(OUTPUT)include/linux/counter.h: ../../include/uapi/linux/counter.h + mkdir -p $(OUTPUT)include/linux 2>&1 || true + ln -sf $(CURDIR)/../../include/uapi/linux/counter.h $@ + +prepare: $(OUTPUT)include/linux/counter.h + +COUNTER_EXAMPLE := $(OUTPUT)counter_example.o +$(COUNTER_EXAMPLE): prepare FORCE + $(Q)$(MAKE) $(build)=counter_example +$(OUTPUT)counter_example: $(COUNTER_EXAMPLE) + $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ + +clean: + rm -f $(ALL_PROGRAMS) + rm -rf $(OUTPUT)include/linux/counter.h + find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete + +install: $(ALL_PROGRAMS) + install -d -m 755 $(DESTDIR)$(bindir); \ + for program in $(ALL_PROGRAMS); do \ + install $$program $(DESTDIR)$(bindir); \ + done + +FORCE: + +.PHONY: all install clean FORCE prepare diff --git a/tools/counter/counter_example.c b/tools/counter/counter_example.c new file mode 100644 index 000000000000..be55287b950f --- /dev/null +++ b/tools/counter/counter_example.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Counter - example userspace application + * + * The userspace application opens /dev/counter0, configures the + * COUNTER_EVENT_INDEX event channel 0 to gather Count 0 count and Count + * 1 count, and prints out the data as it becomes available on the + * character device node. + * + * Copyright (C) 2021 William Breathitt Gray + */ +#include +#include +#include +#include +#include +#include +#include + +static struct counter_watch watches[2] = { + { + /* Component data: Count 0 count */ + .component.type = COUNTER_COMPONENT_COUNT, + .component.scope = COUNTER_SCOPE_COUNT, + .component.parent = 0, + /* Event type: Index */ + .event = COUNTER_EVENT_INDEX, + /* Device event channel 0 */ + .channel = 0, + }, + { + /* Component data: Count 1 count */ + .component.type = COUNTER_COMPONENT_COUNT, + .component.scope = COUNTER_SCOPE_COUNT, + .component.parent = 1, + /* Event type: Index */ + .event = COUNTER_EVENT_INDEX, + /* Device event channel 0 */ + .channel = 0, + }, +}; + +int main(void) +{ + int fd; + int ret; + int i; + struct counter_event event_data[2]; + + fd = open("/dev/counter0", O_RDWR); + if (fd == -1) { + perror("Unable to open /dev/counter0"); + return 1; + } + + for (i = 0; i < 2; i++) { + ret = ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + i); + if (ret == -1) { + fprintf(stderr, "Error adding watches[%d]: %s\n", i, + strerror(errno)); + return 1; + } + } + ret = ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL); + if (ret == -1) { + perror("Error enabling events"); + return 1; + } + + for (;;) { + ret = read(fd, event_data, sizeof(event_data)); + if (ret == -1) { + perror("Failed to read event data"); + return 1; + } + + if (ret != sizeof(event_data)) { + fprintf(stderr, "Failed to read event data\n"); + return -EIO; + } + + printf("Timestamp 0: %llu\tCount 0: %llu\n" + "Error Message 0: %s\n" + "Timestamp 1: %llu\tCount 1: %llu\n" + "Error Message 1: %s\n", + event_data[0].timestamp, event_data[0].value, + strerror(event_data[0].status), + event_data[1].timestamp, event_data[1].value, + strerror(event_data[1].status)); + } + + return 0; +} From patchwork Wed Sep 29 03:16:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 12524503 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 66A24C433FE for ; Wed, 29 Sep 2021 03:20:35 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2CF1661247 for ; Wed, 29 Sep 2021 03:20:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 2CF1661247 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Fr8EWGbgrMOd/PnZw4+nNUUPUrdn29lcD7PgX6DFv/A=; b=KaOHeKAtPnBoPv WcM5EKepY5pMQodRGPEXcZBMMOwlt9+vviPWhgSsHY4BXVpImD3vrMlIntWTSwxGFCeqMFpRUM4gR xcujHRxDDRVWU7RUOZodlnlMuO5qDnm3+IqdZeUkeFx9BFq936U7S2BZm4mfX4yR9+dTipQTzGR1r m+B/VtMrP2ZEHwQzxqNLLGoFrT/H88VPQQFzcdPUawE0k6eiJmjR45LHtwwNy0k9+Fb8yCEOkO8JX Eq7wzseDY9kQtoeJMyBAZb4siT4Lmi0xd4F3vlqkbEaZmT4lJQIl9cU/jztIT/0SDPpHFyhMF9Mv7 QftbQZQ9v4HTGjbT6Dnw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ6p-009lIE-W4; Wed, 29 Sep 2021 03:18:16 +0000 Received: from mail-pj1-x1031.google.com ([2607:f8b0:4864:20::1031]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5d-009kln-N1 for linux-arm-kernel@lists.infradead.org; Wed, 29 Sep 2021 03:17:03 +0000 Received: by mail-pj1-x1031.google.com with SMTP id k23so621184pji.0 for ; Tue, 28 Sep 2021 20:17:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=IaNorZsjU8hM7wfPjt4kkgWnkshK3kwrpC14sR+dG8Q=; b=MTVhbJ0g2H5Q+y+iwaUM+Bh3FGIN3AqPmcifP/Sor+H7DhGOwW0d9tGv3+DDvgwcy/ fq6kwXM9UFWAnOHeZ4ndeQY8qRMgDmuCVSohk8BOwv4hKUaJE5pPBFICkQwsJBHimGJC QMrlvc4GXCVuNig9YsfSQgGaNuafpLSjFesxO8ou6zgx4oOQ0/mjWpXPlawd73Ckur/S xOWa4GYZqR3N8YIABc8ZCr2IoUKsRjG0vYwRYKL47L/vmYzI6xSv7KcCkr38HUtOZv1i oCRHaL47cSKjBYzBA5+xzlJ94/SgSQ5VgYd9zT0Tg0SzJMcpt4hrwD9oPiJxtG9fxc5j iUBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=IaNorZsjU8hM7wfPjt4kkgWnkshK3kwrpC14sR+dG8Q=; b=po2I5nv1vx4swK+eD5hLq7LyLDDdZr3oNiAQTWBbbexgWk15cdTNDbNSvxHSvCRgSk 3hHDy//reD7fkljetk6fDHalu0jwxJ5sokkBcJz2az0rgFAVxPwyUu2T/8y/dzEGy3ga cKrUUBULXfrNcW+4O8M+xVuqPpCiQ3paBlDikIAM3sIvi+LxMMhjWeqJzBUoWXAdHKYe ZQGDXuZzEczpnaPFaZ3v98dso6Koh5llbvmBHhIWZ+lCQ6lWDG07KKYDCTjysi6ZoIOJ z8TEEmhIB9UfCBxuUAxD6huhZ3MqgPcg7c28AHbWqa6eNIXx9F0C2yDsi+OAzZhicgtT 84cw== X-Gm-Message-State: AOAM531DCjDSLqYMgQPr75aTEW1ask3/d6ZGZWqumj5uaFeqwZmzMaQ8 uyLKPXID0xOh3PFRTAjS1g7uLKep0/0= X-Google-Smtp-Source: ABdhPJxBpjh5/Urwl7VFC61ZKNbPqzhscwCBb5zGrk+2nHYlWmkuEdjJRuRpMBa/oiQGCRPbmsYQnQ== X-Received: by 2002:a17:90b:3143:: with SMTP id ip3mr3964650pjb.50.1632885420262; Tue, 28 Sep 2021 20:17:00 -0700 (PDT) Received: from localhost.localdomain ([156.146.35.76]) by smtp.gmail.com with ESMTPSA id 65sm464203pfv.210.2021.09.28.20.16.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Sep 2021 20:16:59 -0700 (PDT) From: William Breathitt Gray To: jic23@kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, kernel@pengutronix.de, a.fatoum@pengutronix.de, kamel.bouhara@bootlin.com, gwendal@chromium.org, alexandre.belloni@bootlin.com, david@lechnology.com, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, syednwaris@gmail.com, patrick.havelange@essensium.com, fabrice.gasnier@st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, o.rempel@pengutronix.de, jarkko.nikula@linux.intel.com, William Breathitt Gray , Dan Carpenter Subject: [PATCH v17 5/9] counter: Implement signalZ_action_component_id sysfs attribute Date: Wed, 29 Sep 2021 12:16:02 +0900 Message-Id: X-Mailer: git-send-email 2.33.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210928_201701_866709_B6CB59F9 X-CRM114-Status: GOOD ( 14.80 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The Generic Counter chrdev interface expects users to supply component IDs in order to select Synapses for requests. In order for users to know what component ID belongs to which Synapse this information must be exposed. The signalZ_action_component_id attribute provides a way for users to discover what component ID belongs to the respective Synapse. Cc: Gwendal Grignou Cc: Dan Carpenter Reviewed-by: David Lechner Signed-off-by: William Breathitt Gray --- Documentation/ABI/testing/sysfs-bus-counter | 7 ++++ drivers/counter/counter-sysfs.c | 45 +++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter index dee79b606847..aa2cd3c10d74 100644 --- a/Documentation/ABI/testing/sysfs-bus-counter +++ b/Documentation/ABI/testing/sysfs-bus-counter @@ -203,6 +203,13 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/countY/signalZ_action_component_id +KernelVersion: 5.16 +Contact: linux-iio@vger.kernel.org +Description: + Read-only attribute that indicates the component ID of the + respective Synapse of Count Y for Signal Z. + What: /sys/bus/counter/devices/counterX/countY/spike_filter_ns KernelVersion: 5.14 Contact: linux-iio@vger.kernel.org diff --git a/drivers/counter/counter-sysfs.c b/drivers/counter/counter-sysfs.c index 108cbd838eb9..ee7ff1cde454 100644 --- a/drivers/counter/counter-sysfs.c +++ b/drivers/counter/counter-sysfs.c @@ -532,6 +532,46 @@ static int counter_name_attr_create(struct device *const dev, return 0; } +static ssize_t counter_comp_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const size_t id = (size_t)to_counter_attribute(attr)->comp.priv; + + return sprintf(buf, "%zu\n", id); +} + +static int counter_comp_id_attr_create(struct device *const dev, + struct counter_attribute_group *const group, + const char *name, const size_t id) +{ + struct counter_attribute *counter_attr; + + /* Allocate Counter attribute */ + counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL); + if (!counter_attr) + return -ENOMEM; + + /* Generate component ID name */ + name = devm_kasprintf(dev, GFP_KERNEL, "%s_component_id", name); + if (!name) + return -ENOMEM; + + /* Configure Counter attribute */ + counter_attr->comp.priv = (void *)id; + + /* Configure device attribute */ + sysfs_attr_init(&counter_attr->dev_attr.attr); + counter_attr->dev_attr.attr.name = name; + counter_attr->dev_attr.attr.mode = 0444; + counter_attr->dev_attr.show = counter_comp_id_show; + + /* Store list node */ + list_add(&counter_attr->l, &group->attr_list); + group->num_attr++; + + return 0; +} + static struct counter_comp counter_signal_comp = { .type = COUNTER_COMP_SIGNAL_LEVEL, .name = "signal", @@ -626,6 +666,11 @@ static int counter_sysfs_synapses_add(struct counter_device *const counter, COUNTER_SCOPE_COUNT, count); if (err < 0) return err; + + /* Create Synapse component ID attribute */ + err = counter_comp_id_attr_create(dev, group, comp.name, i); + if (err < 0) + return err; } return 0; From patchwork Wed Sep 29 03:16:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 12524505 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32EC1C433F5 for ; Wed, 29 Sep 2021 03:21:05 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 06CF560EBD for ; Wed, 29 Sep 2021 03:21:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 06CF560EBD Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=IRG+d9/AmBBUjP/VxHVmcPzo0IRJyjsbsUjs3UFk4PU=; b=xs/xfj453W/Aej gtOBRIGUDB8BpE3XNZkeMjfYNaNfg49JX2lGMMcVpT/ikNFeyNLwI8Etly3s91dhQSfHFGxjUEOVK 94He/77f1ntyHbkNcgYBROIp/pNESWII9NOmznGrBlvi0qNnFaYeNCWNs79WuG9bsLmEdSEu995Ec xr/xDprqnmNmfz0Vh40KzOsF7G33ncOo/VeMJQKbM0vqiC1uSd90GyHU8rLbiNe2m6kbPxZedXmgt 1WrjdGkUk67kiklkBHJZBoLdVoOVDf8G5xs0jY6HbcTQOV0DZTtXjGCgf/1xbgwcSVMeFjFhmgQlV GpFz5bqSkNzvfu8alsbQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ7B-009lTg-O5; Wed, 29 Sep 2021 03:18:38 +0000 Received: from mail-pg1-x531.google.com ([2607:f8b0:4864:20::531]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5j-009koK-UJ for linux-arm-kernel@lists.infradead.org; Wed, 29 Sep 2021 03:17:09 +0000 Received: by mail-pg1-x531.google.com with SMTP id 133so1273675pgb.1 for ; Tue, 28 Sep 2021 20:17:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=D1ZJzVM7lwJIUvFTpSkZIOwRXzMuWD16wO01xh/53mc=; b=Eap6CAx4EhjI17O4riTzd8BatbHAQKJB3td5qsGjzQ1P2WBoaf53W+uLGS/2vlqd9p /JMv9dQ1rp79u970Xn8+sCOSa+G1vJWRN5vEghw5kefCO9Y4w4nd48EIg2FcgUpsiUxx GSXJv/NCbwtq6rFSjWyvL9EM23hMYaQzTerE2EtIKp5ArkT28UQKh9hsp2itYlLWVaue uTWufBMICftRLLNBabw1FQ8frXvVugTWj6XDNRHf87TjOy/va0Y7uFF5IA03qWSTLFUM OCqs+CYcA6U6v5cGFwEbWb5hzTUK4UGPcq0bGZIEFKtbVT+sgH7Wr20eOmj42juBeMOM H0lQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=D1ZJzVM7lwJIUvFTpSkZIOwRXzMuWD16wO01xh/53mc=; b=uqhC2ZN5u6Z8SopHSUhngnyz8yLt926J2IkOHBVwWB7Gx+FZXuQIxw69oNdgpSfpC0 sL5u2I9k8H31Jo0fTzpQc6p4y0sOxFjwjelR0HKNsPIzA91Q+qLoaSNCSAMEHN6S+bah RHgJcgIgZWDvi+DTCY84XQxarfxGTE2YQWi2Qxf7/FQ91Q97HZMo7/DyOK3q0n9ZX94x 0O+esj1vhwa9CC67AsctskQ1UaCvnZqFzNtYHS+hUbbVaL07S/Y4E6d2Le8fporE7J4N 4BxO6SNKQXZ6rve2JYY+xHXM/h9d/0ms4lp16sJbiU+HGqjcuZKyVmAXwSZ17z1UBgiH fUiQ== X-Gm-Message-State: AOAM533QHtPOfg3bm+yT+wAxsB1zXjf/oLkZuYQH229PaQkEZQGDmebJ Mnu7aXb1MNu0V2vhA9GLJto= X-Google-Smtp-Source: ABdhPJzPOon/US/vY5mpbcPMrdaNb7yZ3ehfzoCcxEbVYLiWOpSPKQNhzQrPBmsjbjU/cfDaTG3/PQ== X-Received: by 2002:a63:8c4d:: with SMTP id q13mr7544469pgn.92.1632885427237; Tue, 28 Sep 2021 20:17:07 -0700 (PDT) Received: from localhost.localdomain ([156.146.35.76]) by smtp.gmail.com with ESMTPSA id 65sm464203pfv.210.2021.09.28.20.17.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Sep 2021 20:17:06 -0700 (PDT) From: William Breathitt Gray To: jic23@kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, kernel@pengutronix.de, a.fatoum@pengutronix.de, kamel.bouhara@bootlin.com, gwendal@chromium.org, alexandre.belloni@bootlin.com, david@lechnology.com, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, syednwaris@gmail.com, patrick.havelange@essensium.com, fabrice.gasnier@st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, o.rempel@pengutronix.de, jarkko.nikula@linux.intel.com, William Breathitt Gray , Dan Carpenter Subject: [PATCH v17 6/9] counter: Implement *_component_id sysfs attributes Date: Wed, 29 Sep 2021 12:16:03 +0900 Message-Id: <8961a11edbb882fc689e468194f5be75f572443e.1632884256.git.vilhelm.gray@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210928_201708_011618_0984AC37 X-CRM114-Status: GOOD ( 15.27 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The Generic Counter chrdev interface expects users to supply component IDs in order to select extensions for requests. In order for users to know what component ID belongs to which extension this information must be exposed. The *_component_id attribute provides a way for users to discover what component ID belongs to which respective extension. Cc: David Lechner Cc: Gwendal Grignou Cc: Dan Carpenter Signed-off-by: William Breathitt Gray --- Documentation/ABI/testing/sysfs-bus-counter | 16 +++++++++- drivers/counter/counter-sysfs.c | 33 +++++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter index aa2cd3c10d74..0ce16669157e 100644 --- a/Documentation/ABI/testing/sysfs-bus-counter +++ b/Documentation/ABI/testing/sysfs-bus-counter @@ -203,12 +203,26 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/countY/ceiling_component_id +What: /sys/bus/counter/devices/counterX/countY/floor_component_id +What: /sys/bus/counter/devices/counterX/countY/count_mode_component_id +What: /sys/bus/counter/devices/counterX/countY/direction_component_id +What: /sys/bus/counter/devices/counterX/countY/enable_component_id +What: /sys/bus/counter/devices/counterX/countY/error_noise_component_id +What: /sys/bus/counter/devices/counterX/countY/prescaler_component_id +What: /sys/bus/counter/devices/counterX/countY/preset_component_id +What: /sys/bus/counter/devices/counterX/countY/preset_enable_component_id What: /sys/bus/counter/devices/counterX/countY/signalZ_action_component_id +What: /sys/bus/counter/devices/counterX/signalY/cable_fault_component_id +What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable_component_id +What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler_component_id +What: /sys/bus/counter/devices/counterX/signalY/index_polarity_component_id +What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode_component_id KernelVersion: 5.16 Contact: linux-iio@vger.kernel.org Description: Read-only attribute that indicates the component ID of the - respective Synapse of Count Y for Signal Z. + respective extension or Synapse. What: /sys/bus/counter/devices/counterX/countY/spike_filter_ns KernelVersion: 5.14 diff --git a/drivers/counter/counter-sysfs.c b/drivers/counter/counter-sysfs.c index ee7ff1cde454..97d8d7c2a2b6 100644 --- a/drivers/counter/counter-sysfs.c +++ b/drivers/counter/counter-sysfs.c @@ -586,6 +586,7 @@ static int counter_signal_attrs_create(struct counter_device *const counter, int err; struct counter_comp comp; size_t i; + struct counter_comp *ext; /* Create main Signal attribute */ comp = counter_signal_comp; @@ -601,8 +602,14 @@ static int counter_signal_attrs_create(struct counter_device *const counter, /* Create an attribute for each extension */ for (i = 0; i < signal->num_ext; i++) { - err = counter_attr_create(dev, cattr_group, signal->ext + i, - scope, signal); + ext = &signal->ext[i]; + + err = counter_attr_create(dev, cattr_group, ext, scope, signal); + if (err < 0) + return err; + + err = counter_comp_id_attr_create(dev, cattr_group, ext->name, + i); if (err < 0) return err; } @@ -693,6 +700,7 @@ static int counter_count_attrs_create(struct counter_device *const counter, int err; struct counter_comp comp; size_t i; + struct counter_comp *ext; /* Create main Count attribute */ comp = counter_count_comp; @@ -717,8 +725,14 @@ static int counter_count_attrs_create(struct counter_device *const counter, /* Create an attribute for each extension */ for (i = 0; i < count->num_ext; i++) { - err = counter_attr_create(dev, cattr_group, count->ext + i, - scope, count); + ext = &count->ext[i]; + + err = counter_attr_create(dev, cattr_group, ext, scope, count); + if (err < 0) + return err; + + err = counter_comp_id_attr_create(dev, cattr_group, ext->name, + i); if (err < 0) return err; } @@ -782,6 +796,7 @@ static int counter_sysfs_attr_add(struct counter_device *const counter, struct device *const dev = &counter->dev; int err; size_t i; + struct counter_comp *ext; /* Add Signals sysfs attributes */ err = counter_sysfs_signals_add(counter, cattr_group); @@ -814,8 +829,14 @@ static int counter_sysfs_attr_add(struct counter_device *const counter, /* Create an attribute for each extension */ for (i = 0; i < counter->num_ext; i++) { - err = counter_attr_create(dev, cattr_group, counter->ext + i, - scope, NULL); + ext = &counter->ext[i]; + + err = counter_attr_create(dev, cattr_group, ext, scope, NULL); + if (err < 0) + return err; + + err = counter_comp_id_attr_create(dev, cattr_group, ext->name, + i); if (err < 0) return err; } From patchwork Wed Sep 29 03:16:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 12524507 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6FFA4C433EF for ; Wed, 29 Sep 2021 03:21:27 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 32FE761247 for ; Wed, 29 Sep 2021 03:21:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 32FE761247 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=NsNRGNvKHGFuBBE0497VXYGOmMNVmoN9dxhvhzPi/Ag=; b=2Iigr1bCczZp5M rv8UchN6YZJTzf7506APhU8WGjIEkOMlS41803uXVGjDbAOuAjCi+exBpTVmuEM9MmHdvGDWeVSGE LRqiKvuw25SZEobUJX7NKOHQcOUV60Exz8FQPNQ1LujI+wUdeLyb3B1/q0SG8zQmcRXm9KLgcQYeh j+oc6tGiqNRmzk8Ks8tfDaDgFVRTeFyWXhOhTS52oyO1GIA6FZn3MSnGjHjsqfMYuedrkzaDX6Fie ccIHi6V/JCrjqNkJFaafTxteRgl27shaABnsevHeTK7JVRhl0HudR5fYfPoaWqMNArCL889jgGD9s FCYk1KzeAv7y1ZGuLPPA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ7a-009lfr-Hz; Wed, 29 Sep 2021 03:19:03 +0000 Received: from mail-pg1-x529.google.com ([2607:f8b0:4864:20::529]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5q-009kqj-Pn for linux-arm-kernel@lists.infradead.org; Wed, 29 Sep 2021 03:17:16 +0000 Received: by mail-pg1-x529.google.com with SMTP id g184so1248943pgc.6 for ; Tue, 28 Sep 2021 20:17:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Qa5ZCeGErb5j0p2Gqn+aZhp7ud7tKxLIEmaMkDpWT38=; b=WSwhqWonIxzhiz2hIT5o4Bkl771G1ArxckUQ0wwGagp13+kfNh05CtLG8edArruzbT kxCL8eaED1mWWn8Piv0OFB3uaqwVATI0bUtipjI4c9cD1/0sf/kf6zHqLVRgfA6OEVv4 XPy1gAfNkNrv78gVhfVUBm2Lm3xntohFqywezofWZ5ccCKVDK+bwSjKUbrCMj8dVY+Yk auCxPyULEjMTkkf2or0ihA+yhjdw+T1PGPNsN3ZOvkzu5lXIg26fgLiD5zxAzGo+agzl Q0YQHSI6UIjid4kBYwHNqI7RGPdhJrRDPEVGCUGZtHE04SqEpgQLE2QHAa/Ke2xL2Zzx OPGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Qa5ZCeGErb5j0p2Gqn+aZhp7ud7tKxLIEmaMkDpWT38=; b=kUZfo+kyz9TC+IQJiBEiUqUWLRo5zZLcmT2BA8Kyxyss7ZAcoJ/OkwzzjS6l+50fTZ n/n9vg9o8LiQl5qJiIOnsDdBkh9fsJ5ZRo4a9FjOpyonhRLY6aw0JXqD4uRMb+cF0iN0 xIksYY4nLDeKXZa4aALuPqXmaABbkGiodK0E9akPfDiI/t+WVpvWQ5VMnIPVC5ap1v+I LYkVYhaLwssCxS0gEoZyduIKs3ooMhsLsf13VueM4EtdUEhgCIPxWmOZgapKJwpoHQlz GJX6obzAXQpDbTBnaon930IifR5O0a2w/qBwvMjpD8OBrAF9SnJKSKyRn5JTlxjYdDeH OujA== X-Gm-Message-State: AOAM532H3G1o0LmGOVWlU/jKdCcZ0ZDKrWIm1gJtOAMAK79ZPBMcEvji RwaJfnV+InFUOzhf31TH1CU= X-Google-Smtp-Source: ABdhPJxpn4EftGQF+8jjmSTtCuQwegWeEb3D4qCNrylx6ekMc7l0pclEY+3TVCKYHjlRUh0cl+Dwzw== X-Received: by 2002:a63:330f:: with SMTP id z15mr7663526pgz.402.1632885434094; Tue, 28 Sep 2021 20:17:14 -0700 (PDT) Received: from localhost.localdomain ([156.146.35.76]) by smtp.gmail.com with ESMTPSA id 65sm464203pfv.210.2021.09.28.20.17.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Sep 2021 20:17:13 -0700 (PDT) From: William Breathitt Gray To: jic23@kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, kernel@pengutronix.de, a.fatoum@pengutronix.de, kamel.bouhara@bootlin.com, gwendal@chromium.org, alexandre.belloni@bootlin.com, david@lechnology.com, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, syednwaris@gmail.com, patrick.havelange@essensium.com, fabrice.gasnier@st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, o.rempel@pengutronix.de, jarkko.nikula@linux.intel.com, William Breathitt Gray Subject: [PATCH v17 7/9] counter: Implement events_queue_size sysfs attribute Date: Wed, 29 Sep 2021 12:16:04 +0900 Message-Id: X-Mailer: git-send-email 2.33.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210928_201714_869004_061B9F0C X-CRM114-Status: GOOD ( 19.22 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The events_queue_size sysfs attribute provides a way for users to dynamically configure the Counter events queue size for the Counter character device interface. The size is in number of struct counter_event data structures. The number of elements will be rounded-up to a power of 2 due to a requirement of the kfifo_alloc function called during reallocation of the queue. Cc: Oleksij Rempel Signed-off-by: William Breathitt Gray --- Documentation/ABI/testing/sysfs-bus-counter | 8 ++++ drivers/counter/counter-sysfs.c | 45 +++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter index 0ce16669157e..06c2b3e27e0b 100644 --- a/Documentation/ABI/testing/sysfs-bus-counter +++ b/Documentation/ABI/testing/sysfs-bus-counter @@ -233,6 +233,14 @@ Description: shorter or equal to configured value are ignored. Value 0 means filter is disabled. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.16 +Contact: linux-iio@vger.kernel.org +Description: + Size of the Counter events queue in number of struct + counter_event data structures. The number of elements will be + rounded-up to a power of 2. + What: /sys/bus/counter/devices/counterX/name KernelVersion: 5.2 Contact: linux-iio@vger.kernel.org diff --git a/drivers/counter/counter-sysfs.c b/drivers/counter/counter-sysfs.c index 97d8d7c2a2b6..1ccd771da25f 100644 --- a/drivers/counter/counter-sysfs.c +++ b/drivers/counter/counter-sysfs.c @@ -3,11 +3,13 @@ * Generic Counter sysfs interface * Copyright (C) 2020 William Breathitt Gray */ +#include #include #include #include #include #include +#include #include #include #include @@ -783,12 +785,49 @@ static int counter_num_counts_read(struct counter_device *counter, u8 *val) return 0; } +static int counter_events_queue_size_read(struct counter_device *counter, + u64 *val) +{ + *val = kfifo_size(&counter->events); + return 0; +} + +static int counter_events_queue_size_write(struct counter_device *counter, + u64 val) +{ + DECLARE_KFIFO_PTR(events, struct counter_event); + int err = 0; + + /* Ensure chrdev is not opened more than 1 at a time */ + if (!atomic_add_unless(&counter->chrdev_lock, 1, 1)) + return -EBUSY; + + /* Allocate new events queue */ + err = kfifo_alloc(&events, val, GFP_KERNEL); + if (err) + goto exit_early; + + /* Swap in new events queue */ + kfifo_free(&counter->events); + counter->events.kfifo = events.kfifo; + +exit_early: + atomic_dec(&counter->chrdev_lock); + + return err; +} + static struct counter_comp counter_num_signals_comp = COUNTER_COMP_DEVICE_U8("num_signals", counter_num_signals_read, NULL); static struct counter_comp counter_num_counts_comp = COUNTER_COMP_DEVICE_U8("num_counts", counter_num_counts_read, NULL); +static struct counter_comp counter_events_queue_size_comp = + COUNTER_COMP_DEVICE_U64("events_queue_size", + counter_events_queue_size_read, + counter_events_queue_size_write); + static int counter_sysfs_attr_add(struct counter_device *const counter, struct counter_attribute_group *cattr_group) { @@ -827,6 +866,12 @@ static int counter_sysfs_attr_add(struct counter_device *const counter, if (err < 0) return err; + /* Create events_queue_size attribute */ + err = counter_attr_create(dev, cattr_group, + &counter_events_queue_size_comp, scope, NULL); + if (err < 0) + return err; + /* Create an attribute for each extension */ for (i = 0; i < counter->num_ext; i++) { ext = &counter->ext[i]; From patchwork Wed Sep 29 03:16:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 12524509 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 87C68C433EF for ; Wed, 29 Sep 2021 03:21:48 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4CBB861247 for ; Wed, 29 Sep 2021 03:21:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 4CBB861247 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=zmHwjdaeiTQPhtapeB88vtSiVYTXZSSR0tZasnQ9tTs=; b=Rv+BSXKw4dTXus N9ZMMgtQmTNfUquSPcL+hJcjKutxuxYDUIO9v330+9D4ZCiRTfNPSkPtVbSW1ltq55wWyFZtkltZ2 BBrwoqOSJjahVxA6v9mi8sngPOPeFcYTG20sxgIppsTKzuwgPZS2z97JxXKBlfpESMqLPqdnd//lf B/VBDf4smO99q1Cdm6jMt66aoxTJiVp6R1TajfOGj0vMIRGFrLaqUuL6C0IxUuevRqmbtZUy5rLYh IEnZcg4YfN2D6qOC5lhzgrZfuDBMWrPfR1GylTIVqcMQIgclZIb4BWoIrC2mMtsIHIwGRmgQeFsM0 J++fOiRFA5JT7Ss2BL3w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ89-009lyK-SU; Wed, 29 Sep 2021 03:19:38 +0000 Received: from mail-pj1-x1033.google.com ([2607:f8b0:4864:20::1033]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ5x-009ktx-0m for linux-arm-kernel@lists.infradead.org; Wed, 29 Sep 2021 03:17:23 +0000 Received: by mail-pj1-x1033.google.com with SMTP id d13-20020a17090ad3cd00b0019e746f7bd4so3230188pjw.0 for ; Tue, 28 Sep 2021 20:17:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=un4t0Or+bzEFMQ1nIp70Y2LnF03E0BrK8C7bdtf+Jz4=; b=k/y9p71fk1LZU98YlSUP2qYOp42oVubGw9BemwOTfIHSm2URivpvxi5L7Y5QapTUS7 2bCnAN+71Ri4hPF7LvMxe5pqeHVLczAvPoTfokNmage8weJ6S3dDCcD3GfxH9VYHtgqL rA3d7Go8zgmKbzCe+WaTW/LyX2ugpKdAQbjYHSqsKtNWOCgPtayv2vMBq8pvcA5c3leF 5x8gSEqqZ1tQaUhdVE7hgA0eKste2ZluG9xJCG4dwtkpB+rNyuwdEwaCiuIiQWAaVEWn Zvh25fQ4fJAh/citDSfuAn5H+PtvyA8mlBVjilBSMMEnmslQs+i2cN56fHnIqXnMKRez W7Wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=un4t0Or+bzEFMQ1nIp70Y2LnF03E0BrK8C7bdtf+Jz4=; b=jI2djgUbnqge7ZYpadG5UdH+6SOMnkGlebjJaPMWurmqr4QdVSyXiQKBZkQyfFbNeD vaeXE3nVrxf6Q0x9joX1mrSxrfweh7iD1B1euO0t1CkOVCvw4+N46CMoRk9Ll0fC/lYz Kg530E9bwsTBb1gzBtAwzKimzPx3tkv/+elA1CJv+futKswKA2Q8duhNlc36nPVXrQn8 e1yTw6RxyUNjO6bIKaoQ7RDD9+ToxjfeQChx6jhgQXYSyPzj9Y7n9kyLidPkfyTZlbOH b5wrbe3dTUz6q+OcgbIrXhxeuV0uZyK0R0Pu0uNQdPt3abCMmtJOHaV4x0OMoksWPUQ2 95WA== X-Gm-Message-State: AOAM530wDtb8m7Jq+q8b0xtaxB0TdCC4wcwnqXwIYHzq8ftSA/AkPt3R lT96kciFiF3MDdLUroRfU5E= X-Google-Smtp-Source: ABdhPJyFfXN42i7WhrfQJ+vmhVTbW6Sayw1xe0FCGkgI3iY4vl0gc1XOIq2dtoEuxK/V3aHfNhGP+A== X-Received: by 2002:a17:902:ba8d:b0:13d:cb44:369c with SMTP id k13-20020a170902ba8d00b0013dcb44369cmr8281400pls.40.1632885440183; Tue, 28 Sep 2021 20:17:20 -0700 (PDT) Received: from localhost.localdomain ([156.146.35.76]) by smtp.gmail.com with ESMTPSA id 65sm464203pfv.210.2021.09.28.20.17.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Sep 2021 20:17:19 -0700 (PDT) From: William Breathitt Gray To: jic23@kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, kernel@pengutronix.de, a.fatoum@pengutronix.de, kamel.bouhara@bootlin.com, gwendal@chromium.org, alexandre.belloni@bootlin.com, david@lechnology.com, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, syednwaris@gmail.com, patrick.havelange@essensium.com, fabrice.gasnier@st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, o.rempel@pengutronix.de, jarkko.nikula@linux.intel.com, William Breathitt Gray Subject: [PATCH v17 8/9] counter: 104-quad-8: Replace mutex with spinlock Date: Wed, 29 Sep 2021 12:16:05 +0900 Message-Id: <3f74491dec66de10d062978bcb7b9c2b3bdea86c.1632884256.git.vilhelm.gray@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210928_201721_127183_033A1A9F X-CRM114-Status: GOOD ( 18.99 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This patch replaces the mutex I/O lock with a spinlock. This is in preparation for a subsequent patch adding IRQ support for 104-QUAD-8 devices; we can't sleep in an interrupt context, so we'll need to use a spinlock instead. Acked-by: Syed Nayyar Waris Signed-off-by: William Breathitt Gray --- drivers/counter/104-quad-8.c | 89 +++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index c587f295d720..a56751bf1e9b 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -16,6 +16,7 @@ #include #include #include +#include #define QUAD8_EXTENT 32 @@ -43,7 +44,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); * @base: base port address of the device */ struct quad8 { - struct mutex lock; + spinlock_t lock; struct counter_device counter; unsigned int fck_prescaler[QUAD8_NUM_COUNTERS]; unsigned int preset[QUAD8_NUM_COUNTERS]; @@ -124,6 +125,7 @@ static int quad8_count_read(struct counter_device *counter, unsigned int flags; unsigned int borrow; unsigned int carry; + unsigned long irqflags; int i; flags = inb(base_offset + 1); @@ -133,7 +135,7 @@ static int quad8_count_read(struct counter_device *counter, /* Borrow XOR Carry effectively doubles count range */ *val = (unsigned long)(borrow ^ carry) << 24; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); /* Reset Byte Pointer; transfer Counter to Output Latch */ outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, @@ -142,7 +144,7 @@ static int quad8_count_read(struct counter_device *counter, for (i = 0; i < 3; i++) *val |= (unsigned long)inb(base_offset) << (8 * i); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -152,13 +154,14 @@ static int quad8_count_write(struct counter_device *counter, { struct quad8 *const priv = counter->priv; const int base_offset = priv->base + 2 * count->id; + unsigned long irqflags; int i; /* Only 24-bit values are supported */ if (val > 0xFFFFFF) return -ERANGE; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); /* Reset Byte Pointer */ outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); @@ -183,7 +186,7 @@ static int quad8_count_write(struct counter_device *counter, /* Reset Error flag */ outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -201,8 +204,9 @@ static int quad8_function_read(struct counter_device *counter, { struct quad8 *const priv = counter->priv; const int id = count->id; + unsigned long irqflags; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); if (priv->quadrature_mode[id]) switch (priv->quadrature_scale[id]) { @@ -219,7 +223,7 @@ static int quad8_function_read(struct counter_device *counter, else *function = COUNTER_FUNCTION_PULSE_DIRECTION; - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -234,10 +238,11 @@ static int quad8_function_write(struct counter_device *counter, unsigned int *const scale = priv->quadrature_scale + id; unsigned int *const synchronous_mode = priv->synchronous_mode + id; const int base_offset = priv->base + 2 * id + 1; + unsigned long irqflags; unsigned int mode_cfg; unsigned int idr_cfg; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); mode_cfg = priv->count_mode[id] << 1; idr_cfg = priv->index_polarity[id] << 1; @@ -272,7 +277,7 @@ static int quad8_function_write(struct counter_device *counter, break; default: /* should never reach this path */ - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return -EINVAL; } } @@ -280,7 +285,7 @@ static int quad8_function_write(struct counter_device *counter, /* Load mode configuration to Counter Mode Register */ outb(QUAD8_CTR_CMR | mode_cfg, base_offset); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -406,9 +411,10 @@ static int quad8_index_polarity_set(struct counter_device *counter, struct quad8 *const priv = counter->priv; const size_t channel_id = signal->id - 16; const int base_offset = priv->base + 2 * channel_id + 1; + unsigned long irqflags; unsigned int idr_cfg = index_polarity << 1; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); idr_cfg |= priv->synchronous_mode[channel_id]; @@ -417,7 +423,7 @@ static int quad8_index_polarity_set(struct counter_device *counter, /* Load Index Control configuration to Index Control Register */ outb(QUAD8_CTR_IDR | idr_cfg, base_offset); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -446,15 +452,16 @@ static int quad8_synchronous_mode_set(struct counter_device *counter, struct quad8 *const priv = counter->priv; const size_t channel_id = signal->id - 16; const int base_offset = priv->base + 2 * channel_id + 1; + unsigned long irqflags; unsigned int idr_cfg = synchronous_mode; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); idr_cfg |= priv->index_polarity[channel_id] << 1; /* Index function must be non-synchronous in non-quadrature mode */ if (synchronous_mode && !priv->quadrature_mode[channel_id]) { - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return -EINVAL; } @@ -463,7 +470,7 @@ static int quad8_synchronous_mode_set(struct counter_device *counter, /* Load Index Control configuration to Index Control Register */ outb(QUAD8_CTR_IDR | idr_cfg, base_offset); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -510,6 +517,7 @@ static int quad8_count_mode_write(struct counter_device *counter, unsigned int count_mode; unsigned int mode_cfg; const int base_offset = priv->base + 2 * count->id + 1; + unsigned long irqflags; /* Map Generic Counter count mode to 104-QUAD-8 count mode */ switch (cnt_mode) { @@ -530,7 +538,7 @@ static int quad8_count_mode_write(struct counter_device *counter, return -EINVAL; } - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); priv->count_mode[count->id] = count_mode; @@ -544,7 +552,7 @@ static int quad8_count_mode_write(struct counter_device *counter, /* Load mode configuration to Counter Mode Register */ outb(QUAD8_CTR_CMR | mode_cfg, base_offset); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -564,9 +572,10 @@ static int quad8_count_enable_write(struct counter_device *counter, { struct quad8 *const priv = counter->priv; const int base_offset = priv->base + 2 * count->id; + unsigned long irqflags; unsigned int ior_cfg; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); priv->ab_enable[count->id] = enable; @@ -575,7 +584,7 @@ static int quad8_count_enable_write(struct counter_device *counter, /* Load I/O control configuration */ outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -626,16 +635,17 @@ static int quad8_count_preset_write(struct counter_device *counter, struct counter_count *count, u64 preset) { struct quad8 *const priv = counter->priv; + unsigned long irqflags; /* Only 24-bit values are supported */ if (preset > 0xFFFFFF) return -ERANGE; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); quad8_preset_register_set(priv, count->id, preset); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -644,8 +654,9 @@ static int quad8_count_ceiling_read(struct counter_device *counter, struct counter_count *count, u64 *ceiling) { struct quad8 *const priv = counter->priv; + unsigned long irqflags; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); /* Range Limit and Modulo-N count modes use preset value as ceiling */ switch (priv->count_mode[count->id]) { @@ -659,7 +670,7 @@ static int quad8_count_ceiling_read(struct counter_device *counter, break; } - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -668,23 +679,24 @@ static int quad8_count_ceiling_write(struct counter_device *counter, struct counter_count *count, u64 ceiling) { struct quad8 *const priv = counter->priv; + unsigned long irqflags; /* Only 24-bit values are supported */ if (ceiling > 0xFFFFFF) return -ERANGE; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); /* Range Limit and Modulo-N count modes use preset value as ceiling */ switch (priv->count_mode[count->id]) { case 1: case 3: quad8_preset_register_set(priv, count->id, ceiling); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return -EINVAL; } @@ -706,12 +718,13 @@ static int quad8_count_preset_enable_write(struct counter_device *counter, { struct quad8 *const priv = counter->priv; const int base_offset = priv->base + 2 * count->id + 1; + unsigned long irqflags; unsigned int ior_cfg; /* Preset enable is active low in Input/Output Control register */ preset_enable = !preset_enable; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); priv->preset_enable[count->id] = preset_enable; @@ -720,7 +733,7 @@ static int quad8_count_preset_enable_write(struct counter_device *counter, /* Load I/O control configuration to Input / Output Control Register */ outb(QUAD8_CTR_IOR | ior_cfg, base_offset); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -731,22 +744,23 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter, { struct quad8 *const priv = counter->priv; const size_t channel_id = signal->id / 2; + unsigned long irqflags; bool disabled; unsigned int status; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); disabled = !(priv->cable_fault_enable & BIT(channel_id)); if (disabled) { - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return -EINVAL; } /* Logic 0 = cable fault */ status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); /* Mask respective channel and invert logic */ *cable_fault = !(status & BIT(channel_id)); @@ -772,9 +786,10 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter, { struct quad8 *const priv = counter->priv; const size_t channel_id = signal->id / 2; + unsigned long irqflags; unsigned int cable_fault_enable; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); if (enable) priv->cable_fault_enable |= BIT(channel_id); @@ -786,7 +801,7 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter, outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -809,8 +824,9 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter, struct quad8 *const priv = counter->priv; const size_t channel_id = signal->id / 2; const int base_offset = priv->base + 2 * channel_id; + unsigned long irqflags; - mutex_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, irqflags); priv->fck_prescaler[channel_id] = prescaler; @@ -822,7 +838,7 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter, outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, base_offset + 1); - mutex_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, irqflags); return 0; } @@ -991,8 +1007,7 @@ static int quad8_probe(struct device *dev, unsigned int id) priv->counter.priv = priv; priv->base = base[id]; - /* Initialize mutex */ - mutex_init(&priv->lock); + spin_lock_init(&priv->lock); /* Reset all counters and disable interrupt function */ outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); From patchwork Wed Sep 29 03:16:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Breathitt Gray X-Patchwork-Id: 12524511 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6FB7C433F5 for ; Wed, 29 Sep 2021 03:22:23 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9680661247 for ; Wed, 29 Sep 2021 03:22:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 9680661247 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=d45jEZaBnKKtvPKsSqFgZbIsBHT26xMC2/KktTvHSek=; b=gPLO0WhRZz0mIO 0nbEUtE4zVzIbV3zDeazOC3lJdks2e+5s5YA89yOBpDl3KFbJJUx/PDCU+ftHqH+TDQ+toxq2f1DS 8zQDZuda1algS5fm0MxV8yRF1DreyOR2J7GWBA/Qe3c/jRGgBoF/GbByEXHrth9U6bCRgg/yGIeTy sAv254WZvUbkkMADMyWDe162n7Yc8H3TPlVLT/ZBhLlK8YtV+uOTxdIwIy3/AMR94WwZ5sBSvwYnU tGq1g/6sRO9NWtp0iihLP7dm0M3FTtXqEj8rCcaBzUsYv4QzobTj/0DPdhJb6/84fIMqCeZ24SnQp x+YMQw/w7EazqyRIzdFw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ8t-009mND-Ej; Wed, 29 Sep 2021 03:20:23 +0000 Received: from mail-pj1-x1029.google.com ([2607:f8b0:4864:20::1029]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mVQ63-009kx5-BW for linux-arm-kernel@lists.infradead.org; Wed, 29 Sep 2021 03:17:30 +0000 Received: by mail-pj1-x1029.google.com with SMTP id ce20-20020a17090aff1400b0019f13f6a749so2932674pjb.4 for ; Tue, 28 Sep 2021 20:17:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=TDIe+6SzlRBeAk6I9k2b0FY8DIbSjAdiy7hAihmXRtA=; b=gPkJ/ezX25B76Kslyr/E8CGjV3awtQstvtTmxzkPgIOOgz4IHs+OO3oi3XR652AHQW 06pMtoicrVSgKCdzNpzZEekz3GmdrHKj3SC1bUrSGub05P3q+9XzjxY3A4mfP0gz1PFA HN5pX+ls1sBwDO2GjyfAVPmOXHO2PRbtXSDozHjs2TbyMBhtzI+H5bP8bjhuV/7VGpKp LSP+nEm+FqpJ8tI7F6xQtSqUrsAWSW4pZEA6+FBQXFUYspRogtYn+sMCj2qh94odrp2u hA1y3smajwVrcAnaYBU/8sAjKeDB2d9Df7HoZBLbVedv+gSwSilRTrriyxrwhMZPGcHJ wOXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=TDIe+6SzlRBeAk6I9k2b0FY8DIbSjAdiy7hAihmXRtA=; b=B8xuFW+cIXJw3YVuZlxtKK21D5lU5chwwjSGUfqMeLsruyvoGz9DSc/FhsvLTpR+Z5 sSNk8bfRo/jIJ5xLW9zgP2V3YDCaJwwEy4I0JNiZdcc8o60BVSQZCVxNz/+0f6kMlzq9 zjqmH/KuJ9Gbk/3zJTv+ERh1vvTjp5WaOE6T6noYP7UWNG6Fsdgb6uilugn7DFNVC24w icFWgQuivq5arlKlVTUAfpzY2TOTIYWrBYZBsfkrq2J11XzvIKM8eBQ8+0ijRPERnm8y LmWj9ffqMwG9eDihej7lihhO+xMaKPUuXCi+gfKF8oNY8fBOC5NTu9/9/KJONZ9jCo5G aWqA== X-Gm-Message-State: AOAM532jOQ3/PDPtSkGcThLNWr1oRTXrsix1nGfQukIiglZOdpSS0DSw Rn7GToxnv5+cyflFXSrFYQE= X-Google-Smtp-Source: ABdhPJzIPYLEGIGj7rLahMd9l3sNYDcVVvDVWLECWppA6wYFaT3WKagrmvqhMz0B9hPIALvhHQ+zqw== X-Received: by 2002:a17:90a:c89:: with SMTP id v9mr3673935pja.71.1632885446541; Tue, 28 Sep 2021 20:17:26 -0700 (PDT) Received: from localhost.localdomain ([156.146.35.76]) by smtp.gmail.com with ESMTPSA id 65sm464203pfv.210.2021.09.28.20.17.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Sep 2021 20:17:26 -0700 (PDT) From: William Breathitt Gray To: jic23@kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com, kernel@pengutronix.de, a.fatoum@pengutronix.de, kamel.bouhara@bootlin.com, gwendal@chromium.org, alexandre.belloni@bootlin.com, david@lechnology.com, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, syednwaris@gmail.com, patrick.havelange@essensium.com, fabrice.gasnier@st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, o.rempel@pengutronix.de, jarkko.nikula@linux.intel.com, William Breathitt Gray Subject: [PATCH v17 9/9] counter: 104-quad-8: Add IRQ support for the ACCES 104-QUAD-8 Date: Wed, 29 Sep 2021 12:16:06 +0900 Message-Id: X-Mailer: git-send-email 2.33.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210928_201727_466360_2FB52B3C X-CRM114-Status: GOOD ( 28.58 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The LSI/CSI LS7266R1 chip provides programmable output via the FLG pins. When interrupts are enabled on the ACCES 104-QUAD-8, they occur whenever FLG1 is active. Four functions are available for the FLG1 signal: Carry, Compare, Carry-Borrow, and Index. Carry: Interrupt generated on active low Carry signal. Carry signal toggles every time the respective channel's counter overflows. Compare: Interrupt generated on active low Compare signal. Compare signal toggles every time respective channel's preset register is equal to the respective channel's counter. Carry-Borrow: Interrupt generated on active low Carry signal and active low Borrow signal. Carry signal toggles every time the respective channel's counter overflows. Borrow signal toggles every time the respective channel's counter underflows. Index: Interrupt generated on active high Index signal. These four functions correspond respectivefly to the following four Counter event types: COUNTER_EVENT_OVERFLOW, COUNTER_EVENT_THRESHOLD, COUNTER_EVENT_OVERFLOW_UNDERFLOW, and COUNTER_EVENT_INDEX. Interrupts push Counter events to event channel X, where 'X' is the respective channel whose FLG1 activated. This patch adds IRQ support for the ACCES 104-QUAD-8. The interrupt line numbers for the devices may be configured via the irq array module parameter. Acked-by: Syed Nayyar Waris Signed-off-by: William Breathitt Gray --- drivers/counter/104-quad-8.c | 167 +++++++++++++++++++++++++++++++++-- drivers/counter/Kconfig | 6 +- 2 files changed, 164 insertions(+), 9 deletions(-) diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index a56751bf1e9b..1cbd60aaed69 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,10 @@ static unsigned int num_quad8; module_param_hw_array(base, uint, ioport, &num_quad8, 0); MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); +static unsigned int irq[max_num_isa_dev(QUAD8_EXTENT)]; +module_param_hw_array(irq, uint, irq, NULL, 0); +MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers"); + #define QUAD8_NUM_COUNTERS 8 /** @@ -38,6 +43,8 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); * @quadrature_scale: array of quadrature mode scale configurations * @ab_enable: array of A and B inputs enable configurations * @preset_enable: array of set_to_preset_on_index attribute configurations + * @irq_trigger: array of current IRQ trigger function configurations + * @next_irq_trigger: array of next IRQ trigger function configurations * @synchronous_mode: array of index function synchronous mode configurations * @index_polarity: array of index function polarity configurations * @cable_fault_enable: differential encoder cable status enable configurations @@ -53,13 +60,17 @@ struct quad8 { unsigned int quadrature_scale[QUAD8_NUM_COUNTERS]; unsigned int ab_enable[QUAD8_NUM_COUNTERS]; unsigned int preset_enable[QUAD8_NUM_COUNTERS]; + unsigned int irq_trigger[QUAD8_NUM_COUNTERS]; + unsigned int next_irq_trigger[QUAD8_NUM_COUNTERS]; unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; unsigned int index_polarity[QUAD8_NUM_COUNTERS]; unsigned int cable_fault_enable; unsigned int base; }; +#define QUAD8_REG_INTERRUPT_STATUS 0x10 #define QUAD8_REG_CHAN_OP 0x11 +#define QUAD8_REG_INDEX_INTERRUPT 0x12 #define QUAD8_REG_INDEX_INPUT_LEVELS 0x16 #define QUAD8_DIFF_ENCODER_CABLE_STATUS 0x17 /* Borrow Toggle flip-flop */ @@ -92,8 +103,8 @@ struct quad8 { #define QUAD8_RLD_CNTR_OUT 0x10 /* Transfer Preset Register LSB to FCK Prescaler */ #define QUAD8_RLD_PRESET_PSC 0x18 -#define QUAD8_CHAN_OP_ENABLE_COUNTERS 0x00 #define QUAD8_CHAN_OP_RESET_COUNTERS 0x01 +#define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04 #define QUAD8_CMR_QUADRATURE_X1 0x08 #define QUAD8_CMR_QUADRATURE_X2 0x10 #define QUAD8_CMR_QUADRATURE_X4 0x18 @@ -378,13 +389,103 @@ static int quad8_action_read(struct counter_device *counter, } } +enum { + QUAD8_EVENT_NONE = -1, + QUAD8_EVENT_CARRY = 0, + QUAD8_EVENT_COMPARE = 1, + QUAD8_EVENT_CARRY_BORROW = 2, + QUAD8_EVENT_INDEX = 3, +}; + +static int quad8_events_configure(struct counter_device *counter) +{ + struct quad8 *const priv = counter->priv; + unsigned long irq_enabled = 0; + unsigned long irqflags; + size_t channel; + unsigned long ior_cfg; + unsigned long base_offset; + + spin_lock_irqsave(&priv->lock, irqflags); + + /* Enable interrupts for the requested channels, disable for the rest */ + for (channel = 0; channel < QUAD8_NUM_COUNTERS; channel++) { + if (priv->next_irq_trigger[channel] == QUAD8_EVENT_NONE) + continue; + + if (priv->irq_trigger[channel] != priv->next_irq_trigger[channel]) { + /* Save new IRQ function configuration */ + priv->irq_trigger[channel] = priv->next_irq_trigger[channel]; + + /* Load configuration to I/O Control Register */ + ior_cfg = priv->ab_enable[channel] | + priv->preset_enable[channel] << 1 | + priv->irq_trigger[channel] << 3; + base_offset = priv->base + 2 * channel + 1; + outb(QUAD8_CTR_IOR | ior_cfg, base_offset); + } + + /* Reset next IRQ trigger function configuration */ + priv->next_irq_trigger[channel] = QUAD8_EVENT_NONE; + + /* Enable IRQ line */ + irq_enabled |= BIT(channel); + } + + outb(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT); + + spin_unlock_irqrestore(&priv->lock, irqflags); + + return 0; +} + +static int quad8_watch_validate(struct counter_device *counter, + const struct counter_watch *watch) +{ + struct quad8 *const priv = counter->priv; + + if (watch->channel > QUAD8_NUM_COUNTERS - 1) + return -EINVAL; + + switch (watch->event) { + case COUNTER_EVENT_OVERFLOW: + if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) + priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_CARRY; + else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_CARRY) + return -EINVAL; + return 0; + case COUNTER_EVENT_THRESHOLD: + if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) + priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_COMPARE; + else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_COMPARE) + return -EINVAL; + return 0; + case COUNTER_EVENT_OVERFLOW_UNDERFLOW: + if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) + priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_CARRY_BORROW; + else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_CARRY_BORROW) + return -EINVAL; + return 0; + case COUNTER_EVENT_INDEX: + if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) + priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_INDEX; + else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_INDEX) + return -EINVAL; + return 0; + default: + return -EINVAL; + } +} + static const struct counter_ops quad8_ops = { .signal_read = quad8_signal_read, .count_read = quad8_count_read, .count_write = quad8_count_write, .function_read = quad8_function_read, .function_write = quad8_function_write, - .action_read = quad8_action_read + .action_read = quad8_action_read, + .events_configure = quad8_events_configure, + .watch_validate = quad8_watch_validate, }; static const char *const quad8_index_polarity_modes[] = { @@ -579,7 +680,8 @@ static int quad8_count_enable_write(struct counter_device *counter, priv->ab_enable[count->id] = enable; - ior_cfg = enable | priv->preset_enable[count->id] << 1; + ior_cfg = enable | priv->preset_enable[count->id] << 1 | + priv->irq_trigger[count->id] << 3; /* Load I/O control configuration */ outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1); @@ -728,7 +830,8 @@ static int quad8_count_preset_enable_write(struct counter_device *counter, priv->preset_enable[count->id] = preset_enable; - ior_cfg = priv->ab_enable[count->id] | preset_enable << 1; + ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 | + priv->irq_trigger[count->id] << 3; /* Load I/O control configuration to Input / Output Control Register */ outb(QUAD8_CTR_IOR | ior_cfg, base_offset); @@ -980,11 +1083,54 @@ static struct counter_count quad8_counts[] = { QUAD8_COUNT(7, "Channel 8 Count") }; +static irqreturn_t quad8_irq_handler(int irq, void *private) +{ + struct quad8 *const priv = private; + const unsigned long base = priv->base; + unsigned long irq_status; + unsigned long channel; + u8 event; + + irq_status = inb(base + QUAD8_REG_INTERRUPT_STATUS); + if (!irq_status) + return IRQ_NONE; + + for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) { + switch (priv->irq_trigger[channel]) { + case QUAD8_EVENT_CARRY: + event = COUNTER_EVENT_OVERFLOW; + break; + case QUAD8_EVENT_COMPARE: + event = COUNTER_EVENT_THRESHOLD; + break; + case QUAD8_EVENT_CARRY_BORROW: + event = COUNTER_EVENT_OVERFLOW_UNDERFLOW; + break; + case QUAD8_EVENT_INDEX: + event = COUNTER_EVENT_INDEX; + break; + default: + /* should never reach this path */ + WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n", + priv->irq_trigger[channel], channel); + continue; + } + + counter_push_event(&priv->counter, event, channel); + } + + /* Clear pending interrupts on device */ + outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base + QUAD8_REG_CHAN_OP); + + return IRQ_HANDLED; +} + static int quad8_probe(struct device *dev, unsigned int id) { struct quad8 *priv; int i, j; unsigned int base_offset; + int err; if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) { dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", @@ -1009,6 +1155,8 @@ static int quad8_probe(struct device *dev, unsigned int id) spin_lock_init(&priv->lock); + /* Reset Index/Interrupt Register */ + outb(0x00, base[id] + QUAD8_REG_INDEX_INTERRUPT); /* Reset all counters and disable interrupt function */ outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); /* Set initial configuration for all counters */ @@ -1035,11 +1183,18 @@ static int quad8_probe(struct device *dev, unsigned int id) outb(QUAD8_CTR_IOR, base_offset + 1); /* Disable index function; negative index polarity */ outb(QUAD8_CTR_IDR, base_offset + 1); + /* Initialize next IRQ trigger function configuration */ + priv->next_irq_trigger[i] = QUAD8_EVENT_NONE; } /* Disable Differential Encoder Cable Status for all channels */ outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS); - /* Enable all counters */ - outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); + /* Enable all counters and enable interrupt function */ + outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base[id] + QUAD8_REG_CHAN_OP); + + err = devm_request_irq(dev, irq[id], quad8_irq_handler, IRQF_SHARED, + priv->counter.name, priv); + if (err) + return err; return devm_counter_register(dev, &priv->counter); } diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index d5d2540b30c2..3dcdb681c4e4 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -23,11 +23,11 @@ config 104_QUAD_8 A counter's respective error flag may be cleared by performing a write operation on the respective count value attribute. Although the 104-QUAD-8 counters have a 25-bit range, only the lower 24 bits may be - set, either directly or via the counter's preset attribute. Interrupts - are not supported by this driver. + set, either directly or via the counter's preset attribute. The base port addresses for the devices may be configured via the base - array module parameter. + array module parameter. The interrupt line numbers for the devices may + be configured via the irq array module parameter. config INTERRUPT_CNT tristate "Interrupt counter driver"