Introduce the Counter character device interface
Subsystems (11)
v11 cover Introduce the Counter character device interface
Changes in v11:
- Migrated Intel QEP to new interface
- Context adjustments made for documentation
I pulled out a lot of bits and pieces to their own patches; hopefully that makes reviewing this patchset much simpler than before. This patchset is also available on my personal public git repo for anyone who wants a quick way to clone:
https://gitlab.com/vilhelmgray/iio/-/tree/counter_chrdev_v11
The patches preceding "counter: Internalize sysfs interface code" are primarily cleanup and fixes that can be picked up and applied now to the IIO tree if so desired. The "counter: Internalize sysfs interface code" patch as well may be considered for pickup because it is relatively safe and makes no changes to the userspace interface.
To summarize the main points of this patchset: there are no changes to the existing Counter sysfs userspace interface; a Counter character device interface is introduced that allows Counter events and associated data to be read() by userspace; the events_configure() and watch_validate() driver callbacks are introduced to support Counter events; and IRQ support is added to the 104-QUAD-8 driver, serving as an example of how to support the new Counter events functionality.
Something that should still be discussed: should the struct counter_event "status" member be 8 bits or 32 bits wide? This member will provide the return status (system error number) of an event operation.
William Breathitt Gray (33):
docs: counter: Consolidate Counter sysfs attributes documentation
docs: counter: Fix spelling
counter: 104-quad-8: Remove pointless comment
counter: 104-quad-8: Return error when invalid mode during
ceiling_write
counter: 104-quad-8: Annotate hardware config module parameter
counter: 104-quad-8: Add const qualifiers for
quad8_preset_register_set
counter: 104-quad-8: Add const qualifier for functions_list array
counter: interrupt-cnt: Add const qualifier for functions_list array
counter: microchip-tcb-capture: Add const qualifier for functions_list
array
counter: stm32-lptimer-cnt: Add const qualifier for functions_list
array
counter: stm32-timer-cnt: Add const qualifier for functions_list array
counter: 104-quad-8: Add const qualifier for actions_list array
counter: ftm-quaddec: Add const qualifier for actions_list array
counter: interrupt-cnt: Add const qualifier for actions_list array
counter: microchip-tcb-capture: Add const qualifier for actions_list
array
counter: stm32-lptimer-cnt: Add const qualifier for actions_list array
counter: stm32-timer-cnt: Add const qualifier for actions_list array
counter: Return error code on invalid modes
counter: Standardize to ERANGE for limit exceeded errors
counter: Rename counter_signal_value to counter_signal_level
counter: Rename counter_count_function to counter_function
counter: Internalize sysfs interface code
counter: Update counter.h comments to reflect sysfs internalization
docs: counter: Update to reflect sysfs internalization
counter: Move counter enums to uapi header
counter: Add character device interface
docs: counter: Document character device interface tools/counter: Create Counter tools
counter: Implement signalZ_action_component_id sysfs attribute
counter: Implement *_component_id sysfs attributes
counter: Implement events_queue_size sysfs attribute
counter: 104-quad-8: Replace mutex with spinlock
counter: 104-quad-8: Add IRQ support for the ACCES 104-QUAD-8
Documentation/ABI/testing/sysfs-bus-counter | 112 +- .../ABI/testing/sysfs-bus-counter-104-quad-8 | 61 - .../ABI/testing/sysfs-bus-counter-ftm-quaddec | 16 - Documentation/driver-api/generic-counter.rst | 368 +++- .../userspace-api/ioctl/ioctl-number.rst | 1 + MAINTAINERS | 7 +- drivers/counter/104-quad-8.c | 739 ++++---- drivers/counter/Kconfig | 6 +- drivers/counter/Makefile | 1 + drivers/counter/counter-chrdev.c | 486 ++++++ drivers/counter/counter-chrdev.h | 14 + drivers/counter/counter-core.c | 192 +++ drivers/counter/counter-sysfs.c | 953 +++++++++++ drivers/counter/counter-sysfs.h | 13 + drivers/counter/counter.c | 1496 ----------------- drivers/counter/ftm-quaddec.c | 61 +- drivers/counter/intel-qep.c | 150 +- drivers/counter/interrupt-cnt.c | 75 +- drivers/counter/microchip-tcb-capture.c | 105 +- drivers/counter/stm32-lptimer-cnt.c | 176 +- drivers/counter/stm32-timer-cnt.c | 149 +- drivers/counter/ti-eqep.c | 221 +-- include/linux/counter.h | 716 ++++---- include/linux/counter_enum.h | 45 - include/uapi/linux/counter.h | 133 ++ tools/Makefile | 13 +- tools/counter/Build | 1 + tools/counter/Makefile | 53 + tools/counter/counter_example.c | 95 ++ 29 files changed, 3586 insertions(+), 2872 deletions(-) delete mode 100644 Documentation/ABI/testing/sysfs-bus-counter-104-quad-8 delete mode 100644 Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec create mode 100644 drivers/counter/counter-chrdev.c create mode 100644 drivers/counter/counter-chrdev.h create mode 100644 drivers/counter/counter-core.c create mode 100644 drivers/counter/counter-sysfs.c create mode 100644 drivers/counter/counter-sysfs.h delete mode 100644 drivers/counter/counter.c delete mode 100644 include/linux/counter_enum.h create mode 100644 include/uapi/linux/counter.h create mode 100644 tools/counter/Build create mode 100644 tools/counter/Makefile create mode 100644 tools/counter/counter_example.c
Signature · 1 line
2.32.0
PATCH v11 1/33 docs: counter: Consolidate Counter sysfs attributes documentation
Duplicate ABIs are not valid, so let's consolidate these sysfs attributes into the main sysfs-bus-counter documentation file.
--- Documentation/ABI/testing/sysfs-bus-counter | 76 ++++++++++++++++++- .../ABI/testing/sysfs-bus-counter-104-quad-8 | 61 --------------- .../ABI/testing/sysfs-bus-counter-ftm-quaddec | 16 ---- MAINTAINERS | 4 +- 4 files changed, 75 insertions(+), 82 deletions(-) delete mode 100644 Documentation/ABI/testing/sysfs-bus-counter-104-quad-8 delete mode 100644 Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec
Documentation/ABI/testing/sysfs-bus-counter +74 -2
@@ -57,6 +57,7 @@ Description: What: /sys/bus/counter/devices/counterX/countY/count_mode_available What: /sys/bus/counter/devices/counterX/countY/error_noise_available What: /sys/bus/counter/devices/counterX/countY/function_available +What: /sys/bus/counter/devices/counterX/countY/prescaler_available What: /sys/bus/counter/devices/counterX/countY/signalZ_action_available KernelVersion: 5.2 Contact: [email protected]
@@ -154,6 +155,15 @@ Description: Count Y. If possible, this should match the name of the respective channel as it appears in the device datasheet. +What: /sys/bus/counter/devices/counterX/countY/prescaler +KernelVersion: 5.2 +Contact: [email protected] +Description: + Configure the prescaler value associated with Count Y. + On the FlexTimer, the counter clock source passes through a + prescaler (i.e. a counter). This acts like a clock + divider. + What: /sys/bus/counter/devices/counterX/countY/preset KernelVersion: 5.2 Contact: [email protected]
@@ -224,11 +234,45 @@ Description: Read-only attribute that indicates the total number of Signals belonging to the Counter. -What: /sys/bus/counter/devices/counterX/signalY/signal +What: /sys/bus/counter/devices/counterX/signalY/cable_fault +KernelVersion: 5.7 +Contact: [email protected] +Description: + Read-only attribute that indicates whether a differential + encoder cable fault (not connected or loose wires) is detected + for the respective channel of Signal Y. Valid attribute values + are boolean. Detection must first be enabled via the + corresponding cable_fault_enable attribute. + +What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable +KernelVersion: 5.7 +Contact: [email protected] +Description: + Whether detection of differential encoder cable faults for the + respective channel of Signal Y is enabled. Valid attribute + values are boolean. + +What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler +KernelVersion: 5.7 +Contact: [email protected] +Description: + Filter clock factor for input Signal Y. This prescaler value + affects the inputs of both quadrature pair signals. + +What: /sys/bus/counter/devices/counterX/signalY/index_polarity KernelVersion: 5.2 Contact: [email protected] Description: - Signal data of Signal Y represented as a string. + Active level of index input Signal Y; irrelevant in + non-synchronous load mode. + +What: /sys/bus/counter/devices/counterX/signalY/index_polarity_available +What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode_available +KernelVersion: 5.2 +Contact: [email protected] +Description: + Discrete set of available values for the respective Signal Y + configuration are listed in this file. What: /sys/bus/counter/devices/counterX/signalY/name KernelVersion: 5.2
@@ -237,3 +281,31 @@ Description: Read-only attribute that indicates the device-specific name of Signal Y. If possible, this should match the name of the respective signal as it appears in the device datasheet. + +What: /sys/bus/counter/devices/counterX/signalY/signal +KernelVersion: 5.2 +Contact: [email protected] +Description: + Signal data of Signal Y represented as a string. + +What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode +KernelVersion: 5.2 +Contact: [email protected] +Description: + Configure the counter associated with Signal Y for + non-synchronous or synchronous load mode. Synchronous load mode + cannot be selected in non-quadrature (Pulse-Direction) clock + mode. + + non-synchronous: + A logic low level is the active level at this index + input. The index function (as enabled via preset_enable) + is performed directly on the active level of the index + input. + + synchronous: + Intended for interfacing with encoder Index output in + quadrature clock mode. The active level is configured + via index_polarity. The index function (as enabled via + preset_enable) is performed synchronously with the + quadrature clock on the active level of the index input.
Documentation/ABI/testing/sysfs-bus-counter-104-quad-8 deleted +0 -61
61 lines not on this page · raw message
Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec deleted +0 -16
@@ -1,16 +0,0 @@ -What: /sys/bus/counter/devices/counterX/countY/prescaler_available -KernelVersion: 5.2 -Contact: [email protected] -Description: - Discrete set of available values for the respective Count Y - configuration are listed in this file. Values are delimited by - newline characters. - -What: /sys/bus/counter/devices/counterX/countY/prescaler -KernelVersion: 5.2 -Contact: [email protected] -Description: - Configure the prescaler value associated with Count Y. - On the FlexTimer, the counter clock source passes through a - prescaler (i.e. a counter). This acts like a clock - divider.
MAINTAINERS +1 -3
@@ -299,7 +299,6 @@ M: William Breathitt Gray <[email protected]> M: Syed Nayyar Waris <[email protected]> L: [email protected] S: Maintained -F: Documentation/ABI/testing/sysfs-bus-counter-104-quad-8 F: drivers/counter/104-quad-8.c ACCES PCI-IDIO-16 GPIO DRIVER
@@ -4675,7 +4674,7 @@ COUNTER SUBSYSTEM M: William Breathitt Gray <[email protected]> L: [email protected] S: Maintained -F: Documentation/ABI/testing/sysfs-bus-counter* +F: Documentation/ABI/testing/sysfs-bus-counter F: Documentation/driver-api/generic-counter.rst F: drivers/counter/ F: include/linux/counter.h
@@ -7087,7 +7086,6 @@ FLEXTIMER FTM-QUADDEC DRIVER M: Patrick Havelange <[email protected]> L: [email protected] S: Maintained -F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt F: drivers/counter/ftm-quaddec.c
Signature · 1 line
2.32.0
Jonathan Cameron
maintainerRe: [PATCH v11 01/33] docs: counter: Consolidate Counter sysfs attributes documentation
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:04 +0900 William Breathitt Gray…
Duplicate ABIs are not valid, so let's consolidate these sysfs attributes into the main sysfs-bus-counter documentation file.
Cc Patrick Havelange <[email protected]>Reviewed-by David Lechner <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied to the togreg branch of iio.git and pushed out as testing for the autobuilders to see if they find anything that we missed.
Thanks,
Jonathan
Quoted 235 lines
--- Documentation/ABI/testing/sysfs-bus-counter | 76 ++++++++++++++++++- .../ABI/testing/sysfs-bus-counter-104-quad-8 | 61 --------------- .../ABI/testing/sysfs-bus-counter-ftm-quaddec | 16 ---- MAINTAINERS | 4 +- 4 files changed, 75 insertions(+), 82 deletions(-) delete mode 100644 Documentation/ABI/testing/sysfs-bus-counter-104-quad-8 delete mode 100644 Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddecDocumentation/ABI/testing/sysfs-bus-counter +74
-2@@ -57,6 +57,7 @@ Description: What: /sys/bus/counter/devices/counterX/countY/count_mode_available What: /sys/bus/counter/devices/counterX/countY/error_noise_available What: /sys/bus/counter/devices/counterX/countY/function_available +What: /sys/bus/counter/devices/counterX/countY/prescaler_available What: /sys/bus/counter/devices/counterX/countY/signalZ_action_available KernelVersion: 5.2 Contact: [email protected]@@ -154,6 +155,15 @@ Description: Count Y. If possible, this should match the name of the respective channel as it appears in the device datasheet. +What: /sys/bus/counter/devices/counterX/countY/prescaler +KernelVersion: 5.2 +Contact: [email protected] +Description: + Configure the prescaler value associated with Count Y. + On the FlexTimer, the counter clock source passes through a + prescaler (i.e. a counter). This acts like a clock + divider. + What: /sys/bus/counter/devices/counterX/countY/preset KernelVersion: 5.2 Contact: [email protected]@@ -224,11 +234,45 @@ Description: Read-only attribute that indicates the total number of Signals belonging to the Counter. -What: /sys/bus/counter/devices/counterX/signalY/signal +What: /sys/bus/counter/devices/counterX/signalY/cable_fault +KernelVersion: 5.7 +Contact: [email protected] +Description: + Read-only attribute that indicates whether a differential + encoder cable fault (not connected or loose wires) is detected + for the respective channel of Signal Y. Valid attribute values + are boolean. Detection must first be enabled via the + corresponding cable_fault_enable attribute. + +What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable +KernelVersion: 5.7 +Contact: [email protected] +Description: + Whether detection of differential encoder cable faults for the + respective channel of Signal Y is enabled. Valid attribute + values are boolean. + +What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler +KernelVersion: 5.7 +Contact: [email protected] +Description: + Filter clock factor for input Signal Y. This prescaler value + affects the inputs of both quadrature pair signals. + +What: /sys/bus/counter/devices/counterX/signalY/index_polarity KernelVersion: 5.2 Contact: [email protected] Description: - Signal data of Signal Y represented as a string. + Active level of index input Signal Y; irrelevant in + non-synchronous load mode. + +What: /sys/bus/counter/devices/counterX/signalY/index_polarity_available +What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode_available +KernelVersion: 5.2 +Contact: [email protected] +Description: + Discrete set of available values for the respective Signal Y + configuration are listed in this file. What: /sys/bus/counter/devices/counterX/signalY/name KernelVersion: 5.2@@ -237,3 +281,31 @@ Description: Read-only attribute that indicates the device-specific name of Signal Y. If possible, this should match the name of the respective signal as it appears in the device datasheet. + +What: /sys/bus/counter/devices/counterX/signalY/signal +KernelVersion: 5.2 +Contact: [email protected] +Description: + Signal data of Signal Y represented as a string. + +What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode +KernelVersion: 5.2 +Contact: [email protected] +Description: + Configure the counter associated with Signal Y for + non-synchronous or synchronous load mode. Synchronous load mode + cannot be selected in non-quadrature (Pulse-Direction) clock + mode. + + non-synchronous: + A logic low level is the active level at this index + input. The index function (as enabled via preset_enable) + is performed directly on the active level of the index + input. + + synchronous: + Intended for interfacing with encoder Index output in + quadrature clock mode. The active level is configured + via index_polarity. The index function (as enabled via + preset_enable) is performed synchronously with the + quadrature clock on the active level of the index input.Documentation/ABI/testing/sysfs-bus-counter-104-quad-8 deleted +0
-61@@ -1,61 +0,0 @@ -What: /sys/bus/counter/devices/counterX/signalY/cable_fault -KernelVersion: 5.7 -Contact: [email protected] -Description: - Read-only attribute that indicates whether a differential - encoder cable fault (not connected or loose wires) is detected - for the respective channel of Signal Y. Valid attribute values - are boolean. Detection must first be enabled via the - corresponding cable_fault_enable attribute. - -What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable -KernelVersion: 5.7 -Contact: [email protected] -Description: - Whether detection of differential encoder cable faults for the - respective channel of Signal Y is enabled. Valid attribute - values are boolean. - -What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler -KernelVersion: 5.7 -Contact: [email protected] -Description: - Filter clock factor for input Signal Y. This prescaler value - affects the inputs of both quadrature pair signals. - -What: /sys/bus/counter/devices/counterX/signalY/index_polarity -KernelVersion: 5.2 -Contact: [email protected] -Description: - Active level of index input Signal Y; irrelevant in - non-synchronous load mode. - -What: /sys/bus/counter/devices/counterX/signalY/index_polarity_available -What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode_available -KernelVersion: 5.2 -Contact: [email protected] -Description: - Discrete set of available values for the respective Signal Y - configuration are listed in this file. - -What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode -KernelVersion: 5.2 -Contact: [email protected] -Description: - Configure the counter associated with Signal Y for - non-synchronous or synchronous load mode. Synchronous load mode - cannot be selected in non-quadrature (Pulse-Direction) clock - mode. - - non-synchronous: - A logic low level is the active level at this index - input. The index function (as enabled via preset_enable) - is performed directly on the active level of the index - input. - - synchronous: - Intended for interfacing with encoder Index output in - quadrature clock mode. The active level is configured - via index_polarity. The index function (as enabled via - preset_enable) is performed synchronously with the - quadrature clock on the active level of the index input.Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec deleted +0
-16@@ -1,16 +0,0 @@ -What: /sys/bus/counter/devices/counterX/countY/prescaler_available -KernelVersion: 5.2 -Contact: [email protected] -Description: - Discrete set of available values for the respective Count Y - configuration are listed in this file. Values are delimited by - newline characters. - -What: /sys/bus/counter/devices/counterX/countY/prescaler -KernelVersion: 5.2 -Contact: [email protected] -Description: - Configure the prescaler value associated with Count Y. - On the FlexTimer, the counter clock source passes through a - prescaler (i.e. a counter). This acts like a clock - divider.MAINTAINERS +1
-3@@ -299,7 +299,6 @@ M: William Breathitt Gray <[email protected]> M: Syed Nayyar Waris <[email protected]> L: [email protected] S: Maintained -F: Documentation/ABI/testing/sysfs-bus-counter-104-quad-8 F: drivers/counter/104-quad-8.c ACCES PCI-IDIO-16 GPIO DRIVER@@ -4675,7 +4674,7 @@ COUNTER SUBSYSTEM M: William Breathitt Gray <[email protected]> L: [email protected] S: Maintained -F: Documentation/ABI/testing/sysfs-bus-counter* +F: Documentation/ABI/testing/sysfs-bus-counter F: Documentation/driver-api/generic-counter.rst F: drivers/counter/ F: include/linux/counter.h@@ -7087,7 +7086,6 @@ FLEXTIMER FTM-QUADDEC DRIVER M: Patrick Havelange <[email protected]> L: [email protected] S: Maintained -F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt F: drivers/counter/ftm-quaddec.c
PATCH v11 2/33 docs: counter: Fix spelling
In reply to William Breathitt Gray"Miscellaneous" is the correct spelling.
--- Documentation/driver-api/generic-counter.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/driver-api/generic-counter.rst +1 -1
@@ -307,7 +307,7 @@ Determining the type of extension to create is a matter of scope. * Device extensions are attributes that expose information/control non-specific to a particular Count or Signal. This is where you would - put your global features or other miscellanous functionality. + put your global features or other miscellaneous functionality. For example, if your device has an overtemp sensor, you can report the chip overheated via a device extension called "error_overtemp":
Signature · 1 line
2.32.0
Re: [PATCH v11 02/33] docs: counter: Fix spelling
Quoted 4 lines · On Wed, 9 Jun 2021 10:31:05 +0900 William Breathitt Gray…
"Miscellaneous" is the correct spelling.
Reviewed-by David Lechner <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied.
Quoted 17 lines
--- Documentation/driver-api/generic-counter.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)Documentation/driver-api/generic-counter.rst +1
-1@@ -307,7 +307,7 @@ Determining the type of extension to create is a matter of scope. * Device extensions are attributes that expose information/control non-specific to a particular Count or Signal. This is where you would - put your global features or other miscellanous functionality. + put your global features or other miscellaneous functionality. For example, if your device has an overtemp sensor, you can report the chip overheated via a device extension called "error_overtemp":
PATCH v11 3/33 counter: 104-quad-8: Remove pointless comment
In reply to William Breathitt GrayIt is obvious that devm_counter_register() is used to register a Counter device, so a comment stating such is pointless here.
--- drivers/counter/104-quad-8.c | 1 - 1 file changed, 1 deletion(-)
drivers/counter/104-quad-8.c +0 -1
@@ -1082,7 +1082,6 @@ static int quad8_probe(struct device *dev, unsigned int id)/* Enable all counters */ outb (QUAD8_CHAN_OP_ENABLE_COUNTERS , base[id] +QUAD8_REG_CHAN_OP ); -/* Register Counter device */ return devm_counter_register (dev, &priv->counter); }
Signature · 1 line
2.32.0
Re: [PATCH v11 03/33] counter: 104-quad-8: Remove pointless comment
Quoted 5 lines · On Wed, 9 Jun 2021 10:31:06 +0900 William Breathitt Gray…
It is obvious that
devm_counter_register()is used to register a Counter device, so a comment stating such is pointless here.Signed-off-by William Breathitt Gray <[email protected]>
Applied.
Quoted 16 lines
--- drivers/counter/104-quad-8.c | 1 - 1 file changed, 1 deletion(-)drivers/counter/104-quad-8.c +0
-1@@ -1082,7 +1082,6 @@ static int quad8_probe(struct device *dev, unsigned int id)/* Enable all counters */ outb (QUAD8_CHAN_OP_ENABLE_COUNTERS , base[id] +QUAD8_REG_CHAN_OP ); -/* Register Counter device */ return devm_counter_register (dev, &priv->counter); }
PATCH v11 4/33 counter: 104-quad-8: Return error when invalid mode during ceiling_write
In reply to William Breathitt GrayThe 104-QUAD-8 only has two count modes where a ceiling value makes
sense: Range Limit and Modulo-N. Outside of these two modes, setting a ceiling value is an invalid operation -- so let's report it as such by returning -EINVAL.
--- drivers/counter/104-quad-8.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/counter/104-quad-8.c +3 -2
@@ -714,13 +714,14 @@ static ssize_t quad8_count_ceiling_write(struct counter_device *counter,switch (priv->count_mode[count->id]) {case 1 :case 3 : +mutex_unlock (&priv->lock);quad8_preset_register_set (priv, count->id, ceiling); -break ; +return len; }mutex_unlock (&priv->lock); -return len; +return -EINVAL ; } static ssize_t quad8_count_preset_enable_read(struct counter_device *counter,
Signature · 1 line
2.32.0
Jonathan Cameron
maintainerRe: [PATCH v11 04/33] counter: 104-quad-8: Return error when invalid mode during ceiling_write
Quoted 8 lines · On Wed, 9 Jun 2021 10:31:07 +0900 William Breathitt Gray…
The 104-QUAD-8 only has two count modes where a ceiling value makes
sense: Range Limit and Modulo-N. Outside of these two modes, setting a ceiling value is an invalid operation -- so let's report it as such by returning-EINVAL.Fixes fc069262261c ("counter: 104-quad-8: Add lock guards - generic interface")Signed-off-by William Breathitt Gray <[email protected]>
We seem to have some inconsistency in the driver about whether we hold the priv->lock when calling quad8_preset_register_set()
Can we look to make that consistent?
drivers/counter/104-quad-8.c static ssize_t quad8_count_ceiling_write(struct counter_device *counter, · line 717
Quoted 13 lines
--- drivers/counter/104-quad-8.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)drivers/counter/104-quad-8.c +1
-0@@ -714,13 +714,14 @@ static ssize_t quad8_count_ceiling_write(struct counter_device *counter,switch (priv->count_mode[count->id]) {case 1 :case 3 : +mutex_unlock (&priv->lock);
Probably swap this line and the next one...]
Quoted 12 lines
drivers/counter/104-quad-8.c +2
-2quad8_preset_register_set (priv, count->id, ceiling); -break ; +return len; }mutex_unlock (&priv->lock); -return len; +return -EINVAL ; } static ssize_t quad8_count_preset_enable_read(struct counter_device *counter,
Re: [PATCH v11 04/33] counter: 104-quad-8: Return error when invalid mode during ceiling_write
Quoted 8 lines · Jonathan Cameron
Quoted 5 lines · On Wed, 9 Jun 2021 10:31:07 +0900 William Breathitt Gray…
The 104-QUAD-8 only has two count modes where a ceiling value makes
sense: Range Limit and Modulo-N. Outside of these two modes, setting a ceiling value is an invalid operation -- so let's report it as such by returning-EINVAL.
Quoted 8 lines
Quoted 3 lines
Fixes fc069262261c ("counter: 104-quad-8: Add lock guards - generic interface")Signed-off-by William Breathitt Gray <[email protected]>We seem to have some inconsistency in the driver about whether we hold the
priv->lockwhen callingquad8_preset_register_set()Can we look to make that consistent?
We do need to hold the lock when calling quad8_preset_register_set() lest priv->preset goes out of sync with the device state.
Syed, if you have no objections I'll adjust this in the next version.
William Breathitt Gray
Quoted 29 lines
drivers/counter/104-quad-8.c static ssize_t quad8_count_ceiling_write(struct counter_device *counter, · line 717
Quoted 13 lines
--- drivers/counter/104-quad-8.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)drivers/counter/104-quad-8.c +1
-0@@ -714,13 +714,14 @@ static ssize_t quad8_count_ceiling_write(struct counter_device *counter,switch (priv->count_mode[count->id]) {case 1 :case 3 : +mutex_unlock (&priv->lock);Probably swap this line and the next one...]
Quoted 12 lines
drivers/counter/104-quad-8.c +2
-2quad8_preset_register_set (priv, count->id, ceiling); -break ; +return len; }mutex_unlock (&priv->lock); -return len; +return -EINVAL ; } static ssize_t quad8_count_preset_enable_read(struct counter_device *counter,
PATCH v11 5/33 counter: 104-quad-8: Annotate hardware config module parameter
In reply to William Breathitt GrayWhen the kernel is running in secure boot mode, we lock down the kernel to prevent userspace from modifying the running kernel image. Whilst this includes prohibiting access to things like /dev/mem, it must also prevent access by means of configuring driver modules in such a way as to cause a device to access or modify the kernel image.
To this end, annotate module_param* statements that refer to hardware configuration and indicate for future reference what type of parameter they specify. The parameter parser in the core sees this information and can skip such parameters with an error message if the kernel is locked down. The module initialisation then runs as normal, but just sees whatever the default values for those parameters is.
Note that we do still need to do the module initialisation because some drivers have viable defaults set in case parameters aren't specified and some drivers support automatic configuration (e.g. PNP or PCI) in addition to manually coded parameters.
This patch annotates the 104-QUAD-8 driver.
--- drivers/counter/104-quad-8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/104-quad-8.c +1 -1
@@ -21,7 +21,7 @@static unsigned int base[max_num_isa_dev (QUAD8_EXTENT )];static unsigned int num_quad8; -module_param_array (base, uint, &num_quad8,0 ); +module_param_hw_array (base, uint, ioport, &num_quad8,0 );MODULE_PARM_DESC (base,"ACCES 104-QUAD-8 base addresses" );#define QUAD8_NUM_COUNTERS 8
Signature · 1 line
2.32.0
Jonathan Cameron
maintainerRe: [PATCH v11 05/33] counter: 104-quad-8: Annotate hardware config module parameter
Quoted 18 lines · On Wed, 9 Jun 2021 10:31:08 +0900 William Breathitt Gray…
When the kernel is running in secure boot mode, we lock down the kernel to prevent userspace from modifying the running kernel image. Whilst this includes prohibiting access to things like
/dev/mem, it must also prevent access by means of configuring driver modules in such a way as to cause a device to access or modify the kernel image.To this end, annotate module_param* statements that refer to hardware configuration and indicate for future reference what type of parameter they specify. The parameter parser in the core sees this information and can skip such parameters with an error message if the kernel is locked down. The module initialisation then runs as normal, but just sees whatever the default values for those parameters is.
Note that we do still need to do the module initialisation because some drivers have viable defaults set in case parameters aren't specified and some drivers support automatic configuration (e.g. PNP or PCI) in addition to manually coded parameters.
Quoted 4 lines
This patch annotates the 104-QUAD-8 driver.
Signed-off-by William Breathitt Gray <[email protected]>
As this has no dependency on patch 4, I've applied it.
Applied to the togreg branch of iio.git and pushed out as testing for the autobuilders to poke at it.
Thanks,
Jonathan
Quoted 17 lines
--- drivers/counter/104-quad-8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/104-quad-8.c +1
-1@@ -21,7 +21,7 @@static unsigned int base[max_num_isa_dev (QUAD8_EXTENT )];static unsigned int num_quad8; -module_param_array (base, uint, &num_quad8,0 ); +module_param_hw_array (base, uint, ioport, &num_quad8,0 );MODULE_PARM_DESC (base,"ACCES 104-QUAD-8 base addresses" );#define QUAD8_NUM_COUNTERS 8
PATCH v11 6/33 counter: 104-quad-8: Add const qualifiers for quad8_preset_register_set
In reply to William Breathitt GrayAdd some safety by qualifying the quad8_preset_register_set() function parameters as const.
--- drivers/counter/104-quad-8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/counter/104-quad-8.c +2 -2
@@ -632,8 +632,8 @@ static ssize_t quad8_count_preset_read(struct counter_device *counter,return sprintf (buf,"%u\n" , priv->preset[count->id]); } -static void quad8_preset_register_set (struct quad8 *priv,int id, -unsigned int preset) +static void quad8_preset_register_set (struct quad8 *const priv,const int id, +const unsigned int preset) {const unsigned int base_offset = priv->base +2 * id;int i;
Signature · 1 line
2.32.0
Re: [PATCH v11 06/33] counter: 104-quad-8: Add const qualifiers for quad8_preset_register_set
Quoted 5 lines · On Wed, 9 Jun 2021 10:31:09 +0900 William Breathitt Gray…
Add some safety by qualifying the
quad8_preset_register_set()function parameters as const.Signed-off-by William Breathitt Gray <[email protected]>
Applied
(no clash with patch 4)
Quoted 19 lines
--- drivers/counter/104-quad-8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/counter/104-quad-8.c +2
-2@@ -632,8 +632,8 @@ static ssize_t quad8_count_preset_read(struct counter_device *counter,return sprintf (buf,"%u\n" , priv->preset[count->id]); } -static void quad8_preset_register_set (struct quad8 *priv,int id, -unsigned int preset) +static void quad8_preset_register_set (struct quad8 *const priv,const int id, +const unsigned int preset) {const unsigned int base_offset = priv->base +2 * id;int i;
PATCH v11 7/33 counter: 104-quad-8: Add const qualifier for functions_list array
In reply to William Breathitt GrayThe struct counter_count functions_list member expects a const enum counter_count_function array. This patch adds the const qualifier to the quad8_count_functions_list to match functions_list.
--- drivers/counter/104-quad-8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/104-quad-8.c +1 -1
@@ -193,7 +193,7 @@ enum quad8_count_function {QUAD8_COUNT_FUNCTION_QUADRATURE_X4 }; -static enum counter_count_function quad8_count_functions_list[] = { +static const enum counter_count_function quad8_count_functions_list[] = { [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION ] =COUNTER_COUNT_FUNCTION_PULSE_DIRECTION , [QUAD8_COUNT_FUNCTION_QUADRATURE_X1 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A , [QUAD8_COUNT_FUNCTION_QUADRATURE_X2 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A ,
Signature · 1 line
2.32.0
Re: [PATCH v11 07/33] counter: 104-quad-8: Add const qualifier for functions_list array
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:10 +0900 William Breathitt Gray…
The struct
counter_countfunctions_listmember expects a const enumcounter_count_functionarray. This patch adds the const qualifier to thequad8_count_functions_listto matchfunctions_list.Signed-off-by William Breathitt Gray <[email protected]>
Applied,
Quoted 17 lines
--- drivers/counter/104-quad-8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/104-quad-8.c +1
-1@@ -193,7 +193,7 @@ enum quad8_count_function {QUAD8_COUNT_FUNCTION_QUADRATURE_X4 }; -static enum counter_count_function quad8_count_functions_list[] = { +static const enum counter_count_function quad8_count_functions_list[] = { [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION ] =COUNTER_COUNT_FUNCTION_PULSE_DIRECTION , [QUAD8_COUNT_FUNCTION_QUADRATURE_X1 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A , [QUAD8_COUNT_FUNCTION_QUADRATURE_X2 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A ,
PATCH v11 8/33 counter: interrupt-cnt: Add const qualifier for functions_list array
In reply to William Breathitt GrayThe struct counter_count functions_list member expects a const enum counter_count_function array. This patch adds the const qualifier to the interrupt__cnt_functions to match functions_list.
--- drivers/counter/interrupt-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/interrupt-cnt.c +1 -1
@@ -112,7 +112,7 @@ static int interrupt_cnt_write(struct counter_device *counter,return 0 ; } -static enum counter_count_function interrupt_cnt_functions[] = { +static const enum counter_count_function interrupt_cnt_functions[] = {COUNTER_COUNT_FUNCTION_INCREASE , };
Signature · 1 line
2.32.0
Re: [PATCH v11 08/33] counter: interrupt-cnt: Add const qualifier for functions_list array
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:11 +0900 William Breathitt Gray…
The struct
counter_countfunctions_listmember expects a const enumcounter_count_functionarray. This patch adds the const qualifier to theinterrupt__cnt_functionsto matchfunctions_list.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied
Quoted 17 lines
--- drivers/counter/interrupt-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/interrupt-cnt.c +1
-1@@ -112,7 +112,7 @@ static int interrupt_cnt_write(struct counter_device *counter,return 0 ; } -static enum counter_count_function interrupt_cnt_functions[] = { +static const enum counter_count_function interrupt_cnt_functions[] = {COUNTER_COUNT_FUNCTION_INCREASE , };
PATCH v11 9/33 counter: microchip-tcb-capture: Add const qualifier for functions_list array
In reply to William Breathitt GrayThe struct counter_count functions_list member expects a const enum counter_count_function array. This patch adds the const qualifier to the mchp_tc_count_functions to match functions_list.
--- drivers/counter/microchip-tcb-capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/microchip-tcb-capture.c +1 -1
@@ -37,7 +37,7 @@ enum mchp_tc_count_function { MCHP_TC_FUNCTION_QUADRATURE, }; -static enum counter_count_function mchp_tc_count_functions[] = { +static const enum counter_count_function mchp_tc_count_functions[] = { [MCHP_TC_FUNCTION_INCREASE ] =COUNTER_COUNT_FUNCTION_INCREASE , [MCHP_TC_FUNCTION_QUADRATURE ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X4 , };
Signature · 1 line
2.32.0
Re: [PATCH v11 09/33] counter: microchip-tcb-capture: Add const qualifier for functions_list array
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:12 +0900 William Breathitt Gray…
The struct
counter_countfunctions_listmember expects a const enumcounter_count_functionarray. This patch adds the const qualifier to themchp_tc_count_functionsto matchfunctions_list.Cc Kamel Bouhara <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied.
Quoted 17 lines
--- drivers/counter/microchip-tcb-capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/microchip-tcb-capture.c +1
-1@@ -37,7 +37,7 @@ enum mchp_tc_count_function { MCHP_TC_FUNCTION_QUADRATURE, }; -static enum counter_count_function mchp_tc_count_functions[] = { +static const enum counter_count_function mchp_tc_count_functions[] = { [MCHP_TC_FUNCTION_INCREASE ] =COUNTER_COUNT_FUNCTION_INCREASE , [MCHP_TC_FUNCTION_QUADRATURE ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X4 , };
PATCH v11 10/33 counter: stm32-lptimer-cnt: Add const qualifier for functions_list array
In reply to William Breathitt GrayThe struct counter_count functions_list member expects a const enum counter_count_function array. This patch adds the const qualifier to the stm32_lptim_cnt_functions to match functions_list.
--- drivers/counter/stm32-lptimer-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/stm32-lptimer-cnt.c +1 -1
@@ -134,7 +134,7 @@ enum stm32_lptim_cnt_function { STM32_LPTIM_ENCODER_BOTH_EDGE, }; -static enum counter_count_function stm32_lptim_cnt_functions[] = { +static const enum counter_count_function stm32_lptim_cnt_functions[] = { [STM32_LPTIM_COUNTER_INCREASE ] =COUNTER_COUNT_FUNCTION_INCREASE , [STM32_LPTIM_ENCODER_BOTH_EDGE ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X4 , };
Signature · 1 line
2.32.0
Re: [PATCH v11 10/33] counter: stm32-lptimer-cnt: Add const qualifier for functions_list array
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:13 +0900 William Breathitt Gray…
The struct
counter_countfunctions_listmember expects a const enumcounter_count_functionarray. This patch adds the const qualifier to thestm32_lptim_cnt_functionsto matchfunctions_list.Reviewed-by Fabrice Gasnier <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied.
btw a different reasoning for all of these is that static const is read only and will let linker and compiler do various tricks that it can't do otherwise.
Jonathan
Quoted 17 lines
--- drivers/counter/stm32-lptimer-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/stm32-lptimer-cnt.c +1
-1@@ -134,7 +134,7 @@ enum stm32_lptim_cnt_function { STM32_LPTIM_ENCODER_BOTH_EDGE, }; -static enum counter_count_function stm32_lptim_cnt_functions[] = { +static const enum counter_count_function stm32_lptim_cnt_functions[] = { [STM32_LPTIM_COUNTER_INCREASE ] =COUNTER_COUNT_FUNCTION_INCREASE , [STM32_LPTIM_ENCODER_BOTH_EDGE ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X4 , };
PATCH v11 11/33 counter: stm32-timer-cnt: Add const qualifier for functions_list array
In reply to William Breathitt GrayThe struct counter_count functions_list member expects a const enum counter_count_function array. This patch adds the const qualifier to the stm32_count_functions to match functions_list.
--- drivers/counter/stm32-timer-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/stm32-timer-cnt.c +1 -1
@@ -50,7 +50,7 @@ enum stm32_count_function { STM32_COUNT_ENCODER_MODE_3, }; -static enum counter_count_function stm32_count_functions[] = { +static const enum counter_count_function stm32_count_functions[] = { [STM32_COUNT_SLAVE_MODE_DISABLED ] =COUNTER_COUNT_FUNCTION_INCREASE , [STM32_COUNT_ENCODER_MODE_1 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A , [STM32_COUNT_ENCODER_MODE_2 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B ,
Signature · 1 line
2.32.0
Re: [PATCH v11 11/33] counter: stm32-timer-cnt: Add const qualifier for functions_list array
Quoted 7 lines · On Wed, 9 Jun 2021 10:31:14 +0900 William Breathitt Gray…
The struct
counter_countfunctions_listmember expects a const enumcounter_count_functionarray. This patch adds the const qualifier to thestm32_count_functionsto matchfunctions_list.Cc Benjamin Gaignard <[email protected]>Reviewed-by Fabrice Gasnier <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied. Thanks
Quoted 17 lines
--- drivers/counter/stm32-timer-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/stm32-timer-cnt.c +1
-1@@ -50,7 +50,7 @@ enum stm32_count_function { STM32_COUNT_ENCODER_MODE_3, }; -static enum counter_count_function stm32_count_functions[] = { +static const enum counter_count_function stm32_count_functions[] = { [STM32_COUNT_SLAVE_MODE_DISABLED ] =COUNTER_COUNT_FUNCTION_INCREASE , [STM32_COUNT_ENCODER_MODE_1 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A , [STM32_COUNT_ENCODER_MODE_2 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B ,
PATCH v11 12/33 counter: 104-quad-8: Add const qualifier for actions_list array
In reply to William Breathitt GrayThe struct counter_synapse actions_list member expects a const enum counter_synapse_action array. This patch adds the const qualifier to the quad8_index_actions_list and quad8_synapse_actions_list to match actions_list.
--- drivers/counter/104-quad-8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/counter/104-quad-8.c +2 -2
@@ -305,12 +305,12 @@ enum quad8_synapse_action {QUAD8_SYNAPSE_ACTION_BOTH_EDGES }; -static enum counter_synapse_action quad8_index_actions_list[] = { +static const enum counter_synapse_action quad8_index_actions_list[] = { [QUAD8_SYNAPSE_ACTION_NONE ] =COUNTER_SYNAPSE_ACTION_NONE , [QUAD8_SYNAPSE_ACTION_RISING_EDGE ] =COUNTER_SYNAPSE_ACTION_RISING_EDGE }; -static enum counter_synapse_action quad8_synapse_actions_list[] = { +static const enum counter_synapse_action quad8_synapse_actions_list[] = { [QUAD8_SYNAPSE_ACTION_NONE ] =COUNTER_SYNAPSE_ACTION_NONE , [QUAD8_SYNAPSE_ACTION_RISING_EDGE ] =COUNTER_SYNAPSE_ACTION_RISING_EDGE , [QUAD8_SYNAPSE_ACTION_FALLING_EDGE ] =COUNTER_SYNAPSE_ACTION_FALLING_EDGE ,
Signature · 1 line
2.32.0
Re: [PATCH v11 12/33] counter: 104-quad-8: Add const qualifier for actions_list array
Quoted 7 lines · On Wed, 9 Jun 2021 10:31:15 +0900 William Breathitt Gray…
The struct
counter_synapseactions_listmember expects a const enumcounter_synapse_actionarray. This patch adds the const qualifier to thequad8_index_actions_listandquad8_synapse_actions_listto matchactions_list.Signed-off-by William Breathitt Gray <[email protected]>
Applied
Thanks,
Quoted 23 lines
--- drivers/counter/104-quad-8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/counter/104-quad-8.c +2
-2@@ -305,12 +305,12 @@ enum quad8_synapse_action {QUAD8_SYNAPSE_ACTION_BOTH_EDGES }; -static enum counter_synapse_action quad8_index_actions_list[] = { +static const enum counter_synapse_action quad8_index_actions_list[] = { [QUAD8_SYNAPSE_ACTION_NONE ] =COUNTER_SYNAPSE_ACTION_NONE , [QUAD8_SYNAPSE_ACTION_RISING_EDGE ] =COUNTER_SYNAPSE_ACTION_RISING_EDGE }; -static enum counter_synapse_action quad8_synapse_actions_list[] = { +static const enum counter_synapse_action quad8_synapse_actions_list[] = { [QUAD8_SYNAPSE_ACTION_NONE ] =COUNTER_SYNAPSE_ACTION_NONE , [QUAD8_SYNAPSE_ACTION_RISING_EDGE ] =COUNTER_SYNAPSE_ACTION_RISING_EDGE , [QUAD8_SYNAPSE_ACTION_FALLING_EDGE ] =COUNTER_SYNAPSE_ACTION_FALLING_EDGE ,
PATCH v11 13/33 counter: ftm-quaddec: Add const qualifier for actions_list array
In reply to William Breathitt GrayThe struct counter_synapse actions_list member expects a const enum counter_synapse_action array. This patch adds the const qualifier to the ftm_quaddec_synapse_actions to match actions_list.
--- drivers/counter/ftm-quaddec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/ftm-quaddec.c +1 -1
@@ -162,7 +162,7 @@ enum ftm_quaddec_synapse_action { FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES, }; -static enum counter_synapse_action ftm_quaddec_synapse_actions[] = { +static const enum counter_synapse_action ftm_quaddec_synapse_actions[] = { [FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES ] =COUNTER_SYNAPSE_ACTION_BOTH_EDGES };
Signature · 1 line
2.32.0
Re: [PATCH v11 13/33] counter: ftm-quaddec: Add const qualifier for actions_list array
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:16 +0900 William Breathitt Gray…
The struct
counter_synapseactions_listmember expects a const enumcounter_synapse_actionarray. This patch adds the const qualifier to theftm_quaddec_synapse_actionsto matchactions_list.Cc Patrick Havelange <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied.
Thanks,
Jonathan
Quoted 17 lines
--- drivers/counter/ftm-quaddec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/ftm-quaddec.c +1
-1@@ -162,7 +162,7 @@ enum ftm_quaddec_synapse_action { FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES, }; -static enum counter_synapse_action ftm_quaddec_synapse_actions[] = { +static const enum counter_synapse_action ftm_quaddec_synapse_actions[] = { [FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES ] =COUNTER_SYNAPSE_ACTION_BOTH_EDGES };
PATCH v11 14/33 counter: interrupt-cnt: Add const qualifier for actions_list array
In reply to William Breathitt GrayThe struct counter_synapse actions_list member expects a const enum counter_synapse_action array. This patch adds the const qualifier to the interrupt_cnt_synapse_actionss to match actions_list.
--- drivers/counter/interrupt-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/interrupt-cnt.c +1 -1
@@ -77,7 +77,7 @@ static const struct counter_count_ext interrupt_cnt_ext[] = { }, }; -static enum counter_synapse_action interrupt_cnt_synapse_actionss[] = { +static const enum counter_synapse_action interrupt_cnt_synapse_actionss[] = {COUNTER_SYNAPSE_ACTION_RISING_EDGE , };
Signature · 1 line
2.32.0
Jonathan Cameron
maintainerRe: [PATCH v11 14/33] counter: interrupt-cnt: Add const qualifier for actions_list array
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:17 +0900 William Breathitt Gray…
The struct
counter_synapseactions_listmember expects a const enumcounter_synapse_actionarray. This patch adds the const qualifier to theinterrupt_cnt_synapse_actionssto matchactions_list.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Naming looks unusual...
Quoted 9 lines
--- drivers/counter/interrupt-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/interrupt-cnt.c +0
-0
drivers/counter/interrupt-cnt.c static const struct counter_count_ext interrupt_cnt_ext[] = { · line 80
Quoted 5 lines
drivers/counter/interrupt-cnt.c +1
-1@@ -77,7 +77,7 @@ static const struct counter_count_ext interrupt_cnt_ext[] = { }, }; -static enum counter_synapse_action interrupt_cnt_synapse_actionss[] = { +static const enum counter_synapse_action interrupt_cnt_synapse_actionss[] = {
actions?
Perhaps good to fix that whilst we are here.
Quoted 3 lines
drivers/counter/interrupt-cnt.c +0
-0COUNTER_SYNAPSE_ACTION_RISING_EDGE, };
Re: [PATCH v11 14/33] counter: interrupt-cnt: Add const qualifier for actions_list array
Quoted 23 lines · Jonathan Cameron
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:17 +0900 William Breathitt Gray…
The struct
counter_synapseactions_listmember expects a const enumcounter_synapse_actionarray. This patch adds the const qualifier to theinterrupt_cnt_synapse_actionssto matchactions_list.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>Naming looks unusual...
Quoted 12 lines
--- drivers/counter/interrupt-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/interrupt-cnt.c +0
-0@@ -77,7 +77,7 @@ static const struct counter_count_ext interrupt_cnt_ext[] = { }, };
Quoted 10 lines
drivers/counter/interrupt-cnt.c static const struct counter_count_ext interrupt_cnt_ext[] = { · line 80
Quoted 2 lines
drivers/counter/interrupt-cnt.c +1
-1-static enum counter_synapse_action interrupt_cnt_synapse_actionss[] = { +static const enum counter_synapse_action interrupt_cnt_synapse_actionss[] = {actions?
Perhaps good to fix that whilst we are here.
Quoted 3 lines
drivers/counter/interrupt-cnt.c +0
-0COUNTER_SYNAPSE_ACTION_RISING_EDGE, };
Hi Oleksij,
Would you take a look at this driver and let us know whether the two 's' at the end of this symbol is intentional?
Thanks,
William Breathitt Gray
PATCH v11 15/33 counter: microchip-tcb-capture: Add const qualifier for actions_list array
In reply to William Breathitt GrayThe struct counter_synapse actions_list member expects a const enum counter_synapse_action array. This patch adds the const qualifier to the mchp_tc_synapse_actions to match actions_list.
--- drivers/counter/microchip-tcb-capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/microchip-tcb-capture.c +1 -1
@@ -49,7 +49,7 @@ enum mchp_tc_synapse_action {MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE }; -static enum counter_synapse_action mchp_tc_synapse_actions[] = { +static const enum counter_synapse_action mchp_tc_synapse_actions[] = { [MCHP_TC_SYNAPSE_ACTION_NONE ] =COUNTER_SYNAPSE_ACTION_NONE , [MCHP_TC_SYNAPSE_ACTION_RISING_EDGE ] =COUNTER_SYNAPSE_ACTION_RISING_EDGE , [MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE ] =COUNTER_SYNAPSE_ACTION_FALLING_EDGE ,
Signature · 1 line
2.32.0
Re: [PATCH v11 15/33] counter: microchip-tcb-capture: Add const qualifier for actions_list array
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:18 +0900 William Breathitt Gray…
The struct
counter_synapseactions_listmember expects a const enumcounter_synapse_actionarray. This patch adds the const qualifier to themchp_tc_synapse_actionsto matchactions_list.Cc Kamel Bouhara <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied.
Thanks
Quoted 17 lines
--- drivers/counter/microchip-tcb-capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/microchip-tcb-capture.c +1
-1@@ -49,7 +49,7 @@ enum mchp_tc_synapse_action {MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE }; -static enum counter_synapse_action mchp_tc_synapse_actions[] = { +static const enum counter_synapse_action mchp_tc_synapse_actions[] = { [MCHP_TC_SYNAPSE_ACTION_NONE ] =COUNTER_SYNAPSE_ACTION_NONE , [MCHP_TC_SYNAPSE_ACTION_RISING_EDGE ] =COUNTER_SYNAPSE_ACTION_RISING_EDGE , [MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE ] =COUNTER_SYNAPSE_ACTION_FALLING_EDGE ,
PATCH v11 16/33 counter: stm32-lptimer-cnt: Add const qualifier for actions_list array
In reply to William Breathitt GrayThe struct counter_synapse actions_list member expects a const enum counter_synapse_action array. This patch adds the const qualifier to the stm32_lptim_cnt_synapse_actions to match actions_list.
--- drivers/counter/stm32-lptimer-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/stm32-lptimer-cnt.c +1 -1
@@ -146,7 +146,7 @@ enum stm32_lptim_synapse_action { STM32_LPTIM_SYNAPSE_ACTION_NONE, }; -static enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = { +static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = {/* Index must match with stm32_lptim_cnt_polarity[] (priv->polarity) */ [STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE ] =COUNTER_SYNAPSE_ACTION_RISING_EDGE , [STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE ] =COUNTER_SYNAPSE_ACTION_FALLING_EDGE ,
Signature · 1 line
2.32.0
Re: [PATCH v11 16/33] counter: stm32-lptimer-cnt: Add const qualifier for actions_list array
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:19 +0900 William Breathitt Gray…
The struct
counter_synapseactions_listmember expects a const enumcounter_synapse_actionarray. This patch adds the const qualifier to thestm32_lptim_cnt_synapse_actionsto matchactions_list.Reviewed-by Fabrice Gasnier <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied.
Thanks,
J
Quoted 17 lines
--- drivers/counter/stm32-lptimer-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/stm32-lptimer-cnt.c +1
-1@@ -146,7 +146,7 @@ enum stm32_lptim_synapse_action { STM32_LPTIM_SYNAPSE_ACTION_NONE, }; -static enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = { +static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = {/* Index must match with stm32_lptim_cnt_polarity[] (priv->polarity) */ [STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE ] =COUNTER_SYNAPSE_ACTION_RISING_EDGE , [STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE ] =COUNTER_SYNAPSE_ACTION_FALLING_EDGE ,
PATCH v11 17/33 counter: stm32-timer-cnt: Add const qualifier for actions_list array
In reply to William Breathitt GrayThe struct counter_synapse actions_list member expects a const enum counter_synapse_action array. This patch adds the const qualifier to the stm32_synapse_actions to match actions_list.
--- drivers/counter/stm32-timer-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/counter/stm32-timer-cnt.c +1 -1
@@ -267,7 +267,7 @@ enum stm32_synapse_action { STM32_SYNAPSE_ACTION_BOTH_EDGES }; -static enum counter_synapse_action stm32_synapse_actions[] = { +static const enum counter_synapse_action stm32_synapse_actions[] = { [STM32_SYNAPSE_ACTION_NONE ] =COUNTER_SYNAPSE_ACTION_NONE , [STM32_SYNAPSE_ACTION_BOTH_EDGES ] =COUNTER_SYNAPSE_ACTION_BOTH_EDGES };
Signature · 1 line
2.32.0
Re: [PATCH v11 17/33] counter: stm32-timer-cnt: Add const qualifier for actions_list array
Quoted 7 lines · On Wed, 9 Jun 2021 10:31:20 +0900 William Breathitt Gray…
The struct
counter_synapseactions_listmember expects a const enumcounter_synapse_actionarray. This patch adds the const qualifier to thestm32_synapse_actionsto matchactions_list.Cc Benjamin Gaignard <[email protected]>Reviewed-by Fabrice Gasnier <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Applied.
Quoted 17 lines
--- drivers/counter/stm32-timer-cnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/counter/stm32-timer-cnt.c +1
-1@@ -267,7 +267,7 @@ enum stm32_synapse_action { STM32_SYNAPSE_ACTION_BOTH_EDGES }; -static enum counter_synapse_action stm32_synapse_actions[] = { +static const enum counter_synapse_action stm32_synapse_actions[] = { [STM32_SYNAPSE_ACTION_NONE ] =COUNTER_SYNAPSE_ACTION_NONE , [STM32_SYNAPSE_ACTION_BOTH_EDGES ] =COUNTER_SYNAPSE_ACTION_BOTH_EDGES };
PATCH v11 18/33 counter: Return error code on invalid modes
In reply to William Breathitt GrayOnly a select set of modes (function, action, etc.) are valid for a given device configuration. This patch ensures that invalid modes result in a return -EINVAL. Such a situation should never occur in reality, but it's good to define a default switch cases for the sake of making the intent of the code clear.
--- drivers/counter/104-quad-8.c | 20 +++++++---- drivers/counter/microchip-tcb-capture.c | 6 ++++ drivers/counter/stm32-lptimer-cnt.c | 10 +++--- drivers/counter/ti-eqep.c | 45 +++++++++++-------------- 4 files changed, 46 insertions(+), 35 deletions(-)
drivers/counter/104-quad-8.c +14 -6
@@ -273,6 +273,10 @@ static int quad8_function_set(struct counter_device *counter, *scale =2 ; mode_cfg |=QUAD8_CMR_QUADRATURE_X4 ;break ; +default : +/* should never reach this path */ +mutex_unlock (&priv->lock); +return -EINVAL ; } }
@@ -349,7 +353,7 @@ static int quad8_action_get(struct counter_device *counter,case QUAD8_COUNT_FUNCTION_PULSE_DIRECTION :if (synapse->signal->id == signal_a_id) *action =QUAD8_SYNAPSE_ACTION_RISING_EDGE ; -break ; +return 0 ;case QUAD8_COUNT_FUNCTION_QUADRATURE_X1 :if (synapse->signal->id == signal_a_id) {quad8_direction_get (counter, count, &direction);
@@ -359,17 +363,18 @@ static int quad8_action_get(struct counter_device *counter,else *action =QUAD8_SYNAPSE_ACTION_FALLING_EDGE ; } -break ; +return 0 ;case QUAD8_COUNT_FUNCTION_QUADRATURE_X2 :if (synapse->signal->id == signal_a_id) *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ; -break ; +return 0 ;case QUAD8_COUNT_FUNCTION_QUADRATURE_X4 : *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ; -break ; +return 0 ; +default : +/* should never reach this path */ +return -EINVAL ; } - -return 0 ; }static const struct counter_ops quad8_ops = {
@@ -529,6 +534,9 @@ static int quad8_count_mode_set(struct counter_device *counter,case COUNTER_COUNT_MODE_MODULO_N : cnt_mode =3 ;break ; +default : +/* should never reach this path */ +return -EINVAL ; }mutex_lock (&priv->lock);
drivers/counter/microchip-tcb-capture.c +6 -0
@@ -133,6 +133,9 @@ static int mchp_tc_count_function_set(struct counter_device *counter, bmr |=ATMEL_TC_QDEN |ATMEL_TC_POSEN ; cmr |=ATMEL_TC_ETRGEDG_RISING |ATMEL_TC_ABETRG |ATMEL_TC_XC0 ;break ; +default : +/* should never reach this path */ +return -EINVAL ; }regmap_write (priv->regmap,ATMEL_TC_BMR , bmr);
@@ -226,6 +229,9 @@ static int mchp_tc_count_action_set(struct counter_device *counter,case MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE : edge =ATMEL_TC_ETRGEDG_BOTH ;break ; +default : +/* should never reach this path */ +return -EINVAL ; } return regmap_write_bits(priv->regmap,
drivers/counter/stm32-lptimer-cnt.c +6 -4
@@ -206,9 +206,10 @@ static int stm32_lptim_cnt_function_set(struct counter_device *counter, priv->quadrature_mode =1 ; priv->polarity =STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES ;return 0 ; +default : +/* should never reach this path */ +return -EINVAL ; } - -return -EINVAL ; } static ssize_t stm32_lptim_cnt_enable_read(struct counter_device *counter,
@@ -326,9 +327,10 @@ static int stm32_lptim_cnt_action_get(struct counter_device *counter,case STM32_LPTIM_ENCODER_BOTH_EDGE : *action = priv->polarity;return 0 ; +default : +/* should never reach this path */ +return -EINVAL ; } - -return -EINVAL ; } static int stm32_lptim_cnt_action_set(struct counter_device *counter,
drivers/counter/ti-eqep.c +20 -25
64 lines not on this page · raw message
Signature · 1 line
2.32.0
Jonathan Cameron
maintainerRe: [PATCH v11 18/33] counter: Return error code on invalid modes
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:21 +0900 William Breathitt Gray…
Only a select set of modes (function, action, etc.) are valid for a given device configuration. This patch ensures that invalid modes result in a return
-EINVAL. Such a situation should never occur in reality, but it's good to define a default switch cases for the sake of making the intent of the code clear.
Quoted 7 lines
Cc Kamel Bouhara <[email protected]>Cc Maxime Coquelin <[email protected]>Cc Alexandre Torgue <[email protected]>Cc David Lechner <[email protected]>Reviewed-by Fabrice Gasnier <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Hi,
I've been lazy and not looked at these in sufficient depth before now :(
There are a few cases in here that I think could be handled more elegantly and in a fashion more likely to expose potential bugs if enums change number of entries in future etc.
I've very keen on a compiler being able to see when we have a switch on an enum.
Jonathan
Quoted 94 lines
--- drivers/counter/104-quad-8.c | 20 +++++++---- drivers/counter/microchip-tcb-capture.c | 6 ++++ drivers/counter/stm32-lptimer-cnt.c | 10 +++--- drivers/counter/ti-eqep.c | 45 +++++++++++-------------- 4 files changed, 46 insertions(+), 35 deletions(-)drivers/counter/104-quad-8.c +14
-6@@ -273,6 +273,10 @@ static int quad8_function_set(struct counter_device *counter, *scale =2 ; mode_cfg |=QUAD8_CMR_QUADRATURE_X4 ;break ; +default : +/* should never reach this path */ +mutex_unlock (&priv->lock); +return -EINVAL ; } }@@ -349,7 +353,7 @@ static int quad8_action_get(struct counter_device *counter,case QUAD8_COUNT_FUNCTION_PULSE_DIRECTION :if (synapse->signal->id == signal_a_id) *action =QUAD8_SYNAPSE_ACTION_RISING_EDGE ; -break ; +return 0 ;case QUAD8_COUNT_FUNCTION_QUADRATURE_X1 :if (synapse->signal->id == signal_a_id) {quad8_direction_get (counter, count, &direction);@@ -359,17 +363,18 @@ static int quad8_action_get(struct counter_device *counter,else *action =QUAD8_SYNAPSE_ACTION_FALLING_EDGE ; } -break ; +return 0 ;case QUAD8_COUNT_FUNCTION_QUADRATURE_X2 :if (synapse->signal->id == signal_a_id) *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ; -break ; +return 0 ;case QUAD8_COUNT_FUNCTION_QUADRATURE_X4 : *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ; -break ; +return 0 ; +default : +/* should never reach this path */ +return -EINVAL ; } - -return 0 ; }static const struct counter_ops quad8_ops = {@@ -529,6 +534,9 @@ static int quad8_count_mode_set(struct counter_device *counter,case COUNTER_COUNT_MODE_MODULO_N : cnt_mode =3 ;break ; +default : +/* should never reach this path */ +return -EINVAL ; }mutex_lock (&priv->lock);drivers/counter/microchip-tcb-capture.c +6
-0@@ -133,6 +133,9 @@ static int mchp_tc_count_function_set(struct counter_device *counter, bmr |=ATMEL_TC_QDEN |ATMEL_TC_POSEN ; cmr |=ATMEL_TC_ETRGEDG_RISING |ATMEL_TC_ABETRG |ATMEL_TC_XC0 ;break ; +default : +/* should never reach this path */ +return -EINVAL ; }regmap_write (priv->regmap,ATMEL_TC_BMR , bmr);@@ -226,6 +229,9 @@ static int mchp_tc_count_action_set(struct counter_device *counter,case MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE : edge =ATMEL_TC_ETRGEDG_BOTH ;break ; +default : +/* should never reach this path */ +return -EINVAL ; } return regmap_write_bits(priv->regmap,drivers/counter/stm32-lptimer-cnt.c +0
-0
drivers/counter/stm32-lptimer-cnt.c static int stm32_lptim_cnt_function_set(struct counter_device *counter, · line 211
Quoted 6 lines
drivers/counter/stm32-lptimer-cnt.c +3
-0@@ -206,9 +206,10 @@ static int stm32_lptim_cnt_function_set(struct counter_device *counter, priv->quadrature_mode =1 ; priv->polarity =STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES ;return 0 ; +default : +/* should never reach this path */ +return -EINVAL ;
In this particular case we are already exhaustive. So we should have neither default nor ideally the return below.
If we have a local variable of the relevant enum type, then I think the compiler should be able to tell this is exhaustive and usefully it will then issue a warning should the enum gain more entries in future.
drivers/counter/stm32-lptimer-cnt.c static int stm32_lptim_cnt_action_get(struct counter_device *counter, · line 330
Quoted 11 lines
drivers/counter/stm32-lptimer-cnt.c +1
-2} - -return -EINVAL ; } static ssize_t stm32_lptim_cnt_enable_read(struct counter_device *counter,@@ -326,9 +327,10 @@ static int stm32_lptim_cnt_action_get(struct counter_device *counter,case STM32_LPTIM_ENCODER_BOTH_EDGE : *action = priv->polarity;return 0 ; +default :
Same in this path.
Quoted 13 lines
drivers/counter/stm32-lptimer-cnt.c +2
-2+/* should never reach this path */ +return -EINVAL ; } - -return -EINVAL ; } static int stm32_lptim_cnt_action_set(struct counter_device *counter,drivers/counter/ti-eqep.c +0
-0
drivers/counter/ti-eqep.c static int ti_eqep_action_get(struct counter_device *counter, · line 165
Quoted 10 lines
drivers/counter/ti-eqep.c +1
-2@@ -157,44 +157,39 @@ static int ti_eqep_action_get(struct counter_device *counter,* QEPA and QEPB trigger QCLK. */ *action =TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES ; -break ; +return 0 ;case TI_EQEP_COUNT_FUNC_DIR_COUNT :/* In direction-count mode only rising edge of QEPA is counted * and QEPB gives direction. */ -switch (synapse->signal->id) {
I'd rather see this as
case TI_EQEP_SIGNAL_QEPA:
caes TI_EQEP_SIGNAL_QEPB:
To make it clear what the two cases are. Then we don't need the default assuming the type is right so the compiler should be able to see that we have been exhaustive.
Quoted 21 lines
drivers/counter/ti-eqep.c +4
-11-case TI_EQEP_SIGNAL_QEPA : - *action =TI_EQEP_SYNAPSE_ACTION_RISING_EDGE ; -break ; -default : +if (synapse->signal->id ==TI_EQEP_SIGNAL_QEPB ) *action =TI_EQEP_SYNAPSE_ACTION_NONE ; -break ; - } -break ; +else + *action =TI_EQEP_SYNAPSE_ACTION_RISING_EDGE ; +return 0 ;case TI_EQEP_COUNT_FUNC_UP_COUNT :case TI_EQEP_COUNT_FUNC_DOWN_COUNT :/* In up/down-count modes only QEPA is counted and QEPB is not * used. */ -switch (synapse->signal->id) { -case TI_EQEP_SIGNAL_QEPA : - err =regmap_read (priv->regmap16,QDECCTL , &qdecctl); -if (err)
drivers/counter/ti-eqep.c static int ti_eqep_action_get(struct counter_device *counter, · line 176
Quoted 10 lines
drivers/counter/ti-eqep.c +1
-8-return err; - -if (qdecctl &QDECCTL_XCR ) - *action =TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES ; -else - *action =TI_EQEP_SYNAPSE_ACTION_RISING_EDGE ; -break ; -default : +if (synapse->signal->id ==TI_EQEP_SIGNAL_QEPB ) { *action =TI_EQEP_SYNAPSE_ACTION_NONE ;
Same as above
Quoted 23 lines
drivers/counter/ti-eqep.c +14
-4-break ; +return 0 ; } -break ; - } -return 0 ; + err =regmap_read (priv->regmap16,QDECCTL , &qdecctl); +if (err) +return err; + +if (qdecctl &QDECCTL_XCR ) + *action =TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES ; +else + *action =TI_EQEP_SYNAPSE_ACTION_RISING_EDGE ; +return 0 ; +default : +/* should never reach this path */ +return -EINVAL ; + } }static const struct counter_ops ti_eqep_counter_ops = {
Re: [PATCH v11 18/33] counter: Return error code on invalid modes
Quoted 17 lines · Jonathan Cameron
drivers/counter/stm32-lptimer-cnt.c static int stm32_lptim_cnt_function_set(struct counter_device *counter, · line 211
Quoted 11 lines · On Wed, 9 Jun 2021 10:31:21 +0900 William Breathitt Gray…
drivers/counter/stm32-lptimer-cnt.c +3
-0@@ -206,9 +206,10 @@ static int stm32_lptim_cnt_function_set(struct counter_device *counter, priv->quadrature_mode =1 ; priv->polarity =STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES ;return 0 ; +default : +/* should never reach this path */ +return -EINVAL ;In this particular case we are already exhaustive. So we should have neither default nor ideally the return below.
Quoted 3 lines
If we have a local variable of the relevant enum type, then I think the compiler should be able to tell this is exhaustive and usefully it will then issue a warning should the enum gain more entries in future.
I tried using a local variable of type enum stm32_lptim_cnt_function, but unfortunately the compiler is not able to tell this is exhaustive -- I think it's because 'function' is of type enum counter_function which can theoretically have a value outside enum stm32_lptim_cnt_function.
Quoted 40 lines
drivers/counter/stm32-lptimer-cnt.c static int stm32_lptim_cnt_action_get(struct counter_device *counter, · line 330
Quoted 12 lines
drivers/counter/stm32-lptimer-cnt.c +1
-2} - -return -EINVAL ; } static ssize_t stm32_lptim_cnt_enable_read(struct counter_device *counter,@@ -326,9 +327,10 @@ static int stm32_lptim_cnt_action_get(struct counter_device *counter,case STM32_LPTIM_ENCODER_BOTH_EDGE : *action = priv->polarity;return 0 ; +default :Same in this path.
Quoted 13 lines
drivers/counter/stm32-lptimer-cnt.c +2
-2+/* should never reach this path */ +return -EINVAL ; } - -return -EINVAL ; } static int stm32_lptim_cnt_action_set(struct counter_device *counter,drivers/counter/ti-eqep.c +0
-0drivers/counter/ti-eqep.c static int ti_eqep_action_get(struct counter_device *counter, · line 165
Quoted 10 lines
drivers/counter/ti-eqep.c +1
-2@@ -157,44 +157,39 @@ static int ti_eqep_action_get(struct counter_device *counter,* QEPA and QEPB trigger QCLK. */ *action =TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES ; -break ; +return 0 ;case TI_EQEP_COUNT_FUNC_DIR_COUNT :/* In direction-count mode only rising edge of QEPA is counted * and QEPB gives direction. */ -switch (synapse->signal->id) {I'd rather see this as
Quoted 6 lines
case
TI_EQEP_SIGNAL_QEPA:
caesTI_EQEP_SIGNAL_QEPB:To make it clear what the two cases are. Then we don't need the default assuming the type is right so the compiler should be able to see that we have been exhaustive.
I can refactor this back to a switch statement as you suggest, but we'll need the default case for the same reason as mentioned above.
William Breathitt Gray
Quoted 59 lines
Quoted 22 lines
drivers/counter/ti-eqep.c +4
-11-case TI_EQEP_SIGNAL_QEPA : - *action =TI_EQEP_SYNAPSE_ACTION_RISING_EDGE ; -break ; -default : +if (synapse->signal->id ==TI_EQEP_SIGNAL_QEPB ) *action =TI_EQEP_SYNAPSE_ACTION_NONE ; -break ; - } -break ; +else + *action =TI_EQEP_SYNAPSE_ACTION_RISING_EDGE ; +return 0 ;case TI_EQEP_COUNT_FUNC_UP_COUNT :case TI_EQEP_COUNT_FUNC_DOWN_COUNT :/* In up/down-count modes only QEPA is counted and QEPB is not * used. */ -switch (synapse->signal->id) { -case TI_EQEP_SIGNAL_QEPA : - err =regmap_read (priv->regmap16,QDECCTL , &qdecctl); -if (err)drivers/counter/ti-eqep.c static int ti_eqep_action_get(struct counter_device *counter, · line 176
Quoted 10 lines
drivers/counter/ti-eqep.c +1
-8-return err; - -if (qdecctl &QDECCTL_XCR ) - *action =TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES ; -else - *action =TI_EQEP_SYNAPSE_ACTION_RISING_EDGE ; -break ; -default : +if (synapse->signal->id ==TI_EQEP_SIGNAL_QEPB ) { *action =TI_EQEP_SYNAPSE_ACTION_NONE ;Same as above
Quoted 23 lines
drivers/counter/ti-eqep.c +14
-4-break ; +return 0 ; } -break ; - } -return 0 ; + err =regmap_read (priv->regmap16,QDECCTL , &qdecctl); +if (err) +return err; + +if (qdecctl &QDECCTL_XCR ) + *action =TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES ; +else + *action =TI_EQEP_SYNAPSE_ACTION_RISING_EDGE ; +return 0 ; +default : +/* should never reach this path */ +return -EINVAL ; + } }static const struct counter_ops ti_eqep_counter_ops = {
PATCH v11 19/33 counter: Standardize to ERANGE for limit exceeded errors
In reply to William Breathitt GrayERANGE is a semantically better error code to return when an argument value falls outside the supported limit range of a device.
--- drivers/counter/104-quad-8.c | 6 +++--- drivers/counter/intel-qep.c | 2 +- drivers/counter/interrupt-cnt.c | 3 +++ drivers/counter/stm32-lptimer-cnt.c | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-)
drivers/counter/104-quad-8.c +3 -3
@@ -154,7 +154,7 @@ static int quad8_count_write(struct counter_device *counter,/* Only 24-bit values are supported */ if (val >0xFFFFFF ) -return -EINVAL ; +return -ERANGE ;mutex_lock (&priv->lock);
@@ -669,7 +669,7 @@ static ssize_t quad8_count_preset_write(struct counter_device *counter,/* Only 24-bit values are supported */ if (preset >0xFFFFFF ) -return -EINVAL ; +return -ERANGE ;mutex_lock (&priv->lock);
@@ -714,7 +714,7 @@ static ssize_t quad8_count_ceiling_write(struct counter_device *counter,/* Only 24-bit values are supported */ if (ceiling >0xFFFFFF ) -return -EINVAL ; +return -ERANGE ;mutex_lock (&priv->lock);
drivers/counter/intel-qep.c +1 -1
@@ -320,7 +320,7 @@ static ssize_t spike_filter_ns_write(struct counter_device *counter, }if (length >INTEL_QEPFLT_MAX_COUNT (length)) -return -EINVAL ; +return -ERANGE ;mutex_lock (&qep->lock);if (qep->enabled) {
drivers/counter/interrupt-cnt.c +3 -0
@@ -107,6 +107,9 @@ static int interrupt_cnt_write(struct counter_device *counter, {struct interrupt_cnt_priv *priv = counter->priv; + if (val != (typeof(priv->count.counter))val) +return -ERANGE ; +atomic_set (&priv->count, val);return 0 ;
drivers/counter/stm32-lptimer-cnt.c +1 -1
@@ -283,7 +283,7 @@ static ssize_t stm32_lptim_cnt_ceiling_write(struct counter_device *counter,return ret;if (ceiling >STM32_LPTIM_MAX_ARR ) -return -EINVAL ; +return -ERANGE ; priv->ceiling = ceiling;
Signature · 1 line
2.32.0
PATCH v11 20/33 counter: Rename counter_signal_value to counter_signal_level
In reply to William Breathitt GraySignal values will always be levels so let's be explicit it about it to make the intent of the code clear.
--- drivers/counter/104-quad-8.c | 5 +++-- drivers/counter/counter.c | 12 ++++++------ drivers/counter/interrupt-cnt.c | 4 ++-- drivers/counter/microchip-tcb-capture.c | 4 ++-- include/linux/counter.h | 12 ++++++------ 5 files changed, 19 insertions(+), 18 deletions(-)
drivers/counter/104-quad-8.c +3 -2
@@ -97,7 +97,8 @@ struct quad8 {#define QUAD8_CMR_QUADRATURE_X4 0x18static int quad8_signal_read (struct counter_device *counter, -struct counter_signal *signal,enum counter_signal_value *val) +struct counter_signal *signal, +enum counter_signal_level *level) {const struct quad8 *const priv = counter->priv;unsigned int state;
@@ -109,7 +110,7 @@ static int quad8_signal_read(struct counter_device *counter, state =inb (priv->base +QUAD8_REG_INDEX_INPUT_LEVELS ) &BIT (signal->id -16 ); - *val = (state) ?COUNTER_SIGNAL_HIGH :COUNTER_SIGNAL_LOW ; + *level = (state) ?COUNTER_SIGNAL_LEVEL_HIGH :COUNTER_SIGNAL_LEVEL_LOW ;return 0 ; }
drivers/counter/counter.c +6 -6
@@ -289,9 +289,9 @@ struct counter_signal_unit {struct counter_signal *signal; }; -static const char *const counter_signal_value_str[] = { - [COUNTER_SIGNAL_LOW ] ="low" , - [COUNTER_SIGNAL_HIGH ] ="high" +static const char *const counter_signal_level_str[] = { + [COUNTER_SIGNAL_LEVEL_LOW ] ="low" , + [COUNTER_SIGNAL_LEVEL_HIGH ] ="high" }; static ssize_t counter_signal_show(struct device *dev,
@@ -302,13 +302,13 @@ static ssize_t counter_signal_show(struct device *dev,const struct counter_signal_unit *const component = devattr->component;struct counter_signal *const signal = component->signal;int err; -enum counter_signal_value val; +enum counter_signal_level level; - err = counter->ops->signal_read (counter, signal, &val); + err = counter->ops->signal_read (counter, signal, &level);if (err)return err; -return sprintf (buf,"%s\n" , counter_signal_value_str[val]); +return sprintf (buf,"%s\n" , counter_signal_level_str[level]); }struct counter_name_unit {
drivers/counter/interrupt-cnt.c +2 -2
@@ -130,7 +130,7 @@ static int interrupt_cnt_function_get(struct counter_device *counter,static int interrupt_cnt_signal_read (struct counter_device *counter,struct counter_signal *signal, -enum counter_signal_value *val) +enum counter_signal_level *level) {struct interrupt_cnt_priv *priv = counter->priv;int ret;
@@ -142,7 +142,7 @@ static int interrupt_cnt_signal_read(struct counter_device *counter,if (ret <0 )return ret; - *val = ret ?COUNTER_SIGNAL_HIGH :COUNTER_SIGNAL_LOW ; + *level = ret ?COUNTER_SIGNAL_LEVEL_HIGH :COUNTER_SIGNAL_LEVEL_LOW ;return 0 ; }
drivers/counter/microchip-tcb-capture.c +2 -2
@@ -158,7 +158,7 @@ static int mchp_tc_count_function_set(struct counter_device *counter,static int mchp_tc_count_signal_read (struct counter_device *counter,struct counter_signal *signal, -enum counter_signal_value *val) +enum counter_signal_level *lvl) {struct mchp_tc_data *const priv = counter->priv;bool sigstatus;
@@ -171,7 +171,7 @@ static int mchp_tc_count_signal_read(struct counter_device *counter,else sigstatus = (sr &ATMEL_TC_MTIOA ); - *val = sigstatus ?COUNTER_SIGNAL_HIGH :COUNTER_SIGNAL_LOW ; + *lvl = sigstatus ?COUNTER_SIGNAL_LEVEL_HIGH :COUNTER_SIGNAL_LEVEL_LOW ;return 0 ; }
include/linux/counter.h +6 -6
@@ -290,16 +290,16 @@ struct counter_device_state {const struct attribute_group **groups; }; -enum counter_signal_value { -COUNTER_SIGNAL_LOW =0 , -COUNTER_SIGNAL_HIGH +enum counter_signal_level { +COUNTER_SIGNAL_LEVEL_LOW , +COUNTER_SIGNAL_LEVEL_HIGH , };/** * struct counter_ops - Callbacks from driver * @signal_read: optional read callback for Signal attribute. The read -* value of the respective Signal should be passed back via -* the val parameter. +* level of the respective Signal should be passed back via +* the level parameter. * @count_read: optional read callback for Count attribute. The read * value of the respective Count should be passed back via * the val parameter.
@@ -324,7 +324,7 @@ enum counter_signal_value {struct counter_ops {int (*signal_read)(struct counter_device *counter,struct counter_signal *signal, -enum counter_signal_value *val); +enum counter_signal_level *level);int (*count_read)(struct counter_device *counter,struct counter_count *count,unsigned long *val); int (*count_write)(struct counter_device *counter,
Signature · 1 line
2.32.0
PATCH v11 21/33 counter: Rename counter_count_function to counter_function
In reply to William Breathitt GrayThe phrase "Counter Count function" is verbose and unintentionally implies that function is a Count extension. This patch adjusts the Counter subsystem code to use the more direct "Counter function" phrase to make the intent of this code clearer.
--- drivers/counter/104-quad-8.c | 10 +++---- drivers/counter/counter.c | 38 ++++++++++++------------- drivers/counter/ftm-quaddec.c | 5 ++-- drivers/counter/intel-qep.c | 4 +-- drivers/counter/interrupt-cnt.c | 4 +-- drivers/counter/microchip-tcb-capture.c | 4 +-- drivers/counter/stm32-lptimer-cnt.c | 6 ++-- drivers/counter/stm32-timer-cnt.c | 10 +++---- drivers/counter/ti-eqep.c | 10 +++---- include/linux/counter.h | 20 ++++++------- 10 files changed, 55 insertions(+), 56 deletions(-)
drivers/counter/104-quad-8.c +5 -5
@@ -194,11 +194,11 @@ enum quad8_count_function {QUAD8_COUNT_FUNCTION_QUADRATURE_X4 }; -static const enum counter_count_function quad8_count_functions_list[] = { - [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION ] =COUNTER_COUNT_FUNCTION_PULSE_DIRECTION , - [QUAD8_COUNT_FUNCTION_QUADRATURE_X1 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A , - [QUAD8_COUNT_FUNCTION_QUADRATURE_X2 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A , - [QUAD8_COUNT_FUNCTION_QUADRATURE_X4 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X4 +static const enum counter_function quad8_count_functions_list[] = { + [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION ] =COUNTER_FUNCTION_PULSE_DIRECTION , + [QUAD8_COUNT_FUNCTION_QUADRATURE_X1 ] =COUNTER_FUNCTION_QUADRATURE_X1_A , + [QUAD8_COUNT_FUNCTION_QUADRATURE_X2 ] =COUNTER_FUNCTION_QUADRATURE_X2_A , + [QUAD8_COUNT_FUNCTION_QUADRATURE_X4 ] =COUNTER_FUNCTION_QUADRATURE_X4 }; static int quad8_function_get(struct counter_device *counter,
drivers/counter/counter.c +19 -19
@@ -744,15 +744,15 @@ static ssize_t counter_count_store(struct device *dev,return len; } -static const char *const counter_count_function_str[] = { - [COUNTER_COUNT_FUNCTION_INCREASE ] ="increase" , - [COUNTER_COUNT_FUNCTION_DECREASE ] ="decrease" , - [COUNTER_COUNT_FUNCTION_PULSE_DIRECTION ] ="pulse-direction" , - [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A ] ="quadrature x1 a" , - [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B ] ="quadrature x1 b" , - [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A ] ="quadrature x2 a" , - [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B ] ="quadrature x2 b" , - [COUNTER_COUNT_FUNCTION_QUADRATURE_X4 ] ="quadrature x4" +static const char *const counter_function_str[] = { + [COUNTER_FUNCTION_INCREASE ] ="increase" , + [COUNTER_FUNCTION_DECREASE ] ="decrease" , + [COUNTER_FUNCTION_PULSE_DIRECTION ] ="pulse-direction" , + [COUNTER_FUNCTION_QUADRATURE_X1_A ] ="quadrature x1 a" , + [COUNTER_FUNCTION_QUADRATURE_X1_B ] ="quadrature x1 b" , + [COUNTER_FUNCTION_QUADRATURE_X2_A ] ="quadrature x2 a" , + [COUNTER_FUNCTION_QUADRATURE_X2_B ] ="quadrature x2 b" , + [COUNTER_FUNCTION_QUADRATURE_X4 ] ="quadrature x4" }; static ssize_t counter_function_show(struct device *dev,
@@ -764,7 +764,7 @@ static ssize_t counter_function_show(struct device *dev,const struct counter_count_unit *const component = devattr->component;struct counter_count *const count = component->count;size_t func_index; -enum counter_count_function function; +enum counter_function function; err = counter->ops->function_get (counter, count, &func_index);if (err)
@@ -773,7 +773,7 @@ static ssize_t counter_function_show(struct device *dev, count->function = func_index; function = count->functions_list[func_index]; -return sprintf (buf,"%s\n" , counter_count_function_str[function]); +return sprintf (buf,"%s\n" , counter_function_str[function]); } static ssize_t counter_function_store(struct device *dev,
@@ -785,14 +785,14 @@ static ssize_t counter_function_store(struct device *dev,struct counter_count *const count = component->count;const size_t num_functions = count->num_functions;size_t func_index; -enum counter_count_function function; +enum counter_function function;int err;struct counter_device *const counter =dev_get_drvdata (dev);/* Find requested Count function mode */ for (func_index =0 ; func_index < num_functions; func_index++) { function = count->functions_list[func_index]; -if (sysfs_streq (buf, counter_count_function_str[function])) +if (sysfs_streq (buf, counter_function_str[function]))break ; }/* Return error if requested Count function mode not found */
@@ -880,25 +880,25 @@ static int counter_count_ext_register( }struct counter_func_avail_unit { -const enum counter_count_function *functions_list; +const enum counter_function *functions_list;size_t num_functions; }; -static ssize_t counter_count_function_available_show (struct device *dev, +static ssize_t counter_function_available_show (struct device *dev,struct device_attribute *attr,char *buf) {const struct counter_device_attr *const devattr =to_counter_attr (attr);const struct counter_func_avail_unit *const component = devattr->component; -const enum counter_count_function *const func_list = component->functions_list; +const enum counter_function *const func_list = component->functions_list;const size_t num_functions = component->num_functions;size_t i; -enum counter_count_function function; +enum counter_function function;ssize_t len =0 ;for (i =0 ; i < num_functions; i++) { function = func_list[i]; len +=sprintf (buf + len,"%s\n" , - counter_count_function_str[function]); + counter_function_str[function]); }return len;
@@ -968,7 +968,7 @@ static int counter_count_attributes_create( parm.group = group; parm.prefix ="" ; parm.name ="function_available" ; - parm.show = counter_count_function_available_show; + parm.show = counter_function_available_show; parm.store =NULL ; parm.component = avail_comp; err =counter_attribute_create (&parm);
drivers/counter/ftm-quaddec.c +2 -3
@@ -171,9 +171,8 @@ enum ftm_quaddec_count_function { FTM_QUADDEC_COUNT_ENCODER_MODE_1, }; -static const enum counter_count_function ftm_quaddec_count_functions[] = { - [FTM_QUADDEC_COUNT_ENCODER_MODE_1 ] = -COUNTER_COUNT_FUNCTION_QUADRATURE_X4 +static const enum counter_function ftm_quaddec_count_functions[] = { + [FTM_QUADDEC_COUNT_ENCODER_MODE_1 ] =COUNTER_FUNCTION_QUADRATURE_X4 }; static int ftm_quaddec_count_read(struct counter_device *counter,
drivers/counter/intel-qep.c +2 -2
@@ -127,8 +127,8 @@ static int intel_qep_count_read(struct counter_device *counter,return 0 ; } -static const enum counter_count_function intel_qep_count_functions[] = { -COUNTER_COUNT_FUNCTION_QUADRATURE_X4 , +static const enum counter_function intel_qep_count_functions[] = { +COUNTER_FUNCTION_QUADRATURE_X4 , }; static int intel_qep_function_get(struct counter_device *counter,
drivers/counter/interrupt-cnt.c +2 -2
@@ -115,8 +115,8 @@ static int interrupt_cnt_write(struct counter_device *counter,return 0 ; } -static const enum counter_count_function interrupt_cnt_functions[] = { -COUNTER_COUNT_FUNCTION_INCREASE , +static const enum counter_function interrupt_cnt_functions[] = { +COUNTER_FUNCTION_INCREASE , }; static int interrupt_cnt_function_get(struct counter_device *counter,
drivers/counter/microchip-tcb-capture.c +2 -2
@@ -38,8 +38,8 @@ enum mchp_tc_count_function { };static const enum counter_count_function mchp_tc_count_functions[] = { - [MCHP_TC_FUNCTION_INCREASE ] =COUNTER_COUNT_FUNCTION_INCREASE , - [MCHP_TC_FUNCTION_QUADRATURE ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X4 , + [MCHP_TC_FUNCTION_INCREASE ] =COUNTER_FUNCTION_INCREASE , + [MCHP_TC_FUNCTION_QUADRATURE ] =COUNTER_FUNCTION_QUADRATURE_X4 , };enum mchp_tc_synapse_action {
drivers/counter/stm32-lptimer-cnt.c +3 -3
@@ -134,9 +134,9 @@ enum stm32_lptim_cnt_function { STM32_LPTIM_ENCODER_BOTH_EDGE, }; -static const enum counter_count_function stm32_lptim_cnt_functions[] = { - [STM32_LPTIM_COUNTER_INCREASE ] =COUNTER_COUNT_FUNCTION_INCREASE , - [STM32_LPTIM_ENCODER_BOTH_EDGE ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X4 , +static const enum counter_function stm32_lptim_cnt_functions[] = { + [STM32_LPTIM_COUNTER_INCREASE ] =COUNTER_FUNCTION_INCREASE , + [STM32_LPTIM_ENCODER_BOTH_EDGE ] =COUNTER_FUNCTION_QUADRATURE_X4 , };enum stm32_lptim_synapse_action {
drivers/counter/stm32-timer-cnt.c +5 -5
@@ -50,11 +50,11 @@ enum stm32_count_function { STM32_COUNT_ENCODER_MODE_3, }; -static const enum counter_count_function stm32_count_functions[] = { - [STM32_COUNT_SLAVE_MODE_DISABLED ] =COUNTER_COUNT_FUNCTION_INCREASE , - [STM32_COUNT_ENCODER_MODE_1 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A , - [STM32_COUNT_ENCODER_MODE_2 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B , - [STM32_COUNT_ENCODER_MODE_3 ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X4 , +static const enum counter_function stm32_count_functions[] = { + [STM32_COUNT_SLAVE_MODE_DISABLED ] =COUNTER_FUNCTION_INCREASE , + [STM32_COUNT_ENCODER_MODE_1 ] =COUNTER_FUNCTION_QUADRATURE_X2_A , + [STM32_COUNT_ENCODER_MODE_2 ] =COUNTER_FUNCTION_QUADRATURE_X2_B , + [STM32_COUNT_ENCODER_MODE_3 ] =COUNTER_FUNCTION_QUADRATURE_X4 , }; static int stm32_count_read(struct counter_device *counter,
drivers/counter/ti-eqep.c +5 -5
@@ -284,11 +284,11 @@ static struct counter_signal ti_eqep_signals[] = { }, }; -static const enum counter_count_function ti_eqep_position_functions[] = { - [TI_EQEP_COUNT_FUNC_QUAD_COUNT ] =COUNTER_COUNT_FUNCTION_QUADRATURE_X4 , - [TI_EQEP_COUNT_FUNC_DIR_COUNT ] =COUNTER_COUNT_FUNCTION_PULSE_DIRECTION , - [TI_EQEP_COUNT_FUNC_UP_COUNT ] =COUNTER_COUNT_FUNCTION_INCREASE , - [TI_EQEP_COUNT_FUNC_DOWN_COUNT ] =COUNTER_COUNT_FUNCTION_DECREASE , +static const enum counter_function ti_eqep_position_functions[] = { + [TI_EQEP_COUNT_FUNC_QUAD_COUNT ] =COUNTER_FUNCTION_QUADRATURE_X4 , + [TI_EQEP_COUNT_FUNC_DIR_COUNT ] =COUNTER_FUNCTION_PULSE_DIRECTION , + [TI_EQEP_COUNT_FUNC_UP_COUNT ] =COUNTER_FUNCTION_INCREASE , + [TI_EQEP_COUNT_FUNC_DOWN_COUNT ] =COUNTER_FUNCTION_DECREASE , };static const enum counter_synapse_action ti_eqep_position_synapse_actions[] = {
include/linux/counter.h +10 -10
@@ -162,15 +162,15 @@ struct counter_count_ext {void *priv; }; -enum counter_count_function { -COUNTER_COUNT_FUNCTION_INCREASE =0 , -COUNTER_COUNT_FUNCTION_DECREASE , -COUNTER_COUNT_FUNCTION_PULSE_DIRECTION , -COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A , -COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B , -COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A , -COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B , -COUNTER_COUNT_FUNCTION_QUADRATURE_X4 +enum counter_function { +COUNTER_FUNCTION_INCREASE =0 , +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 };/**
@@ -192,7 +192,7 @@ struct counter_count {const char *name;size_t function; -const enum counter_count_function *functions_list; +const enum counter_function *functions_list;size_t num_functions;struct counter_synapse *synapses;
Signature · 1 line
2.32.0
PATCH v11 22/33 counter: Internalize sysfs interface code
In reply to William Breathitt GrayThis is a reimplementation of the Generic Counter driver interface. There are no modifications to the Counter subsystem userspace interface, so existing userspace applications should continue to run seamlessly.
The purpose of this patch is to internalize the sysfs interface code among the various counter drivers into a shared module. Counter drivers pass and take data natively (i.e. u8, u64, etc.) and the shared counter module handles the translation between the sysfs interface and the device drivers. This guarantees a standard userspace interface for all counter drivers, and helps generalize the Generic Counter driver ABI in order to support the Generic Counter chrdev interface (introduced in a subsequent patch) without significant changes to the existing counter drivers.
Note, Counter device registration is the same as before: drivers populate a struct counter_device with components and callbacks, then pass the structure to the devm_counter_register function. However, what's different now is how the Counter subsystem code handles this registration internally.
Whereas before callbacks would interact directly with sysfs data, this interaction is now abstracted and instead callbacks interact with native C data types. The counter_comp structure forms the basis for Counter extensions.
The counter-sysfs.c file contains the code to parse through the counter_device structure and register the requested components and extensions. Attributes are created and populated based on type, with respective translation functions to handle the mapping between sysfs and the counter driver callbacks.
The translation performed for each attribute is straightforward: the attribute type and data is parsed from the counter_attribute structure, the respective counter driver read/write callback is called, and sysfs I/O is handled before or after the driver read/write function is called.
--- MAINTAINERS | 1 - drivers/counter/104-quad-8.c | 449 +++---- drivers/counter/Makefile | 1 + drivers/counter/counter-core.c | 155 +++ drivers/counter/counter-sysfs.c | 846 +++++++++++++ drivers/counter/counter-sysfs.h | 13 + drivers/counter/counter.c | 1496 ----------------------- drivers/counter/ftm-quaddec.c | 56 +- drivers/counter/intel-qep.c | 144 +-- drivers/counter/interrupt-cnt.c | 62 +- drivers/counter/microchip-tcb-capture.c | 93 +- drivers/counter/stm32-lptimer-cnt.c | 162 ++- drivers/counter/stm32-timer-cnt.c | 147 +-- drivers/counter/ti-eqep.c | 180 +-- include/linux/counter.h | 629 +++++----- include/linux/counter_enum.h | 45 - 16 files changed, 1918 insertions(+), 2561 deletions(-) create mode 100644 drivers/counter/counter-core.c create mode 100644 drivers/counter/counter-sysfs.c create mode 100644 drivers/counter/counter-sysfs.h delete mode 100644 drivers/counter/counter.c delete mode 100644 include/linux/counter_enum.h
MAINTAINERS +0 -1
@@ -4678,7 +4678,6 @@ F: Documentation/ABI/testing/sysfs-bus-counter F: Documentation/driver-api/generic-counter.rst F: drivers/counter/ F: include/linux/counter.h -F: include/linux/counter_enum.h CP2615 I2C DRIVER M: Bence Csókás <[email protected]>
drivers/counter/104-quad-8.c +191 -258
796 lines not on this page · raw message
drivers/counter/Makefile +1 -0
@@ -4,6 +4,7 @@ # obj-$(CONFIG_COUNTER) += counter.o +counter-y := counter-core.o counter-sysfs.o obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o
drivers/counter/counter-core.c new file +155 -0
155 lines not on this page · raw message
drivers/counter/counter-sysfs.c new file +846 -0
846 lines not on this page · raw message
drivers/counter/counter-sysfs.h new file +13 -0
@@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Counter sysfs interface +* Copyright (C) 2020 William Breathitt Gray +*/ +#ifndef _COUNTER_SYSFS_H_ +#define _COUNTER_SYSFS_H_ + +#include <linux/counter.h> + +int counter_sysfs_add (struct counter_device *const counter); + +#endif /* _COUNTER_SYSFS_H_ */
drivers/counter/counter.c deleted +0 -1496
1,176 lines not on this page · raw message
drivers/counter/ftm-quaddec.c +23 -33
56 lines not on this page · raw message
drivers/counter/intel-qep.c +61 -83
144 lines not on this page · raw message
drivers/counter/interrupt-cnt.c +26 -36
62 lines not on this page · raw message
drivers/counter/microchip-tcb-capture.c +40 -53
93 lines not on this page · raw message
drivers/counter/stm32-lptimer-cnt.c +79 -83
162 lines not on this page · raw message
drivers/counter/stm32-timer-cnt.c +59 -88
147 lines not on this page · raw message
drivers/counter/ti-eqep.c +98 -82
180 lines not on this page · raw message
include/linux/counter.h +326 -303
629 lines not on this page · raw message
include/linux/counter_enum.h deleted +0 -45
45 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.32.0
Part of the diff is not shown here. View the raw message.
Jonathan Cameron
maintainerRe: [RESEND PATCH v11 22/33] counter: Internalize sysfs interface code
Quoted 36 lines · On Wed, 9 Jun 2021 23:11:45 +0900 William Breathitt Gray…
This is a reimplementation of the Generic Counter driver interface. There are no modifications to the Counter subsystem userspace interface, so existing userspace applications should continue to run seamlessly.
The purpose of this patch is to internalize the sysfs interface code among the various counter drivers into a shared module. Counter drivers pass and take data natively (i.e. u8, u64, etc.) and the shared counter module handles the translation between the sysfs interface and the device drivers. This guarantees a standard userspace interface for all counter drivers, and helps generalize the Generic Counter driver ABI in order to support the Generic Counter chrdev interface (introduced in a subsequent patch) without significant changes to the existing counter drivers.
Note, Counter device registration is the same as before: drivers populate a struct
counter_devicewith components and callbacks, then pass the structure to thedevm_counter_registerfunction. However, what's different now is how the Counter subsystem code handles this registration internally.Whereas before callbacks would interact directly with sysfs data, this interaction is now abstracted and instead callbacks interact with native C data types. The
counter_compstructure forms the basis for Counter extensions.The
counter-sysfs.cfile contains the code to parse through thecounter_devicestructure and register the requested components and extensions. Attributes are created and populated based on type, with respective translation functions to handle the mapping between sysfs and the counter driver callbacks.The translation performed for each attribute is straightforward: the attribute type and data is parsed from the
counter_attributestructure, the respective counter driver read/write callback is called, and sysfs I/O is handled before or after the driver read/write function is called.
Quoted 11 lines
Cc Syed Nayyar Waris <[email protected]>Cc Jarkko Nikula <[email protected]>Cc Patrick Havelange <[email protected]>Cc Kamel Bouhara <[email protected]>Cc Fabrice Gasnier <[email protected]>Cc Maxime Coquelin <[email protected]>Cc Alexandre Torgue <[email protected]>Cc Dan Carpenter <[email protected]>Reviewed-by David Lechner <[email protected]>Tested-by David Lechner <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Given you will probably do a v12 anyway, a few comments inline.
Jonathan
Quoted 24 lines
--- MAINTAINERS | 1 - drivers/counter/104-quad-8.c | 449 +++---- drivers/counter/Makefile | 1 + drivers/counter/counter-core.c | 155 +++ drivers/counter/counter-sysfs.c | 846 +++++++++++++ drivers/counter/counter-sysfs.h | 13 + drivers/counter/counter.c | 1496 ----------------------- drivers/counter/ftm-quaddec.c | 56 +- drivers/counter/intel-qep.c | 144 +-- drivers/counter/interrupt-cnt.c | 62 +- drivers/counter/microchip-tcb-capture.c | 93 +- drivers/counter/stm32-lptimer-cnt.c | 162 ++- drivers/counter/stm32-timer-cnt.c | 147 +-- drivers/counter/ti-eqep.c | 180 +-- include/linux/counter.h | 629 +++++----- include/linux/counter_enum.h | 45 - 16 files changed, 1918 insertions(+), 2561 deletions(-) create mode 100644 drivers/counter/counter-core.c create mode 100644 drivers/counter/counter-sysfs.c create mode 100644 drivers/counter/counter-sysfs.h delete mode 100644 drivers/counter/counter.c delete mode 100644 include/linux/counter_enum.h
...
Quoted 24 lines
drivers/counter/counter-core.c new file +18
-0@@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Generic Counter interface +* Copyright (C) 2020 William Breathitt Gray +*/ +#include <linux/counter.h> +#include <linux/device.h> +#include <linux/export.h> +#include <linux/gfp.h> +#include <linux/idr.h> +#include <linux/init.h> +#include <linux/module.h> + +#include "counter-sysfs.h" + +/* Provides a unique ID for each counter device */ +static DEFINE_IDA (counter_ida); +
...
Quoted 35 lines
drivers/counter/counter-core.c new file +35
-0+int counter_register (struct counter_device *const counter) +{ +struct device *const dev = &counter->dev; +int id; +int err; + +/* Acquire unique ID */ + id =ida_alloc (&counter_ida,GFP_KERNEL ); +if (id <0 ) +return id; + +/* Configure device structure for Counter */ + dev->id = id; + dev->type = &counter_device_type; + dev->bus = &counter_bus_type; +if (counter->parent) { + dev->parent = counter->parent; + dev->of_node = counter->parent->of_node; + } +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); +if (err <0 ) + goto err_free_id; + +return 0 ; + +err_free_id:
drivers/counter/counter-core.c line 89
Quoted 10 lines
drivers/counter/counter-core.c new file +10
-0+put_device (dev); +return err; +} +EXPORT_SYMBOL_GPL (counter_register); + +/** +* counter_unregister - unregister Counter from the system +* @counter: pointer to Counter to unregister +* +* The Counter is unregistered from the system; all allocated memory is freed.
If we are being fussy. This isn't necessarily true. If the reference goes down to 0 it will be freed, but in theory that could happen later than this call. I'm guessing we will have get_device() calls once the chrdev is in place.
Quoted 26 lines
+ */
drivers/counter/counter-core.c new file +25
-0+void counter_unregister (struct counter_device *const counter) +{ +if (!counter) +return ; + +device_unregister (&counter->dev); +} +EXPORT_SYMBOL_GPL (counter_unregister); + +static void devm_counter_release (struct device *dev,void *res) +{ +counter_unregister (*(struct counter_device **)res); +} + +/** +* devm_counter_register - Resource-managed counter_register +* @dev: device to allocate counter_device for +* @counter: pointer to Counter to register +* +* Managed counter_register. The Counter registered with this function is +* automatically unregistered on driver detach. This function calls +* counter_register internally. Refer to that function for more information. +* +* RETURNS: +* 0 on success, negative error number on failure.
drivers/counter/counter-core.c line 125
Quoted 10 lines
drivers/counter/counter-core.c new file +10
-0+*/ +int devm_counter_register (struct device *dev, +struct counter_device *const counter) +{ +struct counter_device **ptr; +int err; + + ptr =devres_alloc (devm_counter_release,sizeof (*ptr),GFP_KERNEL ); +if (!ptr) +return -ENOMEM ;
If you look at how devm_iio_device_register() is now done in
the togreg branch of iio.git, you'll see it now just uses devm_add_action_or_reset() internally. I think you could do something similar here and reduce boilerplate a little.
Quoted 54 lines
drivers/counter/counter-core.c new file +30
-0+ + err =counter_register (counter); +if (err <0 ) { +devres_free (ptr); +return err; + } + + *ptr = counter; +devres_add (dev, ptr); + +return 0 ; +} +EXPORT_SYMBOL_GPL (devm_counter_register); + +static int __init counter_init (void ) +{ +return bus_register (&counter_bus_type); +} + +static void __exit counter_exit(void) +{ +bus_unregister (&counter_bus_type); +} + +subsys_initcall (counter_init); +module_exit (counter_exit); + +MODULE_AUTHOR ("William Breathitt Gray <[email protected]>" ); +MODULE_DESCRIPTION ("Generic Counter interface" ); +MODULE_LICENSE ("GPL v2" );drivers/counter/counter-sysfs.c new file +17
-0@@ -0,0 +1,846 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Generic Counter sysfs interface +* Copyright (C) 2020 William Breathitt Gray +*/ +#include <linux/counter.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/gfp.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/string.h> +#include <linux/sysfs.h> +#include <linux/types.h> + +#include "counter-sysfs.h" +
...
PATCH v11 23/33 counter: Update counter.h comments to reflect sysfs internalization
In reply to William Breathitt GrayThe Counter subsystem architecture and driver implementations have changed in order to handle Counter sysfs interactions in a more consistent way. This patch updates the Generic Counter interface header file comments to reflect the changes.
--- drivers/counter/counter-core.c | 3 ++ include/linux/counter.h | 72 +++++++++++++++------------------- 2 files changed, 35 insertions(+), 40 deletions(-)
drivers/counter/counter-core.c +3 -0
@@ -41,6 +41,9 @@ static struct bus_type counter_bus_type = {* This function registers a Counter to the system. A sysfs "counter" directory * will be created and populated with sysfs attributes correlating with the * Counter Signals, Synapses, and Counts respectively. +* +* RETURNS: +* 0 on success, negative error number on failure. */ int counter_register (struct counter_device *const counter) {
include/linux/counter.h +32 -40
104 lines not on this page · raw message
Signature · 1 line
2.32.0
Jonathan Cameron
maintainerRe: [PATCH v11 23/33] counter: Update counter.h comments to reflect sysfs internalization
Quoted 6 lines · On Wed, 9 Jun 2021 10:31:26 +0900 William Breathitt Gray…
The Counter subsystem architecture and driver implementations have changed in order to handle Counter sysfs interactions in a more consistent way. This patch updates the Generic Counter interface header file comments to reflect the changes.
Signed-off-by William Breathitt Gray <[email protected]>
I'd rather see anything in here that isn't just tidy up moved back to the earlier patches.
Quoted 27 lines
--- drivers/counter/counter-core.c | 3 ++ include/linux/counter.h | 72 +++++++++++++++------------------- 2 files changed, 35 insertions(+), 40 deletions(-)drivers/counter/counter-core.c +3
-0@@ -41,6 +41,9 @@ static struct bus_type counter_bus_type = {* This function registers a Counter to the system. A sysfs "counter" directory * will be created and populated with sysfs attributes correlating with the * Counter Signals, Synapses, and Counts respectively. +* +* RETURNS: +* 0 on success, negative error number on failure. */ int counter_register (struct counter_device *const counter) {include/linux/counter.h +0
-0@@ -188,12 +188,10 @@ struct counter_comp {/** * struct counter_signal - Counter Signal node
include/linux/counter.h struct counter_comp { · line 194
Quoted 10 lines
include/linux/counter.h +4
-6-* @id: unique ID used to identify signal -* @name: device-specific Signal name; ideally, this should match the name -* as it appears in the datasheet documentation -* @ext: optional array of Counter Signal extensions -* @num_ext: number of Counter Signal extensions specified in @ext -* @priv: optional private data supplied by driver +* @id: unique ID used to identify the Signal +* @name: device-specific Signal name +* @ext: optional array of Signal extensions +* @num_ext: number of Signal extensions specified in @ext
I'm not keen on having a stage between patches where there area things documented that don't exist. (e.g. priv)
Quoted 95 lines
include/linux/counter.h +28
-34*/ struct counter_signal {int id;@@ -207,7 +205,7 @@ struct counter_signal {* struct counter_synapse - Counter Synapse node * @actions_list: array of available action modes * @num_actions: number of action modes specified in @actions_list -* @signal: pointer to associated signal +* @signal: pointer to the associated Signal */ struct counter_synapse {const enum counter_synapse_action *actions_list;@@ -218,17 +216,14 @@ struct counter_synapse {/** * struct counter_count - Counter Count node -* @id: unique ID used to identify Count -* @name: device-specific Count name; ideally, this should match -* the name as it appears in the datasheet documentation -* @function: index of current function mode -* @functions_list: array available function modes +* @id: unique ID used to identify the Count +* @name: device-specific Count name +* @functions_list: array of available function modes * @num_functions: number of function modes specified in @functions_list -* @synapses: array of synapses for initialization -* @num_synapses: number of synapses specified in @synapses -* @ext: optional array of Counter Count extensions -* @num_ext: number of Counter Count extensions specified in @ext -* @priv: optional private data supplied by driver +* @synapses: array of Synapses for initialization +* @num_synapses: number of Synapses specified in @synapses +* @ext: optional array of Count extensions +* @num_ext: number of Count extensions specified in @ext */ struct counter_count {int id;@@ -246,29 +241,26 @@ struct counter_count {/** * struct counter_ops - Callbacks from driver -* @signal_read: optional read callback for Signal attribute. The read -* level of the respective Signal should be passed back via -* the level parameter. -* @count_read: optional read callback for Count attribute. The read -* value of the respective Count should be passed back via -* the val parameter. -* @count_write: optional write callback for Count attribute. The write -* value for the respective Count is passed in via the val +* @signal_read: read callback for Signals. The read level of the +* respective Signal should be passed back via the level +* parameter. +* @count_read: read callback for Counts. The read value of the +* respective Count should be passed back via the value * parameter. -* @function_get: function to get the current count function mode. Returns -* 0 on success and negative error code on error. The index -* of the respective Count's returned function mode should -* be passed back via the function parameter. -* @function_set: function to set the count function mode. function is the -* index of the requested function mode from the respective -* Count's functions_list array. -* @action_get: function to get the current action mode. Returns 0 on -* success and negative error code on error. The index of -* the respective Synapse's returned action mode should be -* passed back via the action parameter. -* @action_set: function to set the action mode. action is the index of -* the requested action mode from the respective Synapse's -* actions_list array. +* @count_write: write callback for Counts. The write value for the +* respective Count is passed in via the value parameter. +* @function_read: read callback the Count function modes. The read +* function mode of the respective Count should be passed +* back via the function parameter. +* @function_write: write callback for Count function modes. The function +* mode to write for the respective Count is passed in via +* the function parameter. +* @action_read: read callback the Synapse action modes. The read action +* mode of the respective Synapse should be passed back via +* the action parameter. +* @action_write: write callback for Synapse action modes. The action mode +* to write for the respective Synapse is passed in via the +* action parameter. */ struct counter_ops { int (*signal_read)(struct counter_device *counter,@@ -296,7 +288,7 @@ struct counter_ops {/** * struct counter_device - Counter data structure -* @name: name of the device as it appears in the datasheet +* @name: name of the device * @parent: optional parent device providing the counters * @ops: callbacks from driver * @signals: array of Signals
PATCH v11 24/33 docs: counter: Update to reflect sysfs internalization
In reply to William Breathitt GrayThe Counter subsystem architecture and driver implementations have changed in order to handle Counter sysfs interactions in a more consistent way. This patch updates the Generic Counter interface documentation to reflect the changes.
--- Documentation/ABI/testing/sysfs-bus-counter | 9 +- Documentation/driver-api/generic-counter.rst | 243 ++++++++++++++----- 2 files changed, 185 insertions(+), 67 deletions(-)
Documentation/ABI/testing/sysfs-bus-counter +8 -1
@@ -286,7 +286,14 @@ What: /sys/bus/counter/devices/counterX/signalY/signal KernelVersion: 5.2 Contact: [email protected] Description: - Signal data of Signal Y represented as a string. + Signal level state of Signal Y. The following signal level + states are available: + + low: + Low level state. + + high: + High level state. What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode KernelVersion: 5.2
Documentation/driver-api/generic-counter.rst +177 -66
262 lines not on this page · raw message
Signature · 1 line
2.32.0
PATCH v11 25/33 counter: Move counter enums to uapi header
In reply to William Breathitt GrayThis is in preparation for a subsequent patch implementing a character device interface for the Counter subsystem.
--- 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
MAINTAINERS +1 -0
@@ -4678,6 +4678,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 <[email protected]>
include/linux/counter.h +1 -41
54 lines not on this page · raw message
include/uapi/linux/counter.h new file +56 -0
56 lines not on this page · raw message
Signature · 1 line
2.32.0
PATCH v11 26/33 counter: Add character device interface
In reply to William Breathitt GrayThis 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.
--- drivers/counter/Makefile | 2 +- drivers/counter/counter-chrdev.c | 482 +++++++++++++++++++++++++++++++ drivers/counter/counter-chrdev.h | 14 + drivers/counter/counter-core.c | 44 ++- include/linux/counter.h | 45 +++ include/uapi/linux/counter.h | 77 +++++ 6 files changed, 658 insertions(+), 6 deletions(-) create mode 100644 drivers/counter/counter-chrdev.c create mode 100644 drivers/counter/counter-chrdev.h
drivers/counter/Makefile +1 -1
@@ -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
drivers/counter/counter-chrdev.c new file +482 -0
482 lines not on this page · raw message
drivers/counter/counter-chrdev.h new file +14 -0
@@ -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 <linux/counter.h> + +int counter_chrdev_add (struct counter_device *const counter); +void counter_chrdev_remove (struct counter_device *const counter); + +#endif /* _COUNTER_CHRDEV_H_ */
drivers/counter/counter-core.c +39 -5
103 lines not on this page · raw message
include/linux/counter.h +45 -0
90 lines not on this page · raw message
include/uapi/linux/counter.h +77 -0
89 lines not on this page · raw message
Signature · 1 line
2.32.0
Re: [PATCH v11 26/33] counter: Add character device interface
drivers/counter/counter-chrdev.c line 104
Quoted 7 lines · William Breathitt Gray
drivers/counter/counter-chrdev.c new file +7
-0+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; +struct counter_comp_node *comp_node; +
The caller should be holding the counter->events_list_lock lock but it's not.
Quoted 59 lines
drivers/counter/counter-chrdev.c new file +59
-0+/* 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_ATOMIC ); +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 && + comp_node->comp.count_u8_read == cfg->comp.count_u8_read) +return -EINVAL ; + +/* Allocate component node */ + comp_node =kmalloc (sizeof (*comp_node),GFP_ATOMIC ); +if (!comp_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 -ENOMEM ; + } + *comp_node = *cfg; + +/* Add component node to event node */ +list_add_tail (&comp_node->l, &event_node->comp_list); + +return 0 ; +} + +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); + +counter_events_list_free (&counter->next_events_list);
drivers/counter/counter-chrdev.c line 173
Quoted 10 lines
drivers/counter/counter-chrdev.c new file +10
-0+ +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 = {0 };
Always use = {};. It's the new hotness, and it avoids a Sparse warning for using 0 instead of NULL. #IDidNotTest #CouldBeWrongAboutSparse
drivers/counter/counter-chrdev.c line 178
Quoted 5 lines
drivers/counter/counter-chrdev.c new file +5
-0+size_t parent, id; +struct counter_comp *ext; +size_t num_ext; +int err; +
regards,
dan carpenter
Re: [PATCH v11 26/33] counter: Add character device interface
Quoted 11 lines · Dan Carpenter
drivers/counter/counter-chrdev.c line 104
Quoted 7 lines · William Breathitt Gray
drivers/counter/counter-chrdev.c new file +7
-0+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; +struct counter_comp_node *comp_node; +The caller should be holding the
counter->events_list_locklock but it's not.
Hi Dan,
The counter_set_event_node() function doesn't access or modify counter->events_list (it works on counter->next_events_list) so holding the counter->events_list_lock here isn't necessary.
Quoted 64 lines
Quoted 64 lines
drivers/counter/counter-chrdev.c new file +64
-0+/* 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_ATOMIC ); +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 && + comp_node->comp.count_u8_read == cfg->comp.count_u8_read) +return -EINVAL ; + +/* Allocate component node */ + comp_node =kmalloc (sizeof (*comp_node),GFP_ATOMIC ); +if (!comp_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 -ENOMEM ; + } + *comp_node = *cfg; + +/* Add component node to event node */ +list_add_tail (&comp_node->l, &event_node->comp_list); + +return 0 ; +} + +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); + +counter_events_list_free (&counter->next_events_list); + +return err; +} + +static int counter_add_watch(struct counter_device *const counter,
Quoted 8 lines
drivers/counter/counter-chrdev.c line 173
Quoted 5 lines
drivers/counter/counter-chrdev.c new file +5
-0+ const unsigned long arg) +{ +void __user *const uwatch = (void __user *)arg; +struct counter_watch watch; +struct counter_comp_node comp_node = {0 };Always use = {};. It's the new hotness, and it avoids a Sparse warning for using 0 instead of NULL. #IDidNotTest #CouldBeWrongAboutSparse
Thanks for the heads-up! I think this is the only patch where I have this, so I'll hold off submitting a v12 for just this change unless something else comes up with this patchset (I can fix this spare warning in a subsequent patch).
William Breathitt Gray
Re: [PATCH v11 26/33] counter: Add character device interface
Quoted 13 lines · William Breathitt Gray
Quoted 11 lines · Dan Carpenter
drivers/counter/counter-chrdev.c line 104
Quoted 7 lines · William Breathitt Gray
drivers/counter/counter-chrdev.c new file +7
-0+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; +struct counter_comp_node *comp_node; +The caller should be holding the
counter->events_list_locklock but it's not.
Quoted 6 lines
Hi Dan,
The
counter_set_event_node()function doesn't access or modifycounter->events_list(it works oncounter->next_events_list) so holding thecounter->events_list_lockhere isn't necessary.
There needs to be some sort of locking or this function can race with itself. (Two threads add the same event at exactly the same time). It looks like it can also race with counter_disable_events() leading to a use after free.
Quoted 10 lines
Quoted 10 lines
drivers/counter/counter-chrdev.c line 114
Quoted 10 lines
drivers/counter/counter-chrdev.c new file +10
-0+/* 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_ATOMIC );
Btw, say we decided that we can add/remove events locklessly, then these GFP_ATOMICs can be changed to GFP_KERNEL.
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
drivers/counter/counter-chrdev.c new file +10
-0+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); + } +
Quoted 8 lines
Quoted 8 lines
drivers/counter/counter-chrdev.c line 132
Quoted 8 lines
drivers/counter/counter-chrdev.c new file +8
-0+/* 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 && + comp_node->comp.count_u8_read == cfg->comp.count_u8_read) +return -EINVAL ; + +/* Allocate component node */ + comp_node =kmalloc (sizeof (*comp_node),GFP_ATOMIC );
^^^^^^^^^^
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/counter/counter-chrdev.c new file +7
-0+if (!comp_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 -ENOMEM ;
Quoted 8 lines
Quoted 8 lines
drivers/counter/counter-chrdev.c line 147
Quoted 8 lines
drivers/counter/counter-chrdev.c new file +8
-0+ } + *comp_node = *cfg; + +/* Add component node to event node */ +list_add_tail (&comp_node->l, &event_node->comp_list); + +return 0 ; +}
regards,
dan carpenter
Re: [PATCH v11 26/33] counter: Add character device interface
Quoted 21 lines · Dan Carpenter
Quoted 13 lines · William Breathitt Gray
Quoted 11 lines · Dan Carpenter
drivers/counter/counter-chrdev.c line 104
Quoted 7 lines · William Breathitt Gray
drivers/counter/counter-chrdev.c new file +7
-0+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; +struct counter_comp_node *comp_node; +The caller should be holding the
counter->events_list_locklock but it's not.Quoted 6 lines
Hi Dan,
The
counter_set_event_node()function doesn't access or modifycounter->events_list(it works oncounter->next_events_list) so holding thecounter->events_list_lockhere isn't necessary.
Quoted 4 lines
There needs to be some sort of locking or this function can race with itself. (Two threads add the same event at exactly the same time). It looks like it can also race with
counter_disable_events()leading to a use after free.
All right, I'll add in a lock to protect this function so it doesn't race with itself nor counter_disable_events().
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
drivers/counter/counter-chrdev.c new file +5
-0+/* 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 ;
Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
drivers/counter/counter-chrdev.c line 114
Quoted 5 lines
drivers/counter/counter-chrdev.c new file +5
-0+ +/* 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_ATOMIC );Btw, say we decided that we can add/remove events locklessly, then these
GFP_ATOMICscan be changed toGFP_KERNEL.
Because I'll be using a lock I'll keep these as GFP_ATOMICs afterall.
Thanks,
William Breathitt Gray
PATCH v11 27/33 docs: counter: Document character device interface
In reply to William Breathitt GrayThis patch adds high-level documentation about the Counter subsystem character device interface.
--- Documentation/driver-api/generic-counter.rst | 185 ++++++++++++++---- .../userspace-api/ioctl/ioctl-number.rst | 1 + 2 files changed, 145 insertions(+), 41 deletions(-)
Documentation/driver-api/generic-counter.rst +144 -41
@@ -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,112 @@ 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 data 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 4 -- 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: + +* COUNTER_ADD_WATCH_IOCTL: + Queues a Counter watch for the specified event. The queued watches + will not be applied until ``COUNTER_ENABLE_EVENTS_IOCTL`` is called. + +* COUNTER_ENABLE_EVENTS_IOCTL: + 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``. + +* COUNTER_DISABLE_EVENTS_IOCTL: + Stops monitoring the previously enabled events. + +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.
Documentation/userspace-api/ioctl/ioctl-number.rst +1 -0
@@ -88,6 +88,7 @@ Code Seq# Include File Comments <http://infiniband.sourceforge.net/> 0x20 all drivers/cdrom/cm206.h 0x22 all scsi/sg.h +0x3E 00-0F linux/counter.h <mailto:[email protected]> '!' 00-1F uapi/linux/seccomp.h '#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem
Signature · 1 line
2.32.0
PATCH v11 28/33 tools/counter: Create Counter tools
In reply to William Breathitt GrayThis creates an example Counter program under tools/counter/* to exemplify the Counter character device interface.
--- MAINTAINERS | 1 + tools/Makefile | 13 ++--- tools/counter/Build | 1 + tools/counter/Makefile | 53 ++++++++++++++++++ tools/counter/counter_example.c | 95 +++++++++++++++++++++++++++++++++ 5 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 tools/counter/Build create mode 100644 tools/counter/Makefile create mode 100644 tools/counter/counter_example.c
MAINTAINERS +1 -0
@@ -4679,6 +4679,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 <[email protected]>
tools/Makefile +7 -6
@@ -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 \
tools/counter/Build new file +1 -0
@@ -0,0 +1 @@ +counter_example-y += counter_example.o
tools/counter/Makefile new file +53 -0
53 lines not on this page · raw message
tools/counter/counter_example.c new file +95 -0
95 lines not on this page · raw message
Signature · 1 line
2.32.0
PATCH v11 29/33 counter: Implement signalZ_action_component_id sysfs attribute
In reply to William Breathitt GrayThe 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.
--- Documentation/ABI/testing/sysfs-bus-counter | 7 ++++ drivers/counter/counter-sysfs.c | 45 +++++++++++++++++++++ 2 files changed, 52 insertions(+)
Documentation/ABI/testing/sysfs-bus-counter +7 -0
@@ -203,6 +203,13 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/countY/signalZ_action_component_id +KernelVersion: 5.15 +Contact: [email protected] +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: [email protected]
drivers/counter/counter-sysfs.c +45 -0
57 lines not on this page · raw message
Signature · 1 line
2.32.0
PATCH v11 30/33 counter: Implement *_component_id sysfs attributes
In reply to William Breathitt GrayThe 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.
--- Documentation/ABI/testing/sysfs-bus-counter | 16 ++++++++++- drivers/counter/counter-sysfs.c | 30 ++++++++++++++++----- 2 files changed, 39 insertions(+), 7 deletions(-)
Documentation/ABI/testing/sysfs-bus-counter +15 -1
@@ -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.15 Contact: [email protected] 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
drivers/counter/counter-sysfs.c +24 -6
@@ -587,6 +587,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;
@@ -602,8 +603,13 @@ 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, group, signal->ext + i, scope, - signal); + ext = signal->ext + i; + + err =counter_attr_create (dev, group, ext, scope, signal); +if (err <0 ) +return err; + + err =counter_comp_id_attr_create (dev, group, ext->name, i);if (err <0 )return err; }
@@ -694,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;
@@ -718,8 +725,13 @@ 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, group, count->ext + i, scope, - count); + ext = count->ext + i; + + err =counter_attr_create (dev, group, ext, scope, count); +if (err <0 ) +return err; + + err =counter_comp_id_attr_create (dev, group, ext->name, i);if (err <0 )return err; }
@@ -783,6 +795,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, group);
@@ -815,8 +828,13 @@ 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, group, counter->ext + i, scope, -NULL ); + ext = counter->ext + i; + + err =counter_attr_create (dev, group, ext, scope,NULL ); +if (err <0 ) +return err; + + err =counter_comp_id_attr_create (dev, group, ext->name, i);if (err <0 )return err; }
Signature · 1 line
2.32.0
PATCH v11 31/33 counter: Implement events_queue_size sysfs attribute
In reply to William Breathitt GrayThe 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.
--- Documentation/ABI/testing/sysfs-bus-counter | 8 ++++ drivers/counter/counter-chrdev.c | 4 ++ drivers/counter/counter-sysfs.c | 44 +++++++++++++++++++++ include/linux/counter.h | 2 + 4 files changed, 58 insertions(+)
Documentation/ABI/testing/sysfs-bus-counter +8 -0
@@ -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.15 +Contact: [email protected] +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: [email protected]
drivers/counter/counter-chrdev.c +4 -0
@@ -311,6 +311,9 @@ static int counter_chrdev_open(struct inode *inode, struct file *filp)typeof (*counter), chrdev); +if (!mutex_trylock (&counter->chrdev_lock)) +return -EBUSY ; +get_device (&counter->dev); filp->private_data = counter;
@@ -327,6 +330,7 @@ static int counter_chrdev_release(struct inode *inode, struct file *filp)return err;put_device (&counter->dev); +mutex_unlock (&counter->chrdev_lock);return 0 ; }
drivers/counter/counter-sysfs.c +44 -0
69 lines not on this page · raw message
include/linux/counter.h +2 -0
@@ -289,6 +289,7 @@ struct counter_ops {* @priv: optional private data supplied by driver * @dev: internal device structure * @chrdev: internal character device structure +* @chrdev_lock: lock to limit chrdev to a single open at a time * @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
@@ -314,6 +315,7 @@ struct counter_device {struct device dev;struct cdev chrdev; +struct mutex chrdev_lock;struct list_head events_list;spinlock_t events_list_lock;struct list_head next_events_list;
Signature · 1 line
2.32.0
PATCH v11 32/33 counter: 104-quad-8: Replace mutex with spinlock
In reply to William Breathitt GrayThis 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.
--- drivers/counter/104-quad-8.c | 90 +++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 37 deletions(-)
drivers/counter/104-quad-8.c +53 -37
@@ -16,6 +16,7 @@#include <linux/module.h> #include <linux/moduleparam.h> #include <linux/types.h> +#include <linux/spinlock.h> #define QUAD8_EXTENT 32
@@ -28,6 +29,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");/** * struct quad8 - device private data structure +* @lock: lock to prevent clobbering device states during R/W ops * @counter: instance of the counter_device * @fck_prescaler: array of filter clock prescaler configurations * @preset: array of preset values
@@ -42,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 ];
@@ -123,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 );
@@ -132,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,
@@ -141,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 ; }
@@ -151,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 );
@@ -182,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 ; }
@@ -200,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]) {
@@ -218,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 ; }
@@ -233,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 ;
@@ -271,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 ; } }
@@ -279,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 ; }
@@ -405,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];
@@ -416,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 ; }
@@ -445,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 ; }
@@ -462,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 ; }
@@ -509,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) {
@@ -529,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;
@@ -543,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 ; }
@@ -563,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;
@@ -574,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 ; }
@@ -625,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 ; }
@@ -643,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]) {
@@ -658,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 ; }
@@ -667,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 : -mutex_unlock (&priv->lock); +spin_unlock_irqrestore (&priv->lock, irqflags);quad8_preset_register_set (priv, count->id, ceiling);return 0 ; } -mutex_unlock (&priv->lock); +spin_unlock_irqrestore (&priv->lock, irqflags);return -EINVAL ; }
@@ -705,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;
@@ -719,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 ; }
@@ -730,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));
@@ -771,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);
@@ -785,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 ; }
@@ -808,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;
@@ -821,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 ; }
@@ -990,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 );
Signature · 1 line
2.32.0
PATCH v11 33/33 counter: 104-quad-8: Add IRQ support for the ACCES 104-QUAD-8
In reply to William Breathitt GrayThe 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.
--- drivers/counter/104-quad-8.c | 167 +++++++++++++++++++++++++++++++++-- drivers/counter/Kconfig | 6 +- 2 files changed, 164 insertions(+), 9 deletions(-)
drivers/counter/104-quad-8.c +161 -6
@@ -11,6 +11,7 @@#include <linux/errno.h> #include <linux/io.h> #include <linux/ioport.h> +#include <linux/interrupt.h> #include <linux/isa.h> #include <linux/kernel.h> #include <linux/module.h>
@@ -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); }
drivers/counter/Kconfig +3 -3
@@ -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"
Signature · 1 line
2.32.0
Jonathan Cameron
maintainerRe: [PATCH v11 33/33] counter: 104-quad-8: Add IRQ support for the ACCES 104-QUAD-8
Quoted 32 lines · On Wed, 9 Jun 2021 10:31:36 +0900 William Breathitt Gray…
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, andCOUNTER_EVENT_INDEX. Interrupts push Counter events to event channel X, where 'X' is the respective channel whose FLG1 activated.
Quoted 6 lines
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.
Signed-off-by William Breathitt Gray <[email protected]>
I've taken a look at the remainder of the patches I haven't commented on an I think they are all fine.
Of course good to get more eyes on this if possible though and perhaps a few more reviews of the interfaces at least from the various counter driver maintainers.
Thanks,
Jonathan
Quoted 294 lines
--- drivers/counter/104-quad-8.c | 167 +++++++++++++++++++++++++++++++++-- drivers/counter/Kconfig | 6 +- 2 files changed, 164 insertions(+), 9 deletions(-)drivers/counter/104-quad-8.c +161
-6@@ -11,6 +11,7 @@#include <linux/errno.h> #include <linux/io.h> #include <linux/ioport.h> +#include <linux/interrupt.h> #include <linux/isa.h> #include <linux/kernel.h> #include <linux/module.h> @@ -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); }drivers/counter/Kconfig +3
-3@@ -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"
Quoted 10 lines · On Wed, 9 Jun 2021 10:31:03 +0900 William Breathitt Gray…
Changes in v11:
- Migrated Intel QEP to new interface
- Context adjustments made for documentationI pulled out a lot of bits and pieces to their own patches; hopefully that makes reviewing this patchset much simpler than before. This patchset is also available on my personal public git repo for anyone who wants a quick way to clone:
https://gitlab.com/vilhelmgray/iio/-/tree/counter_chrdev_v11
Quoted 5 lines
The patches preceding "counter: Internalize sysfs interface code" are primarily cleanup and fixes that can be picked up and applied now to the IIO tree if so desired. The "counter: Internalize sysfs interface code" patch as well may be considered for pickup because it is relatively safe and makes no changes to the userspace interface.
Let us aim to do that in the interests of cutting down on the volume for future versions!
However, it is made tricky by the fact patch 22 hasn't made it to me or lore.kernel.org. Could you send that one again. Hopefully the in-reply-to will ensure it's correctly threaded.
Jonathan
Quoted 99 lines
To summarize the main points of this patchset: there are no changes to the existing Counter sysfs userspace interface; a Counter character device interface is introduced that allows Counter events and associated data to be
read()by userspace; theevents_configure()andwatch_validate()driver callbacks are introduced to support Counter events; and IRQ support is added to the 104-QUAD-8 driver, serving as an example of how to support the new Counter events functionality.Something that should still be discussed: should the struct
counter_event"status" member be 8 bits or 32 bits wide? This member will provide the return status (system error number) of an event operation.William Breathitt Gray (33):
docs: counter: Consolidate Counter sysfs attributes documentation
docs: counter: Fix spelling
counter: 104-quad-8: Remove pointless comment
counter: 104-quad-8: Return error when invalid mode during
ceiling_write
counter: 104-quad-8: Annotate hardware config module parameter
counter: 104-quad-8: Add const qualifiers for
quad8_preset_register_set
counter: 104-quad-8: Add const qualifier forfunctions_listarray
counter: interrupt-cnt: Add const qualifier forfunctions_listarray
counter: microchip-tcb-capture: Add const qualifier forfunctions_list
array
counter: stm32-lptimer-cnt: Add const qualifier forfunctions_list
array
counter: stm32-timer-cnt: Add const qualifier forfunctions_listarray
counter: 104-quad-8: Add const qualifier foractions_listarray
counter: ftm-quaddec: Add const qualifier foractions_listarray
counter: interrupt-cnt: Add const qualifier foractions_listarray
counter: microchip-tcb-capture: Add const qualifier foractions_list
array
counter: stm32-lptimer-cnt: Add const qualifier foractions_listarray
counter: stm32-timer-cnt: Add const qualifier foractions_listarray
counter: Return error code on invalid modes
counter: Standardize to ERANGE for limit exceeded errors
counter: Renamecounter_signal_valuetocounter_signal_level
counter: Renamecounter_count_functiontocounter_function
counter: Internalize sysfs interface code
counter: Updatecounter.hcomments to reflect sysfs internalization
docs: counter: Update to reflect sysfs internalization
counter: Move counter enums to uapi header
counter: Add character device interface
docs: counter: Document character device interfacetools/counter: Create Counter tools
counter: ImplementsignalZ_action_component_idsysfs attribute
counter: Implement*_component_idsysfs attributes
counter: Implementevents_queue_sizesysfs attribute
counter: 104-quad-8: Replace mutex with spinlock
counter: 104-quad-8: Add IRQ support for the ACCES 104-QUAD-8Documentation/ABI/testing/sysfs-bus-counter | 112 +- .../ABI/testing/sysfs-bus-counter-104-quad-8 | 61 - .../ABI/testing/sysfs-bus-counter-ftm-quaddec | 16 - Documentation/driver-api/generic-counter.rst | 368 +++- .../userspace-api/ioctl/ioctl-number.rst | 1 + MAINTAINERS | 7 +- drivers/counter/104-quad-8.c | 739 ++++---- drivers/counter/Kconfig | 6 +- drivers/counter/Makefile | 1 + drivers/counter/counter-chrdev.c | 486 ++++++ drivers/counter/counter-chrdev.h | 14 + drivers/counter/counter-core.c | 192 +++ drivers/counter/counter-sysfs.c | 953 +++++++++++ drivers/counter/counter-sysfs.h | 13 + drivers/counter/counter.c | 1496 ----------------- drivers/counter/ftm-quaddec.c | 61 +- drivers/counter/intel-qep.c | 150 +- drivers/counter/interrupt-cnt.c | 75 +- drivers/counter/microchip-tcb-capture.c | 105 +- drivers/counter/stm32-lptimer-cnt.c | 176 +- drivers/counter/stm32-timer-cnt.c | 149 +- drivers/counter/ti-eqep.c | 221 +-- include/linux/counter.h | 716 ++++---- include/linux/counter_enum.h | 45 - include/uapi/linux/counter.h | 133 ++ tools/Makefile | 13 +- tools/counter/Build | 1 + tools/counter/Makefile | 53 + tools/counter/counter_example.c | 95 ++ 29 files changed, 3586 insertions(+), 2872 deletions(-) delete mode 100644 Documentation/ABI/testing/sysfs-bus-counter-104-quad-8 delete mode 100644 Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec create mode 100644 drivers/counter/counter-chrdev.c create mode 100644 drivers/counter/counter-chrdev.h create mode 100644 drivers/counter/counter-core.c create mode 100644 drivers/counter/counter-sysfs.c create mode 100644 drivers/counter/counter-sysfs.h delete mode 100644 drivers/counter/counter.c delete mode 100644 include/linux/counter_enum.h create mode 100644 include/uapi/linux/counter.h create mode 100644 tools/counter/Build create mode 100644 tools/counter/Makefile create mode 100644 tools/counter/counter_example.c
Quoted 19 lines · Jonathan Cameron
Quoted 10 lines · On Wed, 9 Jun 2021 10:31:03 +0900 William Breathitt Gray…
Changes in v11:
- Migrated Intel QEP to new interface
- Context adjustments made for documentationI pulled out a lot of bits and pieces to their own patches; hopefully that makes reviewing this patchset much simpler than before. This patchset is also available on my personal public git repo for anyone who wants a quick way to clone:
https://gitlab.com/vilhelmgray/iio/-/tree/counter_chrdev_v11Quoted 5 lines
The patches preceding "counter: Internalize sysfs interface code" are primarily cleanup and fixes that can be picked up and applied now to the IIO tree if so desired. The "counter: Internalize sysfs interface code" patch as well may be considered for pickup because it is relatively safe and makes no changes to the userspace interface.
Quoted 8 lines
Let us aim to do that in the interests of cutting down on the volume for future versions!
However, it is made tricky by the fact patch 22 hasn't made it to me or lore.kernel.org. Could you send that one again. Hopefully the in-reply-to will ensure it's correctly threaded.
Jonathan
I think patch 22 just took a while to be processed by the servers because of its size; I went ahead and submitted a RESEND of it regardless just in case. You should be able to access both on lore.kernel.org:
https://lore.kernel.org/lkml/87dec6c889e40068ed27cbb3e66a6376856e2267.1623201082.git.vilhelm.gray@gmail.com/
https://lore.kernel.org/lkml/20210609141145.Ci-kBe7zxq4hPKS98nEi0JK7WOv0DHLOIm8pmrIDvVY@z/
Let me know if you encounter any other problems.
William Breathitt Gray