Introduce the Counter character device interface
Subsystems (9)
v8 cover Introduce the Counter character device interface
Changes in v8:
- Consolidated Counter sysfs ABI documentation to single file
- Added events_queue_size sysfs attribute to allow users to dynamically resize the events queue
- Fixed markup syntax and typos in generic-counter.rst
- Improved documentation in include/uapi/linux/counter.h and friends
- Renamed COUNTER_LOAD_WATCHES_IOCTL to COUNTER_ENABLE_EVENTS_IOCTL; Renamed COUNTER_CLEAR_WATCHES_IOCTL to COUNTER_DISABLE_EVENTS_IOCTL
- Renamed the struct counter_event "errno" member to "status"
- Dropped the "irq_trigger" 104-QUAD-8 sysfs attribute; this functionality now occurs implicitly via the Counter chrdev interface
- Return -ERANGE where appropriate instead of -EINVAL
- Simplified switch exit paths; return early when possible
- Call devm_request_irq() before devm_counter_register() for 104-quad-8
- Renamed devm_counter_unregister() to more apt devm_counter_release()
- Use enum counter_scope for scope values in counter-sysfs.c
- Use sysfs_emit() instead of sprintf() where appropriate
- Renamed find_in_string_array() to more apt counter_find_enum()
- Renamed *_action_get() and *_action_write() to *_action_read() and *_action_write() to match new naming convention of Counter callbacks
- Use "Counter function" naming convention instead of "Counter count function" to avoid confusion about scope
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_v8
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 (22):
docs: counter: Consolidate Counter sysfs attributes documentation
docs: counter: Fix spelling
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: 104-quad-8: Add const qualifier for actions_list array
counter: ftm-quaddec: 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
counter: Implement extension*_name 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 | 100 +- .../ABI/testing/sysfs-bus-counter-104-quad-8 | 61 - .../ABI/testing/sysfs-bus-counter-ftm-quaddec | 16 - Documentation/driver-api/generic-counter.rst | 426 ++++- .../userspace-api/ioctl/ioctl-number.rst | 1 + MAINTAINERS | 6 +- drivers/counter/104-quad-8.c | 751 +++++---- drivers/counter/Kconfig | 6 +- drivers/counter/Makefile | 1 + drivers/counter/counter-chrdev.c | 519 ++++++ drivers/counter/counter-chrdev.h | 18 + drivers/counter/counter-core.c | 185 ++ drivers/counter/counter-sysfs.c | 889 ++++++++++ drivers/counter/counter-sysfs.h | 13 + drivers/counter/counter.c | 1496 ----------------- drivers/counter/ftm-quaddec.c | 69 +- drivers/counter/microchip-tcb-capture.c | 105 +- drivers/counter/stm32-lptimer-cnt.c | 186 +- drivers/counter/stm32-timer-cnt.c | 187 +-- drivers/counter/ti-eqep.c | 226 ++- include/linux/counter.h | 716 ++++---- include/linux/counter_enum.h | 45 - include/uapi/linux/counter.h | 126 ++ 23 files changed, 3363 insertions(+), 2785 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
base-commit: b72d4f6a5122a78941ce5a3147685d6a44939a75
Signature · 1 line
2.30.0
PATCH v8 1/22 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]
@@ -215,11 +225,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
@@ -228,3 +272,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
@@ -297,7 +297,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
@@ -4540,7 +4539,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
@@ -6925,7 +6924,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.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 01/22] docs: counter: Consolidate Counter sysfs attributes documentation
Quoted 2 lines · On Fri, 12 Feb 2021 21:13:25 +0900 William Breathitt Gray…
Duplicate ABIs are not valid, so let's consolidate these sysfs attributes into the main sysfs-bus-counter documentation file.
This is sensible to do, but is there any duplicate ABI? I went looking for any resulting build problems and couldn't see what was actually duplicated.
Jonathan
Quoted 238 lines
Cc Patrick Havelange <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- 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]@@ -215,11 +225,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@@ -228,3 +272,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@@ -297,7 +297,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@@ -4540,7 +4539,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@@ -6925,7 +6924,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
Re: [PATCH v8 01/22] docs: counter: Consolidate Counter sysfs attributes documentation
Quoted 11 lines · Jonathan Cameron
Quoted 2 lines · On Fri, 12 Feb 2021 21:13:25 +0900 William Breathitt Gray…
Duplicate ABIs are not valid, so let's consolidate these sysfs attributes into the main sysfs-bus-counter documentation file.
This is sensible to do, but is there any duplicate ABI? I went looking for any resulting build problems and couldn't see what was actually duplicated.
Jonathan
There's no duplication currently, so this is just a preventative measure. These files were started for the purpose of permitting future duplication; now that duplication is explicitly disallowed, we're better off consolidating these now in order to prevent fragmentation of the documentation.
William Breathitt Gray
Re: [PATCH v8 01/22] docs: counter: Consolidate Counter sysfs attributes documentation
In reply to William Breathitt GrayQuoted 6 lines · 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]>Signed-off-by William Breathitt Gray <[email protected]>---
PATCH v8 2/22 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.30.0
Re: [PATCH v8 02/22] docs: counter: Fix spelling
Quoted 4 lines · William Breathitt Gray
"Miscellaneous" is the correct spelling.
Signed-off-by William Breathitt Gray <[email protected]>---
PATCH v8 3/22 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.30.0
David Lechner
reviewerRe: [PATCH v8 03/22] counter: 104-quad-8: Return error when invalid mode during ceiling_write
Quoted 24 lines · 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")Cc Syed Nayyar Waris <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- drivers/counter/104-quad-8.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)drivers/counter/104-quad-8.c +1
-1@@ -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 ;
drivers/counter/104-quad-8.c static ssize_t quad8_count_ceiling_write(struct counter_device *counter, · line 727
Quoted 10 lines
drivers/counter/104-quad-8.c +2
-1+return len; }mutex_unlock (&priv->lock); -return len; +return -EINVAL ; } static ssize_t quad8_count_preset_enable_read(struct counter_device *counter,
What happens if the register is written to when in the wrong mode?
If it doesn't hurt anything, I would suggest always writing the register instead so that users don't have to know worry about the fact that the mode has to be set first.
Re: [PATCH v8 03/22] counter: 104-quad-8: Return error when invalid mode during ceiling_write
Quoted 33 lines · David Lechner
Quoted 32 lines · 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")Cc Syed Nayyar Waris <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- 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 ; }
Quoted 8 lines
drivers/counter/104-quad-8.c static ssize_t quad8_count_ceiling_write(struct counter_device *counter, · line 727
Quoted 2 lines
drivers/counter/104-quad-8.c +0
-0static ssize_t quad8_count_preset_enable_read(struct counter_device *counter,What happens if the register is written to when in the wrong mode?
If it doesn't hurt anything, I would suggest always writing the register instead so that users don't have to know worry about the fact that the mode has to be set first.
Unfortunately this register is used for two different functions: as a ceiling limit and as a preset value. When we're in the preset mode, the value of this register will be used to set the counter value when an interrupt occurs; whereas in ceiling mode, this value is used as the upper counting limit for the counter. We should only set this value when in the correct mode, lest we end clobbering the value for the other mode (e.g. user sets ceiling value, but driver unexpectantly changes the preset value).
William Breathitt Gray
PATCH v8 4/22 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.30.0
PATCH v8 5/22 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.30.0
PATCH v8 6/22 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_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_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.30.0
PATCH v8 7/22 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.30.0
PATCH v8 8/22 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.30.0
PATCH v8 9/22 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 | 10 ++++++++++ drivers/counter/microchip-tcb-capture.c | 6 ++++++ drivers/counter/stm32-lptimer-cnt.c | 10 ++++++---- drivers/counter/stm32-timer-cnt.c | 3 +++ drivers/counter/ti-eqep.c | 3 +++ 5 files changed, 28 insertions(+), 4 deletions(-)
drivers/counter/104-quad-8.c +10 -0
@@ -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 ; } }
@@ -367,6 +371,9 @@ static int quad8_action_get(struct counter_device *counter,case QUAD8_COUNT_FUNCTION_QUADRATURE_X4 : *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ;break ; +default : +/* should never reach this path */ +return -EINVAL ; }return 0 ;
@@ -529,6 +536,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/stm32-timer-cnt.c +3 -0
@@ -296,6 +296,9 @@ static int stm32_action_get(struct counter_device *counter,/* counts up/down on both TI1FP1 and TI2FP2 edges */ *action =STM32_SYNAPSE_ACTION_BOTH_EDGES ;break ; +default : +/* should never reach this path */ +return -EINVAL ; }return 0 ;
drivers/counter/ti-eqep.c +3 -0
@@ -192,6 +192,9 @@ static int ti_eqep_action_get(struct counter_device *counter,break ; }break ; +default : +/* should never reach this path */ +return -EINVAL ; }return 0 ;
Signature · 1 line
2.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 09/22] counter: Return error code on invalid modes
Quoted 5 lines · On Fri, 12 Feb 2021 21:13:33 +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.
In many of these cases it may make sense to also return early in the good paths rather than share a return 0 at the end of the function?
Quoted 133 lines
Cc Syed Nayyar Waris <[email protected]>Cc Kamel Bouhara <[email protected]>Cc Fabrice Gasnier <[email protected]>Cc Maxime Coquelin <[email protected]>Cc Alexandre Torgue <[email protected]>Cc David Lechner <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- drivers/counter/104-quad-8.c | 10 ++++++++++ drivers/counter/microchip-tcb-capture.c | 6 ++++++ drivers/counter/stm32-lptimer-cnt.c | 10 ++++++---- drivers/counter/stm32-timer-cnt.c | 3 +++ drivers/counter/ti-eqep.c | 3 +++ 5 files changed, 28 insertions(+), 4 deletions(-)drivers/counter/104-quad-8.c +10
-0@@ -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 ; } }@@ -367,6 +371,9 @@ static int quad8_action_get(struct counter_device *counter,case QUAD8_COUNT_FUNCTION_QUADRATURE_X4 : *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ;break ; +default : +/* should never reach this path */ +return -EINVAL ; }return 0 ;@@ -529,6 +536,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/stm32-timer-cnt.c +3
-0@@ -296,6 +296,9 @@ static int stm32_action_get(struct counter_device *counter,/* counts up/down on both TI1FP1 and TI2FP2 edges */ *action =STM32_SYNAPSE_ACTION_BOTH_EDGES ;break ; +default : +/* should never reach this path */ +return -EINVAL ; }return 0 ;drivers/counter/ti-eqep.c +3
-0@@ -192,6 +192,9 @@ static int ti_eqep_action_get(struct counter_device *counter,break ; }break ; +default : +/* should never reach this path */ +return -EINVAL ; }return 0 ;
Re: [PATCH v8 09/22] counter: Return error code on invalid modes
In reply to William Breathitt GrayQuoted 6 lines · 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 8 lines
Cc Syed Nayyar Waris <[email protected]>Cc Kamel Bouhara <[email protected]>Cc Fabrice Gasnier <[email protected]>Cc Maxime Coquelin <[email protected]>Cc Alexandre Torgue <[email protected]>Cc David Lechner <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>---
(In response to Jonathan's comment, I think this is fine rather than adding more churn to change all of the breaks to returns - but will keep that in mind for future changes.)
Re: [PATCH v8 09/22] counter: Return error code on invalid modes
Quoted 16 lines · David Lechner
Quoted 6 lines · 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 8 lines
Cc Syed Nayyar Waris <[email protected]>Cc Kamel Bouhara <[email protected]>Cc Fabrice Gasnier <[email protected]>Cc Maxime Coquelin <[email protected]>Cc Alexandre Torgue <[email protected]>Cc David Lechner <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>---
Quoted 5 lines
Reviewed-by David Lechner <[email protected]>(In response to Jonathan's comment, I think this is fine rather than adding more churn to change all of the breaks to returns - but will keep that in mind for future changes.)
Due to some other updates I'm making to this patchset, I went ahead already and updated the breaks to returns in the few places where applicable. The changes to this patch are minor, but being pedantic I'll hold off on adding your Reviewed-by line until the next revision so you have the opportunity to formally approve it.
William Breathitt Gray
PATCH v8 10/22 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/stm32-lptimer-cnt.c | 2 +- 2 files changed, 4 insertions(+), 4 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);
@@ -671,7 +671,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);
@@ -716,7 +716,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/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.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 10/22] counter: Standardize to ERANGE for limit exceeded errors
Quoted 2 lines · On Fri, 12 Feb 2021 21:13:34 +0900 William Breathitt Gray…
ERANGE is a semantically better error code to return when an argument value falls outside the supported limit range of a device.
#define ERANGE 34 /* Math result not representable */
Not generally applicable to a parameter being out of range despite the name.
#define EINVAL 22 /* Invalid argument */
Is probably closer to what we want to describe here.
Jonathan
Quoted 55 lines
Cc Syed Nayyar Waris <[email protected]>Cc Fabrice Gasnier <[email protected]>Cc Maxime Coquelin <[email protected]>Cc Alexandre Torgue <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- drivers/counter/104-quad-8.c | 6 +++--- drivers/counter/stm32-lptimer-cnt.c | 2 +- 2 files changed, 4 insertions(+), 4 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);@@ -671,7 +671,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);@@ -716,7 +716,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/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;
Re: [PATCH v8 10/22] counter: Standardize to ERANGE for limit exceeded errors
Quoted 6 lines · Jonathan Cameron
Quoted 2 lines · On Fri, 12 Feb 2021 21:13:34 +0900 William Breathitt Gray…
ERANGE is a semantically better error code to return when an argument value falls outside the supported limit range of a device.
Quoted 8 lines
#define ERANGE 34 /* Math result not representable */
Not generally applicable to a parameter being out of range despite the name.
#define EINVAL 22 /* Invalid argument */
Is probably closer to what we want to describe here.Jonathan
The comment for ERANGE in error-base.h may be terse to a fault. I believe there's a connotation here provided by ERANGE that is absent from EINVAL: primarily that the device buffer is incapable of supporting the desired value (i.e. there is a hardware limitation).
This is why strtoul() returns ERANGE if the correct value is outside the range of representable values: the result of the operation is valid in theory (it would be an unsigned integer), but it cannot be returned to the user due to a limitation of the hardware to support that value (e.g. 32-bit registers) [1].
The changes in this patch follow the same logic: these are arguments that are valid in theory (e.g. they are unsigned integers), but the underlying devices are incapable of processing such a value (e.g. the 104-QUAD-8 can only handle 24-bit values).
[1] https://stackoverflow.com/a/34981398/1806289
William Breathitt Gray
Jonathan Cameron
maintainerRe: [PATCH v8 10/22] counter: Standardize to ERANGE for limit exceeded errors
Quoted 27 lines · On Tue, 16 Feb 2021 10:26:52 +0900 William Breathitt Gray…
Quoted 6 lines · Jonathan Cameron
Quoted 2 lines · On Fri, 12 Feb 2021 21:13:34 +0900 William Breathitt Gray…
ERANGE is a semantically better error code to return when an argument value falls outside the supported limit range of a device.
Quoted 8 lines
#define ERANGE 34 /* Math result not representable */
Not generally applicable to a parameter being out of range despite the name.
#define EINVAL 22 /* Invalid argument */
Is probably closer to what we want to describe here.Jonathan
The comment for ERANGE in
error-base.hmay be terse to a fault. I believe there's a connotation here provided by ERANGE that is absent from EINVAL: primarily that the device buffer is incapable of supporting the desired value (i.e. there is a hardware limitation).This is why
strtoul()returns ERANGE if the correct value is outside the range of representable values: the result of the operation is valid in theory (it would be an unsigned integer), but it cannot be returned to the user due to a limitation of the hardware to support that value (e.g. 32-bit registers) [1].
Quoted 6 lines
The changes in this patch follow the same logic: these are arguments that are valid in theory (e.g. they are unsigned integers), but the underlying devices are incapable of processing such a value (e.g. the 104-QUAD-8 can only handle 24-bit values).
Its a bit of a stretch, but I can't claim to feel that strongly about this.
Jonathan
Quoted 2 lines
William Breathitt Gray
Re: [PATCH v8 10/22] counter: Standardize to ERANGE for limit exceeded errors
In reply to William Breathitt GrayQuoted 9 lines · William Breathitt Gray
ERANGE is a semantically better error code to return when an argument value falls outside the supported limit range of a device.
Cc Syed Nayyar Waris <[email protected]>Cc Fabrice Gasnier <[email protected]>Cc Maxime Coquelin <[email protected]>Cc Alexandre Torgue <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>---
(I agree with William's assessment that this use of ERANGE is consistent with other uses in the kernel.)
PATCH v8 11/22 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/microchip-tcb-capture.c | 4 ++-- include/linux/counter.h | 12 ++++++------ 4 files changed, 17 insertions(+), 16 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/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.30.0
Re: [PATCH v8 11/22] counter: Rename counter_signal_value to counter_signal_level
Quoted 7 lines · William Breathitt Gray
Signal values will always be levels so let's be explicit it about it to make the intent of the code clear.
Cc Syed Nayyar Waris <[email protected]>Cc Kamel Bouhara <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>---
PATCH v8 12/22 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. The phrase "Count action" is adjusted herein as well for the same reason.
--- drivers/counter/104-quad-8.c | 62 +++++++++++----------- drivers/counter/counter.c | 38 +++++++------- drivers/counter/ftm-quaddec.c | 23 ++++----- drivers/counter/microchip-tcb-capture.c | 44 ++++++++-------- drivers/counter/stm32-lptimer-cnt.c | 56 ++++++++++---------- drivers/counter/stm32-timer-cnt.c | 68 ++++++++++++------------- drivers/counter/ti-eqep.c | 28 +++++----- include/linux/counter.h | 20 ++++---- 8 files changed, 166 insertions(+), 173 deletions(-)
drivers/counter/104-quad-8.c +31 -31
@@ -187,18 +187,18 @@ static int quad8_count_write(struct counter_device *counter,return 0 ; } -enum quad8_count_function { -QUAD8_COUNT_FUNCTION_PULSE_DIRECTION =0 , -QUAD8_COUNT_FUNCTION_QUADRATURE_X1 , -QUAD8_COUNT_FUNCTION_QUADRATURE_X2 , -QUAD8_COUNT_FUNCTION_QUADRATURE_X4 +enum quad8_function { +QUAD8_FUNCTION_PULSE_DIRECTION =0 , +QUAD8_FUNCTION_QUADRATURE_X1 , +QUAD8_FUNCTION_QUADRATURE_X2 , +QUAD8_FUNCTION_QUADRATURE_X4 }; -static const enum counter_count_function quad8_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_functions_list[] = { + [QUAD8_FUNCTION_PULSE_DIRECTION ] =COUNTER_FUNCTION_PULSE_DIRECTION , + [QUAD8_FUNCTION_QUADRATURE_X1 ] =COUNTER_FUNCTION_QUADRATURE_X1_A , + [QUAD8_FUNCTION_QUADRATURE_X2 ] =COUNTER_FUNCTION_QUADRATURE_X2_A , + [QUAD8_FUNCTION_QUADRATURE_X4 ] =COUNTER_FUNCTION_QUADRATURE_X4 }; static int quad8_function_get(struct counter_device *counter,
@@ -212,17 +212,17 @@ static int quad8_function_get(struct counter_device *counter,if (priv->quadrature_mode[id])switch (priv->quadrature_scale[id]) {case 0 : - *function =QUAD8_COUNT_FUNCTION_QUADRATURE_X1 ; + *function =QUAD8_FUNCTION_QUADRATURE_X1 ;break ;case 1 : - *function =QUAD8_COUNT_FUNCTION_QUADRATURE_X2 ; + *function =QUAD8_FUNCTION_QUADRATURE_X2 ;break ;case 2 : - *function =QUAD8_COUNT_FUNCTION_QUADRATURE_X4 ; + *function =QUAD8_FUNCTION_QUADRATURE_X4 ;break ; }else - *function =QUAD8_COUNT_FUNCTION_PULSE_DIRECTION ; + *function =QUAD8_FUNCTION_PULSE_DIRECTION ;mutex_unlock (&priv->lock);
@@ -246,7 +246,7 @@ static int quad8_function_set(struct counter_device *counter, mode_cfg = priv->count_mode[id] <<1 ; idr_cfg = priv->index_polarity[id] <<1 ; -if (function ==QUAD8_COUNT_FUNCTION_PULSE_DIRECTION ) { +if (function ==QUAD8_FUNCTION_PULSE_DIRECTION ) { *quadrature_mode =0 ;/* Quadrature scaling only available in quadrature mode */
@@ -262,15 +262,15 @@ static int quad8_function_set(struct counter_device *counter, *quadrature_mode =1 ;switch (function) { -case QUAD8_COUNT_FUNCTION_QUADRATURE_X1 : +case QUAD8_FUNCTION_QUADRATURE_X1 : *scale =0 ; mode_cfg |=QUAD8_CMR_QUADRATURE_X1 ;break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X2 : +case QUAD8_FUNCTION_QUADRATURE_X2 : *scale =1 ; mode_cfg |=QUAD8_CMR_QUADRATURE_X2 ;break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X4 : +case QUAD8_FUNCTION_QUADRATURE_X4 : *scale =2 ; mode_cfg |=QUAD8_CMR_QUADRATURE_X4 ;break ;
@@ -351,11 +351,11 @@ static int quad8_action_get(struct counter_device *counter,/* Determine action mode based on current count function mode */ switch (function) { -case QUAD8_COUNT_FUNCTION_PULSE_DIRECTION : +case QUAD8_FUNCTION_PULSE_DIRECTION :if (synapse->signal->id == signal_a_id) *action =QUAD8_SYNAPSE_ACTION_RISING_EDGE ;break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X1 : +case QUAD8_FUNCTION_QUADRATURE_X1 :if (synapse->signal->id == signal_a_id) {quad8_direction_get (counter, count, &direction);
@@ -365,11 +365,11 @@ static int quad8_action_get(struct counter_device *counter, *action =QUAD8_SYNAPSE_ACTION_FALLING_EDGE ; }break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X2 : +case QUAD8_FUNCTION_QUADRATURE_X2 :if (synapse->signal->id == signal_a_id) *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ;break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X4 : +case QUAD8_FUNCTION_QUADRATURE_X4 : *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ;break ;default :
@@ -1010,15 +1010,15 @@ static const struct counter_count_ext quad8_count_ext[] = { } }; -#define QUAD8_COUNT (_id, _cntname) { \ - .id = (_id), \ - .name = (_cntname), \ - .functions_list = quad8_count_functions_list, \ - .num_functions = ARRAY_SIZE(quad8_count_functions_list), \ - .synapses = quad8_count_synapses[(_id)], \ - .num_synapses = 2, \ - .ext = quad8_count_ext, \ - .num_ext = ARRAY_SIZE(quad8_count_ext) \ +#define QUAD8_COUNT (_id, _cntname) { \ + .id = (_id), \ + .name = (_cntname), \ + .functions_list = quad8_functions_list, \ + .num_functions = ARRAY_SIZE(quad8_functions_list), \ + .synapses = quad8_count_synapses[(_id)], \ + .num_synapses = 2, \ + .ext = quad8_count_ext, \ + .num_ext = ARRAY_SIZE(quad8_count_ext) \ }static struct counter_count quad8_counts[] = {
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 +11 -12
@@ -167,13 +167,12 @@ static const enum counter_synapse_action ftm_quaddec_synapse_actions[] = {COUNTER_SYNAPSE_ACTION_BOTH_EDGES }; -enum ftm_quaddec_count_function { -FTM_QUADDEC_COUNT_ENCODER_MODE_1 , +enum ftm_quaddec_function { +FTM_QUADDEC_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_functions[] = { + [FTM_QUADDEC_ENCODER_MODE_1 ] =COUNTER_FUNCTION_QUADRATURE_X4 }; static int ftm_quaddec_count_read(struct counter_device *counter,
@@ -206,11 +205,11 @@ static int ftm_quaddec_count_write(struct counter_device *counter,return 0 ; } -static int ftm_quaddec_count_function_get (struct counter_device *counter, -struct counter_count *count, -size_t *function) +static int ftm_quaddec_function_get (struct counter_device *counter, +struct counter_count *count, +size_t *function) { - *function =FTM_QUADDEC_COUNT_ENCODER_MODE_1 ; + *function =FTM_QUADDEC_ENCODER_MODE_1 ;return 0 ; }
@@ -228,7 +227,7 @@ static int ftm_quaddec_action_get(struct counter_device *counter,static const struct counter_ops ftm_quaddec_cnt_ops = { .count_read = ftm_quaddec_count_read, .count_write = ftm_quaddec_count_write, - .function_get = ftm_quaddec_count_function_get, + .function_get = ftm_quaddec_function_get, .action_get = ftm_quaddec_action_get, };
@@ -264,8 +263,8 @@ static const struct counter_count_ext ftm_quaddec_count_ext[] = {static struct counter_count ftm_quaddec_counts = { .id =0 , .name ="Channel 1 Count" , - .functions_list = ftm_quaddec_count_functions, - .num_functions =ARRAY_SIZE (ftm_quaddec_count_functions), + .functions_list = ftm_quaddec_functions, + .num_functions =ARRAY_SIZE (ftm_quaddec_functions), .synapses = ftm_quaddec_count_synapses, .num_synapses =ARRAY_SIZE (ftm_quaddec_count_synapses), .ext = ftm_quaddec_count_ext,
drivers/counter/microchip-tcb-capture.c +20 -24
90 lines not on this page · raw message
drivers/counter/stm32-lptimer-cnt.c +28 -28
125 lines not on this page · raw message
drivers/counter/stm32-timer-cnt.c +33 -35
140 lines not on this page · raw message
drivers/counter/ti-eqep.c +14 -14
@@ -73,11 +73,11 @@ enum { };/* Position Counter Input Modes */ -enum { -TI_EQEP_COUNT_FUNC_QUAD_COUNT , -TI_EQEP_COUNT_FUNC_DIR_COUNT , -TI_EQEP_COUNT_FUNC_UP_COUNT , -TI_EQEP_COUNT_FUNC_DOWN_COUNT , +enum ti_eqep_function { +TI_EQEP_FUNCTION_QUAD_COUNT , +TI_EQEP_FUNCTION_DIR_COUNT , +TI_EQEP_FUNCTION_UP_COUNT , +TI_EQEP_FUNCTION_DOWN_COUNT , };enum {
@@ -152,13 +152,13 @@ static int ti_eqep_action_get(struct counter_device *counter,return err;switch (function) { -case TI_EQEP_COUNT_FUNC_QUAD_COUNT : +case TI_EQEP_FUNCTION_QUAD_COUNT :/* In quadrature mode, the rising and falling edge of both * QEPA and QEPB trigger QCLK. */ *action =TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES ;break ; -case TI_EQEP_COUNT_FUNC_DIR_COUNT : +case TI_EQEP_FUNCTION_DIR_COUNT :/* In direction-count mode only rising edge of QEPA is counted * and QEPB gives direction. */
@@ -171,8 +171,8 @@ static int ti_eqep_action_get(struct counter_device *counter,break ; }break ; -case TI_EQEP_COUNT_FUNC_UP_COUNT : -case TI_EQEP_COUNT_FUNC_DOWN_COUNT : +case TI_EQEP_FUNCTION_UP_COUNT : +case TI_EQEP_FUNCTION_DOWN_COUNT :/* In up/down-count modes only QEPA is counted and QEPB is not * used. */
@@ -327,11 +327,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_FUNCTION_QUAD_COUNT ] =COUNTER_FUNCTION_QUADRATURE_X4 , + [TI_EQEP_FUNCTION_DIR_COUNT ] =COUNTER_FUNCTION_PULSE_DIRECTION , + [TI_EQEP_FUNCTION_UP_COUNT ] =COUNTER_FUNCTION_INCREASE , + [TI_EQEP_FUNCTION_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.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 12/22] counter: Rename counter_count_function to counter_function
Quoted 6 lines · On Fri, 12 Feb 2021 21:13:36 +0900 William Breathitt Gray…
The 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. The phrase "Count action" is adjusted herein as well for the same reason.
Quoted 8 lines
Cc Syed Nayyar Waris <[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 David Lechner <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
I agree this makes sense in the counter core code, but in the drivers it may not be quite so obvious we are talking about a counter function given some of the bits of hardware do a number of other things.
I guess up to the various driver maintainers on whether they think the new meaning is clear enough!
Jonathan
Quoted 802 lines
--- drivers/counter/104-quad-8.c | 62 +++++++++++----------- drivers/counter/counter.c | 38 +++++++------- drivers/counter/ftm-quaddec.c | 23 ++++----- drivers/counter/microchip-tcb-capture.c | 44 ++++++++-------- drivers/counter/stm32-lptimer-cnt.c | 56 ++++++++++---------- drivers/counter/stm32-timer-cnt.c | 68 ++++++++++++------------- drivers/counter/ti-eqep.c | 28 +++++----- include/linux/counter.h | 20 ++++---- 8 files changed, 166 insertions(+), 173 deletions(-)drivers/counter/104-quad-8.c +31
-31@@ -187,18 +187,18 @@ static int quad8_count_write(struct counter_device *counter,return 0 ; } -enum quad8_count_function { -QUAD8_COUNT_FUNCTION_PULSE_DIRECTION =0 , -QUAD8_COUNT_FUNCTION_QUADRATURE_X1 , -QUAD8_COUNT_FUNCTION_QUADRATURE_X2 , -QUAD8_COUNT_FUNCTION_QUADRATURE_X4 +enum quad8_function { +QUAD8_FUNCTION_PULSE_DIRECTION =0 , +QUAD8_FUNCTION_QUADRATURE_X1 , +QUAD8_FUNCTION_QUADRATURE_X2 , +QUAD8_FUNCTION_QUADRATURE_X4 }; -static const enum counter_count_function quad8_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_functions_list[] = { + [QUAD8_FUNCTION_PULSE_DIRECTION ] =COUNTER_FUNCTION_PULSE_DIRECTION , + [QUAD8_FUNCTION_QUADRATURE_X1 ] =COUNTER_FUNCTION_QUADRATURE_X1_A , + [QUAD8_FUNCTION_QUADRATURE_X2 ] =COUNTER_FUNCTION_QUADRATURE_X2_A , + [QUAD8_FUNCTION_QUADRATURE_X4 ] =COUNTER_FUNCTION_QUADRATURE_X4 }; static int quad8_function_get(struct counter_device *counter,@@ -212,17 +212,17 @@ static int quad8_function_get(struct counter_device *counter,if (priv->quadrature_mode[id])switch (priv->quadrature_scale[id]) {case 0 : - *function =QUAD8_COUNT_FUNCTION_QUADRATURE_X1 ; + *function =QUAD8_FUNCTION_QUADRATURE_X1 ;break ;case 1 : - *function =QUAD8_COUNT_FUNCTION_QUADRATURE_X2 ; + *function =QUAD8_FUNCTION_QUADRATURE_X2 ;break ;case 2 : - *function =QUAD8_COUNT_FUNCTION_QUADRATURE_X4 ; + *function =QUAD8_FUNCTION_QUADRATURE_X4 ;break ; }else - *function =QUAD8_COUNT_FUNCTION_PULSE_DIRECTION ; + *function =QUAD8_FUNCTION_PULSE_DIRECTION ;mutex_unlock (&priv->lock);@@ -246,7 +246,7 @@ static int quad8_function_set(struct counter_device *counter, mode_cfg = priv->count_mode[id] <<1 ; idr_cfg = priv->index_polarity[id] <<1 ; -if (function ==QUAD8_COUNT_FUNCTION_PULSE_DIRECTION ) { +if (function ==QUAD8_FUNCTION_PULSE_DIRECTION ) { *quadrature_mode =0 ;/* Quadrature scaling only available in quadrature mode */ @@ -262,15 +262,15 @@ static int quad8_function_set(struct counter_device *counter, *quadrature_mode =1 ;switch (function) { -case QUAD8_COUNT_FUNCTION_QUADRATURE_X1 : +case QUAD8_FUNCTION_QUADRATURE_X1 : *scale =0 ; mode_cfg |=QUAD8_CMR_QUADRATURE_X1 ;break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X2 : +case QUAD8_FUNCTION_QUADRATURE_X2 : *scale =1 ; mode_cfg |=QUAD8_CMR_QUADRATURE_X2 ;break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X4 : +case QUAD8_FUNCTION_QUADRATURE_X4 : *scale =2 ; mode_cfg |=QUAD8_CMR_QUADRATURE_X4 ;break ;@@ -351,11 +351,11 @@ static int quad8_action_get(struct counter_device *counter,/* Determine action mode based on current count function mode */ switch (function) { -case QUAD8_COUNT_FUNCTION_PULSE_DIRECTION : +case QUAD8_FUNCTION_PULSE_DIRECTION :if (synapse->signal->id == signal_a_id) *action =QUAD8_SYNAPSE_ACTION_RISING_EDGE ;break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X1 : +case QUAD8_FUNCTION_QUADRATURE_X1 :if (synapse->signal->id == signal_a_id) {quad8_direction_get (counter, count, &direction);@@ -365,11 +365,11 @@ static int quad8_action_get(struct counter_device *counter, *action =QUAD8_SYNAPSE_ACTION_FALLING_EDGE ; }break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X2 : +case QUAD8_FUNCTION_QUADRATURE_X2 :if (synapse->signal->id == signal_a_id) *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ;break ; -case QUAD8_COUNT_FUNCTION_QUADRATURE_X4 : +case QUAD8_FUNCTION_QUADRATURE_X4 : *action =QUAD8_SYNAPSE_ACTION_BOTH_EDGES ;break ;default :@@ -1010,15 +1010,15 @@ static const struct counter_count_ext quad8_count_ext[] = { } }; -#define QUAD8_COUNT (_id, _cntname) { \ - .id = (_id), \ - .name = (_cntname), \ - .functions_list = quad8_count_functions_list, \ - .num_functions = ARRAY_SIZE(quad8_count_functions_list), \ - .synapses = quad8_count_synapses[(_id)], \ - .num_synapses = 2, \ - .ext = quad8_count_ext, \ - .num_ext = ARRAY_SIZE(quad8_count_ext) \ +#define QUAD8_COUNT (_id, _cntname) { \ + .id = (_id), \ + .name = (_cntname), \ + .functions_list = quad8_functions_list, \ + .num_functions = ARRAY_SIZE(quad8_functions_list), \ + .synapses = quad8_count_synapses[(_id)], \ + .num_synapses = 2, \ + .ext = quad8_count_ext, \ + .num_ext = ARRAY_SIZE(quad8_count_ext) \ }static struct counter_count quad8_counts[] = {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 +11
-12@@ -167,13 +167,12 @@ static const enum counter_synapse_action ftm_quaddec_synapse_actions[] = {COUNTER_SYNAPSE_ACTION_BOTH_EDGES }; -enum ftm_quaddec_count_function { -FTM_QUADDEC_COUNT_ENCODER_MODE_1 , +enum ftm_quaddec_function { +FTM_QUADDEC_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_functions[] = { + [FTM_QUADDEC_ENCODER_MODE_1 ] =COUNTER_FUNCTION_QUADRATURE_X4 }; static int ftm_quaddec_count_read(struct counter_device *counter,@@ -206,11 +205,11 @@ static int ftm_quaddec_count_write(struct counter_device *counter,return 0 ; } -static int ftm_quaddec_count_function_get (struct counter_device *counter, -struct counter_count *count, -size_t *function) +static int ftm_quaddec_function_get (struct counter_device *counter, +struct counter_count *count, +size_t *function) { - *function =FTM_QUADDEC_COUNT_ENCODER_MODE_1 ; + *function =FTM_QUADDEC_ENCODER_MODE_1 ;return 0 ; }@@ -228,7 +227,7 @@ static int ftm_quaddec_action_get(struct counter_device *counter,static const struct counter_ops ftm_quaddec_cnt_ops = { .count_read = ftm_quaddec_count_read, .count_write = ftm_quaddec_count_write, - .function_get = ftm_quaddec_count_function_get, + .function_get = ftm_quaddec_function_get, .action_get = ftm_quaddec_action_get, };@@ -264,8 +263,8 @@ static const struct counter_count_ext ftm_quaddec_count_ext[] = {static struct counter_count ftm_quaddec_counts = { .id =0 , .name ="Channel 1 Count" , - .functions_list = ftm_quaddec_count_functions, - .num_functions =ARRAY_SIZE (ftm_quaddec_count_functions), + .functions_list = ftm_quaddec_functions, + .num_functions =ARRAY_SIZE (ftm_quaddec_functions), .synapses = ftm_quaddec_count_synapses, .num_synapses =ARRAY_SIZE (ftm_quaddec_count_synapses), .ext = ftm_quaddec_count_ext,drivers/counter/microchip-tcb-capture.c +20
-24@@ -32,14 +32,14 @@ struct mchp_tc_data {bool trig_inverted; }; -enum mchp_tc_count_function { +enum mchp_tc_function {MCHP_TC_FUNCTION_INCREASE ,MCHP_TC_FUNCTION_QUADRATURE , }; -static 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 , +static enum counter_function mchp_tc_functions[] = { + [MCHP_TC_FUNCTION_INCREASE ] =COUNTER_FUNCTION_INCREASE , + [MCHP_TC_FUNCTION_QUADRATURE ] =COUNTER_FUNCTION_QUADRATURE_X4 , };enum mchp_tc_synapse_action {@@ -80,9 +80,8 @@ static struct counter_synapse mchp_tc_count_synapses[] = { } }; -static int mchp_tc_count_function_get (struct counter_device *counter, -struct counter_count *count, -size_t *function) +static int mchp_tc_function_get (struct counter_device *counter, +struct counter_count *count,size_t *function) {struct mchp_tc_data *const priv = counter->priv;@@ -94,9 +93,8 @@ static int mchp_tc_count_function_get(struct counter_device *counter,return 0 ; } -static int mchp_tc_count_function_set (struct counter_device *counter, -struct counter_count *count, -size_t function) +static int mchp_tc_function_set (struct counter_device *counter, +struct counter_count *count,size_t function) {struct mchp_tc_data *const priv = counter->priv;u32 bmr, cmr;@@ -176,10 +174,9 @@ static int mchp_tc_count_signal_read(struct counter_device *counter,return 0 ; } -static int mchp_tc_count_action_get (struct counter_device *counter, -struct counter_count *count, -struct counter_synapse *synapse, -size_t *action) +static int mchp_tc_action_get (struct counter_device *counter, +struct counter_count *count, +struct counter_synapse *synapse,size_t *action) {struct mchp_tc_data *const priv = counter->priv;u32 cmr;@@ -204,10 +201,9 @@ static int mchp_tc_count_action_get(struct counter_device *counter,return 0 ; } -static int mchp_tc_count_action_set (struct counter_device *counter, -struct counter_count *count, -struct counter_synapse *synapse, -size_t action) +static int mchp_tc_action_set (struct counter_device *counter, +struct counter_count *count, +struct counter_synapse *synapse,size_t action) {struct mchp_tc_data *const priv = counter->priv;u32 edge =ATMEL_TC_ETRGEDG_NONE ;@@ -256,8 +252,8 @@ static struct counter_count mchp_tc_counts[] = { { .id = 0, .name = "Timer Counter", - .functions_list = mchp_tc_count_functions, - .num_functions = ARRAY_SIZE(mchp_tc_count_functions), + .functions_list = mchp_tc_functions, + .num_functions = ARRAY_SIZE(mchp_tc_functions), .synapses = mchp_tc_count_synapses, .num_synapses = ARRAY_SIZE(mchp_tc_count_synapses), },@@ -266,10 +262,10 @@ static struct counter_count mchp_tc_counts[] = {static const struct counter_ops mchp_tc_ops = { .signal_read = mchp_tc_count_signal_read, .count_read = mchp_tc_count_read, - .function_get = mchp_tc_count_function_get, - .function_set = mchp_tc_count_function_set, - .action_get = mchp_tc_count_action_get, - .action_set = mchp_tc_count_action_set + .function_get = mchp_tc_function_get, + .function_set = mchp_tc_function_set, + .action_get = mchp_tc_action_get, + .action_set = mchp_tc_action_set };static const struct atmel_tcb_config tcb_rm9200_config = {drivers/counter/stm32-lptimer-cnt.c +28
-28@@ -108,7 +108,7 @@ static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable) }/** -* enum stm32_lptim_cnt_function - enumerates LPTimer counter & encoder modes +* enum stm32_lptim_function - enumerates LPTimer counter & encoder modes * @STM32_LPTIM_COUNTER_INCREASE: up count on IN1 rising, falling or both edges * @STM32_LPTIM_ENCODER_BOTH_EDGE: count on both edges (IN1 & IN2 quadrature) * @@ -129,14 +129,14 @@ static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable)* | edges | Low -> | Up | Down | Down | Up | * +---------+----------+----------+---------+----------+---------+ */ -enum stm32_lptim_cnt_function { +enum stm32_lptim_function {STM32_LPTIM_COUNTER_INCREASE ,STM32_LPTIM_ENCODER_BOTH_EDGE , }; -static 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 enum counter_function stm32_lptim_functions[] = { + [STM32_LPTIM_COUNTER_INCREASE ] =COUNTER_FUNCTION_INCREASE , + [STM32_LPTIM_ENCODER_BOTH_EDGE ] =COUNTER_FUNCTION_QUADRATURE_X4 , };enum stm32_lptim_synapse_action {@@ -170,9 +170,9 @@ static int stm32_lptim_cnt_read(struct counter_device *counter,return 0 ; } -static int stm32_lptim_cnt_function_get (struct counter_device *counter, -struct counter_count *count, -size_t *function) +static int stm32_lptim_function_get (struct counter_device *counter, +struct counter_count *count, +size_t *function) {struct stm32_lptim_cnt *const priv = counter->priv;@@ -189,9 +189,9 @@ static int stm32_lptim_cnt_function_get(struct counter_device *counter,return -EINVAL ; } -static int stm32_lptim_cnt_function_set (struct counter_device *counter, -struct counter_count *count, -size_t function) +static int stm32_lptim_function_set (struct counter_device *counter, +struct counter_count *count, +size_t function) {struct stm32_lptim_cnt *const priv = counter->priv;@@ -303,16 +303,16 @@ static const struct counter_count_ext stm32_lptim_cnt_ext[] = { }, }; -static int stm32_lptim_cnt_action_get (struct counter_device *counter, -struct counter_count *count, -struct counter_synapse *synapse, -size_t *action) +static int stm32_lptim_action_get (struct counter_device *counter, +struct counter_count *count, +struct counter_synapse *synapse, +size_t *action) {struct stm32_lptim_cnt *const priv = counter->priv;size_t function;int err; - err =stm32_lptim_cnt_function_get (counter, count, &function); + err =stm32_lptim_function_get (counter, count, &function);if (err)return err;@@ -333,10 +333,10 @@ static int stm32_lptim_cnt_action_get(struct counter_device *counter, } } -static int stm32_lptim_cnt_action_set (struct counter_device *counter, -struct counter_count *count, -struct counter_synapse *synapse, -size_t action) +static int stm32_lptim_action_set (struct counter_device *counter, +struct counter_count *count, +struct counter_synapse *synapse, +size_t action) {struct stm32_lptim_cnt *const priv = counter->priv;size_t function;@@ -345,7 +345,7 @@ static int stm32_lptim_cnt_action_set(struct counter_device *counter,if (stm32_lptim_is_enabled (priv))return -EBUSY ; - err =stm32_lptim_cnt_function_get (counter, count, &function); + err =stm32_lptim_function_get (counter, count, &function);if (err)return err;@@ -366,10 +366,10 @@ static int stm32_lptim_cnt_action_set(struct counter_device *counter,static const struct counter_ops stm32_lptim_cnt_ops = { .count_read = stm32_lptim_cnt_read, - .function_get = stm32_lptim_cnt_function_get, - .function_set = stm32_lptim_cnt_function_set, - .action_get = stm32_lptim_cnt_action_get, - .action_set = stm32_lptim_cnt_action_set, + .function_get = stm32_lptim_function_get, + .function_set = stm32_lptim_function_set, + .action_get = stm32_lptim_action_get, + .action_set = stm32_lptim_action_set, };static struct counter_signal stm32_lptim_cnt_signals[] = {@@ -400,8 +400,8 @@ static struct counter_synapse stm32_lptim_cnt_synapses[] = {static struct counter_count stm32_lptim_enc_counts = { .id =0 , .name ="LPTimer Count" , - .functions_list = stm32_lptim_cnt_functions, - .num_functions =ARRAY_SIZE (stm32_lptim_cnt_functions), + .functions_list = stm32_lptim_functions, + .num_functions =ARRAY_SIZE (stm32_lptim_functions), .synapses = stm32_lptim_cnt_synapses, .num_synapses =ARRAY_SIZE (stm32_lptim_cnt_synapses), .ext = stm32_lptim_cnt_ext,@@ -412,7 +412,7 @@ static struct counter_count stm32_lptim_enc_counts = {static struct counter_count stm32_lptim_in1_counts = { .id =0 , .name ="LPTimer Count" , - .functions_list = stm32_lptim_cnt_functions, + .functions_list = stm32_lptim_functions, .num_functions =1 , .synapses = stm32_lptim_cnt_synapses, .num_synapses =1 ,drivers/counter/stm32-timer-cnt.c +33
-35@@ -37,23 +37,23 @@ struct stm32_timer_cnt { };/** -* enum stm32_count_function - enumerates stm32 timer counter encoder modes -* @STM32_COUNT_SLAVE_MODE_DISABLED: counts on internal clock when CEN=1 -* @STM32_COUNT_ENCODER_MODE_1: counts TI1FP1 edges, depending on TI2FP2 level -* @STM32_COUNT_ENCODER_MODE_2: counts TI2FP2 edges, depending on TI1FP1 level -* @STM32_COUNT_ENCODER_MODE_3: counts on both TI1FP1 and TI2FP2 edges +* enum stm32_function - enumerates stm32 timer counter encoder modes +* @STM32_SLAVE_MODE_DISABLED: counts on internal clock when CEN=1 +* @STM32_ENCODER_MODE_1: counts TI1FP1 edges, depending on TI2FP2 level +* @STM32_ENCODER_MODE_2: counts TI2FP2 edges, depending on TI1FP1 level +* @STM32_ENCODER_MODE_3: counts on both TI1FP1 and TI2FP2 edges */ -enum stm32_count_function { -STM32_COUNT_SLAVE_MODE_DISABLED =-1 , -STM32_COUNT_ENCODER_MODE_1 , -STM32_COUNT_ENCODER_MODE_2 , -STM32_COUNT_ENCODER_MODE_3 , +enum stm32_function { +STM32_SLAVE_MODE_DISABLED =-1 , +STM32_ENCODER_MODE_1 , +STM32_ENCODER_MODE_2 , +STM32_ENCODER_MODE_3 , }; -static enum counter_count_function stm32_count_functions[] = { - [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 enum counter_function stm32_functions[] = { + [STM32_ENCODER_MODE_1 ] =COUNTER_FUNCTION_QUADRATURE_X2_A , + [STM32_ENCODER_MODE_2 ] =COUNTER_FUNCTION_QUADRATURE_X2_B , + [STM32_ENCODER_MODE_3 ] =COUNTER_FUNCTION_QUADRATURE_X4 , }; static int stm32_count_read(struct counter_device *counter,@@ -80,9 +80,8 @@ static int stm32_count_write(struct counter_device *counter,return regmap_write (priv->regmap,TIM_CNT , val); } -static int stm32_count_function_get (struct counter_device *counter, -struct counter_count *count, -size_t *function) +static int stm32_function_get (struct counter_device *counter, +struct counter_count *count,size_t *function) {struct stm32_timer_cnt *const priv = counter->priv;u32 smcr;@@ -91,34 +90,33 @@ static int stm32_count_function_get(struct counter_device *counter,switch (smcr &TIM_SMCR_SMS ) {case 1 : - *function =STM32_COUNT_ENCODER_MODE_1 ; + *function =STM32_ENCODER_MODE_1 ;return 0 ;case 2 : - *function =STM32_COUNT_ENCODER_MODE_2 ; + *function =STM32_ENCODER_MODE_2 ;return 0 ;case 3 : - *function =STM32_COUNT_ENCODER_MODE_3 ; + *function =STM32_ENCODER_MODE_3 ;return 0 ; }return -EINVAL ; } -static int stm32_count_function_set (struct counter_device *counter, -struct counter_count *count, -size_t function) +static int stm32_function_set (struct counter_device *counter, +struct counter_count *count,size_t function) {struct stm32_timer_cnt *const priv = counter->priv;u32 cr1, sms;switch (function) { -case STM32_COUNT_ENCODER_MODE_1 : +case STM32_ENCODER_MODE_1 : sms =1 ;break ; -case STM32_COUNT_ENCODER_MODE_2 : +case STM32_ENCODER_MODE_2 : sms =2 ;break ; -case STM32_COUNT_ENCODER_MODE_3 : +case STM32_ENCODER_MODE_3 : sms =3 ;break ;default :@@ -274,25 +272,25 @@ static int stm32_action_get(struct counter_device *counter,size_t function;int err; -/* Default action mode (e.g. STM32_COUNT_SLAVE_MODE_DISABLED) */ +/* Default action mode (e.g. STM32_SLAVE_MODE_DISABLED) */ *action =STM32_SYNAPSE_ACTION_NONE ; - err =stm32_count_function_get (counter, count, &function); + err =stm32_function_get (counter, count, &function);if (err)return 0 ;switch (function) { -case STM32_COUNT_ENCODER_MODE_1 : +case STM32_ENCODER_MODE_1 :/* counts up/down on TI1FP1 edge depending on TI2FP2 level */ if (synapse->signal->id == count->synapses[0 ].signal->id) *action =STM32_SYNAPSE_ACTION_BOTH_EDGES ;break ; -case STM32_COUNT_ENCODER_MODE_2 : +case STM32_ENCODER_MODE_2 :/* counts up/down on TI2FP2 edge depending on TI1FP1 level */ if (synapse->signal->id == count->synapses[1 ].signal->id) *action =STM32_SYNAPSE_ACTION_BOTH_EDGES ;break ; -case STM32_COUNT_ENCODER_MODE_3 : +case STM32_ENCODER_MODE_3 :/* counts up/down on both TI1FP1 and TI2FP2 edges */ *action =STM32_SYNAPSE_ACTION_BOTH_EDGES ;break ;@@ -307,8 +305,8 @@ static int stm32_action_get(struct counter_device *counter,static const struct counter_ops stm32_timer_cnt_ops = { .count_read = stm32_count_read, .count_write = stm32_count_write, - .function_get = stm32_count_function_get, - .function_set = stm32_count_function_set, + .function_get = stm32_function_get, + .function_set = stm32_function_set, .action_get = stm32_action_get, };@@ -339,8 +337,8 @@ static struct counter_synapse stm32_count_synapses[] = {static struct counter_count stm32_counts = { .id =0 , .name ="Channel 1 Count" , - .functions_list = stm32_count_functions, - .num_functions =ARRAY_SIZE (stm32_count_functions), + .functions_list = stm32_functions, + .num_functions =ARRAY_SIZE (stm32_functions), .synapses = stm32_count_synapses, .num_synapses =ARRAY_SIZE (stm32_count_synapses), .ext = stm32_count_ext,drivers/counter/ti-eqep.c +14
-14@@ -73,11 +73,11 @@ enum { };/* Position Counter Input Modes */ -enum { -TI_EQEP_COUNT_FUNC_QUAD_COUNT , -TI_EQEP_COUNT_FUNC_DIR_COUNT , -TI_EQEP_COUNT_FUNC_UP_COUNT , -TI_EQEP_COUNT_FUNC_DOWN_COUNT , +enum ti_eqep_function { +TI_EQEP_FUNCTION_QUAD_COUNT , +TI_EQEP_FUNCTION_DIR_COUNT , +TI_EQEP_FUNCTION_UP_COUNT , +TI_EQEP_FUNCTION_DOWN_COUNT , };enum {@@ -152,13 +152,13 @@ static int ti_eqep_action_get(struct counter_device *counter,return err;switch (function) { -case TI_EQEP_COUNT_FUNC_QUAD_COUNT : +case TI_EQEP_FUNCTION_QUAD_COUNT :/* In quadrature mode, the rising and falling edge of both * QEPA and QEPB trigger QCLK. */ *action =TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES ;break ; -case TI_EQEP_COUNT_FUNC_DIR_COUNT : +case TI_EQEP_FUNCTION_DIR_COUNT :/* In direction-count mode only rising edge of QEPA is counted * and QEPB gives direction. */ @@ -171,8 +171,8 @@ static int ti_eqep_action_get(struct counter_device *counter,break ; }break ; -case TI_EQEP_COUNT_FUNC_UP_COUNT : -case TI_EQEP_COUNT_FUNC_DOWN_COUNT : +case TI_EQEP_FUNCTION_UP_COUNT : +case TI_EQEP_FUNCTION_DOWN_COUNT :/* In up/down-count modes only QEPA is counted and QEPB is not * used. */ @@ -327,11 +327,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_FUNCTION_QUAD_COUNT ] =COUNTER_FUNCTION_QUADRATURE_X4 , + [TI_EQEP_FUNCTION_DIR_COUNT ] =COUNTER_FUNCTION_PULSE_DIRECTION , + [TI_EQEP_FUNCTION_UP_COUNT ] =COUNTER_FUNCTION_INCREASE , + [TI_EQEP_FUNCTION_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;
David Lechner
reviewerRe: [PATCH v8 12/22] counter: Rename counter_count_function to counter_function
Quoted 18 lines · Jonathan Cameron
Quoted 6 lines · On Fri, 12 Feb 2021 21:13:36 +0900 William Breathitt Gray…
The 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. The phrase "Count action" is adjusted herein as well for the same reason.
Quoted 8 lines
Cc Syed Nayyar Waris <[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 David Lechner <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Quoted 9 lines
I agree this makes sense in the counter core code, but in the drivers it may not be quite so obvious we are talking about a counter function given some of the bits of hardware do a number of other things.
I guess up to the various driver maintainers on whether they think the new meaning is clear enough!
Jonathan
TBH, I think "counter count function" makes more sense to me.
Re: [PATCH v8 12/22] counter: Rename counter_count_function to counter_function
Quoted 23 lines · David Lechner
Quoted 22 lines · Jonathan Cameron
Quoted 6 lines · On Fri, 12 Feb 2021 21:13:36 +0900 William Breathitt Gray…
The 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. The phrase "Count action" is adjusted herein as well for the same reason.
Quoted 8 lines
Cc Syed Nayyar Waris <[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 David Lechner <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>I agree this makes sense in the counter core code, but in the drivers it may not be quite so obvious we are talking about a counter function given some of the bits of hardware do a number of other things.
Quoted 7 lines
Quoted 5 lines
I guess up to the various driver maintainers on whether they think the new meaning is clear enough!
Jonathan
TBH, I think "counter count function" makes more sense to me.
That's a fair point. I'll revert this for the individual drivers and leave it up to the maintainers if they want to adjust their namings. Instead, I'll limit the name changes to the counter core code.
William Breathitt Gray
PATCH v8 13/22 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 | 153 +++ drivers/counter/counter-sysfs.c | 833 +++++++++++++ drivers/counter/counter-sysfs.h | 13 + drivers/counter/counter.c | 1496 ----------------------- drivers/counter/ftm-quaddec.c | 56 +- drivers/counter/microchip-tcb-capture.c | 87 +- drivers/counter/stm32-lptimer-cnt.c | 164 ++- drivers/counter/stm32-timer-cnt.c | 142 +-- drivers/counter/ti-eqep.c | 211 ++-- include/linux/counter.h | 631 +++++----- include/linux/counter_enum.h | 45 - 14 files changed, 1816 insertions(+), 2466 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
@@ -4543,7 +4543,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 CPMAC ETHERNET DRIVER M: Florian Fainelli <[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_STM32_TIMER_CNT) += stm32-timer-cnt.o
drivers/counter/counter-core.c new file +153 -0
153 lines not on this page · raw message
drivers/counter/counter-sysfs.c new file +833 -0
833 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,191 lines not on this page · raw message
drivers/counter/ftm-quaddec.c +23 -33
56 lines not on this page · raw message
drivers/counter/microchip-tcb-capture.c +39 -48
87 lines not on this page · raw message
drivers/counter/stm32-lptimer-cnt.c +80 -84
164 lines not on this page · raw message
drivers/counter/stm32-timer-cnt.c +59 -83
142 lines not on this page · raw message
drivers/counter/ti-eqep.c +96 -115
211 lines not on this page · raw message
include/linux/counter.h +328 -303
631 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.30.0
Part of the diff is not shown here. View the raw message.
Jonathan Cameron
maintainerRe: [PATCH v8 13/22] counter: Internalize sysfs interface code
Quoted 36 lines · On Fri, 12 Feb 2021 21:13:37 +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 9 lines
Cc Syed Nayyar Waris <[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 David Lechner <[email protected]>Cc Dan Carpenter <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
A few minor comments inline.
This set is still huge, so I've only looked at the core code for this version. Hopefully driver maintainers will do the thorough review of how it effects the individual drivers!
Jonathan
Quoted 39 lines
--- MAINTAINERS | 1 - drivers/counter/104-quad-8.c | 449 +++---- drivers/counter/Makefile | 1 + drivers/counter/counter-core.c | 153 +++ drivers/counter/counter-sysfs.c | 833 +++++++++++++ drivers/counter/counter-sysfs.h | 13 + drivers/counter/counter.c | 1496 ----------------------- drivers/counter/ftm-quaddec.c | 56 +- drivers/counter/microchip-tcb-capture.c | 87 +- drivers/counter/stm32-lptimer-cnt.c | 164 ++- drivers/counter/stm32-timer-cnt.c | 142 +-- drivers/counter/ti-eqep.c | 211 ++-- include/linux/counter.h | 631 +++++----- include/linux/counter_enum.h | 45 - 14 files changed, 1816 insertions(+), 2466 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.hMAINTAINERS +0
-1@@ -4543,7 +4543,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 CPMAC ETHERNET DRIVER M: Florian Fainelli <[email protected]>drivers/counter/104-quad-8.c +0
-0@@ -116,7 +116,7 @@ static int quad8_signal_read(struct counter_device *counter,
...
Quoted 6 lines
drivers/counter/counter-sysfs.c new file +0
-0@@ -0,0 +1,833 @@
...
Quoted 9 lines
drivers/counter/counter-sysfs.c new file +9
-0+ +static ssize_t counter_comp_u8_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +const struct counter_attribute *const a =to_counter_attribute (attr); +struct counter_device *const counter =dev_get_drvdata (dev); +int err; +u8 data =0 ; +
drivers/counter/counter-sysfs.c line 102
Quoted 10 lines
drivers/counter/counter-sysfs.c new file +10
-0+switch (a->scope) { +case COUNTER_SCOPE_DEVICE : + err = a->comp.device_u8_read (counter, &data); +break ; +case COUNTER_SCOPE_SIGNAL : + err = a->comp.signal_u8_read (counter, a->parent, &data); +break ; +case COUNTER_SCOPE_COUNT : + err = a->comp.count_u8_read (counter, a->parent, &data); +break ;
I'd add a default in here just to make it obvious anything else is an error. Same in other similar cases that follow.
Quoted 10 lines
drivers/counter/counter-sysfs.c new file +10
-0+ } +if (err <0 ) +return err; + +if (a->comp.type ==COUNTER_COMP_BOOL ) + data = !!data; + +return sprintf (buf,"%u\n" , (unsigned int )data); +} +
...
Quoted 17 lines
drivers/counter/counter-sysfs.c new file +17
-0+ +static int counter_name_attr_create (struct device *const dev, +struct counter_attribute_group *const group, +const char *const name) +{ +struct counter_attribute *counter_attr; + +/* Allocate Counter attribute */ + counter_attr =devm_kzalloc (dev,sizeof (*counter_attr),GFP_KERNEL ); +if (!counter_attr) +return -ENOMEM ; + +/* Configure Counter attribute */ + counter_attr->comp.name = name; + +/* Configure device attribute */ +sysfs_attr_init (&counter_attr->dev_attr.attr);
drivers/counter/counter-sysfs.c line 520
Quoted 10 lines
drivers/counter/counter-sysfs.c new file +10
-0+ counter_attr->dev_attr.attr.name ="name" ; + counter_attr->dev_attr.attr.mode =0444 ; + counter_attr->dev_attr.show = counter_comp_name_show; + +/* Store list node */ +list_add (&counter_attr->l, &group->attr_list); + group->num_attr++; + +return 0 ; +}
Trivial but one too many blank lines.
Quoted 6 lines
drivers/counter/counter-sysfs.c new file +6
-0+ + +static struct counter_comp counter_signal_comp = { + .type =COUNTER_COMP_SIGNAL_LEVEL , + .name ="signal" , +};
...
Quoted 9 lines
static struct
counter_synapseti_eqep_position_synapses[] = {include/linux/counter.h +0
-0@@ -6,42 +6,184 @@#ifndef _COUNTER_H_#define _COUNTER_H_
...
Re: [PATCH v8 13/22] counter: Internalize sysfs interface code
In reply to William Breathitt GrayQuoted 45 lines · 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.Cc Syed Nayyar Waris <[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 David Lechner <[email protected]>Cc Dan Carpenter <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Quoted 1 line
---
For TI eQEP bits...
PATCH v8 14/22 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
@@ -40,6 +40,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.30.0
PATCH v8 15/22 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
@@ -277,7 +277,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.30.0
PATCH v8 16/22 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
@@ -4543,6 +4543,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 CPMAC ETHERNET DRIVER M: Florian Fainelli <[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.30.0
Re: [PATCH v8 16/22] counter: Move counter enums to uapi header
Quoted 5 lines · William Breathitt Gray
This is in preparation for a subsequent patch implementing a character device interface for the Counter subsystem.
Signed-off-by William Breathitt Gray <[email protected]>---
PATCH v8 17/22 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 | 496 +++++++++++++++++++++++++++++++ drivers/counter/counter-chrdev.h | 16 + drivers/counter/counter-core.c | 37 ++- include/linux/counter.h | 45 +++ include/uapi/linux/counter.h | 70 +++++ 6 files changed, 661 insertions(+), 5 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_STM32_TIMER_CNT) += stm32-timer-cnt.o
drivers/counter/counter-chrdev.c new file +496 -0
496 lines not on this page · raw message
drivers/counter/counter-chrdev.h new file +16 -0
@@ -0,0 +1,16 @@ +/* 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> +#include <linux/types.h> + +int counter_chrdev_add (struct counter_device *const counter, +const dev_t counter_devt); +void counter_chrdev_remove (struct counter_device *const counter); + +#endif /* _COUNTER_CHRDEV_H_ */
drivers/counter/counter-core.c +33 -4
@@ -5,12 +5,16 @@*/ #include <linux/counter.h> #include <linux/device.h> +#include <linux/device/bus.h> #include <linux/export.h> +#include <linux/fs.h> #include <linux/gfp.h> #include <linux/idr.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/types.h> +#include "counter-chrdev.h" #include "counter-sysfs.h" /* Provides a unique ID for each counter device */
@@ -33,6 +37,8 @@ static struct bus_type counter_bus_type = { .name = "counter" }; +static dev_t counter_devt; +/** * counter_register - register Counter to the system * @counter: pointer to Counter to register
@@ -54,7 +60,6 @@ int counter_register(struct counter_device *const counter)if (counter->id <0 )return counter->id; -/* Configure device structure for Counter */ dev->type = &counter_device_type; dev->bus = &counter_bus_type;if (counter->parent) {
@@ -65,18 +70,25 @@ int counter_register(struct counter_device *const counter)device_initialize (dev);dev_set_drvdata (dev, counter); +/* Add Counter character device */ + err =counter_chrdev_add (counter, counter_devt); +if (err <0 ) + goto err_free_id; +/* Add Counter sysfs attributes */ err =counter_sysfs_add (counter);if (err <0 ) - goto err_free_id; + goto err_remove_chrdev;/* Add device to system */ err =device_add (dev);if (err <0 ) - goto err_free_id; + goto err_remove_chrdev;return 0 ; +err_remove_chrdev: +counter_chrdev_remove (counter); err_free_id:put_device (dev);return err;
@@ -138,13 +150,30 @@ int devm_counter_register(struct device *dev, }EXPORT_SYMBOL_GPL (devm_counter_register); +#define COUNTER_DEV_MAX 256 +static int __init counter_init (void ) { -return bus_register (&counter_bus_type); +int err; + + err =bus_register (&counter_bus_type); +if (err <0 ) +return err; + + err =alloc_chrdev_region (&counter_devt,0 ,COUNTER_DEV_MAX ,"counter" ); +if (err <0 ) + goto err_unregister_bus; + +return 0 ; + +err_unregister_bus: +bus_unregister (&counter_bus_type); +return err; } static void __exit counter_exit(void) { +unregister_chrdev_region (counter_devt,COUNTER_DEV_MAX );bus_unregister (&counter_bus_type); }
include/linux/counter.h +45 -0
90 lines not on this page · raw message
include/uapi/linux/counter.h +70 -0
82 lines not on this page · raw message
Signature · 1 line
2.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 17/22] counter: Add character device interface
Quoted 11 lines · On Fri, 12 Feb 2021 21:13:41 +0900 William Breathitt Gray…
This patch introduces a character device interface for the Counter subsystem. Device data is exposed through standard character device read operations. Device data is gathered when a Counter event is pushed by the respective Counter device driver. Configuration is handled via ioctl operations on the respective Counter character device node.
Cc David Lechner <[email protected]>Cc Gwendal Grignou <[email protected]>Cc Dan Carpenter <[email protected]>Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Hi William,
A few minor comments. Mostly seems to have come together well and makes sense to me.
Jonathan
Quoted 11 lines
--- drivers/counter/Makefile | 2 +- drivers/counter/counter-chrdev.c | 496 +++++++++++++++++++++++++++++++ drivers/counter/counter-chrdev.h | 16 + drivers/counter/counter-core.c | 37 ++- include/linux/counter.h | 45 +++ include/uapi/linux/counter.h | 70 +++++ 6 files changed, 661 insertions(+), 5 deletions(-) create mode 100644 drivers/counter/counter-chrdev.c create mode 100644 drivers/counter/counter-chrdev.h
...
Quoted 31 lines
drivers/counter/counter-core.c +6
-0@@ -5,12 +5,16 @@*/ #include <linux/counter.h> #include <linux/device.h> +#include <linux/device/bus.h> #include <linux/export.h> +#include <linux/fs.h> #include <linux/gfp.h> #include <linux/idr.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/types.h> +#include "counter-chrdev.h" #include "counter-sysfs.h" /* Provides a unique ID for each counter device */ @@ -33,6 +37,8 @@ static struct bus_type counter_bus_type = { .name = "counter" }; +static dev_t counter_devt; +/** * counter_register - register Counter to the system * @counter: pointer to Counter to register
drivers/counter/counter-core.c int counter_register(struct counter_device *const counter) · line 57
Quoted 4 lines
drivers/counter/counter-core.c +0
-1@@ -54,7 +60,6 @@ int counter_register(struct counter_device *const counter)if (counter->id <0 )return counter->id; -/* Configure device structure for Counter */
Not sure why this comment gets removed here.
Quoted 13 lines
drivers/counter/counter-core.c +5
-0dev->type = &counter_device_type; dev->bus = &counter_bus_type;if (counter->parent) {@@ -65,18 +70,25 @@ int counter_register(struct counter_device *const counter)device_initialize (dev);dev_set_drvdata (dev, counter); +/* Add Counter character device */ + err =counter_chrdev_add (counter, counter_devt); +if (err <0 ) + goto err_free_id; +/* Add Counter sysfs attributes */
drivers/counter/counter-core.c int counter_register(struct counter_device *const counter) · line 86
Quoted 10 lines
drivers/counter/counter-core.c +2
-2err =counter_sysfs_add (counter);if (err <0 ) - goto err_free_id; + goto err_remove_chrdev;/* Add device to system */ err =device_add (dev);if (err <0 ) - goto err_free_id; + goto err_remove_chrdev;
It might be worth thinking about using cdev_device_add() though will require a slightly different order of adding.
Quoted 40 lines
drivers/counter/counter-core.c +20
-1return 0 ; +err_remove_chrdev: +counter_chrdev_remove (counter); err_free_id:put_device (dev);return err;@@ -138,13 +150,30 @@ int devm_counter_register(struct device *dev, }EXPORT_SYMBOL_GPL (devm_counter_register); +#define COUNTER_DEV_MAX 256 +static int __init counter_init (void ) { -return bus_register (&counter_bus_type); +int err; + + err =bus_register (&counter_bus_type); +if (err <0 ) +return err; + + err =alloc_chrdev_region (&counter_devt,0 ,COUNTER_DEV_MAX ,"counter" ); +if (err <0 ) + goto err_unregister_bus; + +return 0 ; + +err_unregister_bus: +bus_unregister (&counter_bus_type); +return err; } static void __exit counter_exit(void) { +unregister_chrdev_region (counter_devt,COUNTER_DEV_MAX );bus_unregister (&counter_bus_type); }
...
Quoted 25 lines
include/uapi/linux/counter.h +13
-0@@ -6,6 +6,19 @@#ifndef _UAPI_COUNTER_H_#define _UAPI_COUNTER_H_ +#include <linux/ioctl.h> +#include <linux/types.h> + +/* Component type definitions */ +enum counter_component_type { +COUNTER_COMPONENT_NONE , +COUNTER_COMPONENT_SIGNAL , +COUNTER_COMPONENT_COUNT , +COUNTER_COMPONENT_FUNCTION , +COUNTER_COMPONENT_SYNAPSE_ACTION , +COUNTER_COMPONENT_EXTENSION , +}; +/* Component scope definitions */ enum counter_scope { COUNTER_SCOPE_DEVICE,
include/uapi/linux/counter.h enum counter_scope { · line 34
Quoted 9 lines
include/uapi/linux/counter.h +6
-0@@ -13,6 +26,63 @@ enum counter_scope { COUNTER_SCOPE_COUNT, }; +/** +* struct counter_component - Counter component identification +* @type: component type (one of enum counter_component_type) +* @scope: component scope (one of enum counter_scope) +* @parent: parent component ID (matching the Y/Z suffix of the respective sysfs +* path as described in Documentation/ABI/testing/sysfs-bus-counter)
Probably good to give an example here as well as the cross reference.
Quoted 54 lines
include/uapi/linux/counter.h +51
-0+* @id: component ID (matching the Y/Z suffix of the respective sysfs path as +* described in Documentation/ABI/testing/sysfs-bus-counter) +*/ +struct counter_component { +__u8 type; +__u8 scope; +__u8 parent; +__u8 id; +}; + +/* Event type definitions */ +enum counter_event_type { +COUNTER_EVENT_OVERFLOW , +COUNTER_EVENT_UNDERFLOW , +COUNTER_EVENT_OVERFLOW_UNDERFLOW , +COUNTER_EVENT_THRESHOLD , +COUNTER_EVENT_INDEX , +}; + +/** +* struct counter_watch - Counter component watch configuration +* @component: component to watch when event triggers +* @event: event that triggers (one of enum counter_event_type) +* @channel: event channel (typically 0 unless the device supports concurrent +* events of the same type) +*/ +struct counter_watch { +struct counter_component component; +__u8 event; +__u8 channel; +}; + +/* ioctl commands */ +#define COUNTER_ADD_WATCH_IOCTL _IOW(0x3E, 0x00, struct counter_watch) +#define COUNTER_ENABLE_EVENTS_IOCTL _IO(0x3E, 0x01) +#define COUNTER_DISABLE_EVENTS_IOCTL _IO(0x3E, 0x02) + +/** +* struct counter_event - Counter event data +* @timestamp: best estimate of time of event occurrence, in nanoseconds +* @value: component value +* @watch: component watch configuration +* @status: return status (system error number) +*/ +struct counter_event { +__aligned_u64 timestamp; +__aligned_u64 value; +struct counter_watch watch; +__u8 status; +}; +/* Count direction values */ enum counter_count_direction {COUNTER_COUNT_DIRECTION_FORWARD ,
Re: [PATCH v8 17/22] counter: Add character device interface
Quoted 70 lines · Jonathan Cameron
Quoted 11 lines · On Fri, 12 Feb 2021 21:13:41 +0900 William Breathitt Gray…
This patch introduces a character device interface for the Counter subsystem. Device data is exposed through standard character device read operations. Device data is gathered when a Counter event is pushed by the respective Counter device driver. Configuration is handled via ioctl operations on the respective Counter character device node.
Cc David Lechner <[email protected]>Cc Gwendal Grignou <[email protected]>Cc Dan Carpenter <[email protected]>Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>Hi William,
A few minor comments. Mostly seems to have come together well and makes sense to me.
Jonathan
Quoted 11 lines
--- drivers/counter/Makefile | 2 +- drivers/counter/counter-chrdev.c | 496 +++++++++++++++++++++++++++++++ drivers/counter/counter-chrdev.h | 16 + drivers/counter/counter-core.c | 37 ++- include/linux/counter.h | 45 +++ include/uapi/linux/counter.h | 70 +++++ 6 files changed, 661 insertions(+), 5 deletions(-) create mode 100644 drivers/counter/counter-chrdev.c create mode 100644 drivers/counter/counter-chrdev.h...
Quoted 34 lines
drivers/counter/counter-core.c +6
-0@@ -5,12 +5,16 @@*/ #include <linux/counter.h> #include <linux/device.h> +#include <linux/device/bus.h> #include <linux/export.h> +#include <linux/fs.h> #include <linux/gfp.h> #include <linux/idr.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/types.h> +#include "counter-chrdev.h" #include "counter-sysfs.h" /* Provides a unique ID for each counter device */ @@ -33,6 +37,8 @@ static struct bus_type counter_bus_type = { .name = "counter" }; +static dev_t counter_devt; +/** * counter_register - register Counter to the system * @counter: pointer to Counter to register @@ -54,7 +60,6 @@ int counter_register(struct counter_device *const counter)if (counter->id <0 )return counter->id;
Quoted 3 lines
drivers/counter/counter-core.c int counter_register(struct counter_device *const counter) · line 57
Quoted 1 line
drivers/counter/counter-core.c +0
-1-/* Configure device structure for Counter */ Not sure why this comment gets removed here.
This comment wasn't suppose to be removed. I'll revert this.
Quoted 18 lines
Quoted 18 lines
drivers/counter/counter-core.c +6
-1dev->type = &counter_device_type; dev->bus = &counter_bus_type;if (counter->parent) {@@ -65,18 +70,25 @@ int counter_register(struct counter_device *const counter)device_initialize (dev);dev_set_drvdata (dev, counter); +/* Add Counter character device */ + err =counter_chrdev_add (counter, counter_devt); +if (err <0 ) + goto err_free_id; +/* Add Counter sysfs attributes */ err =counter_sysfs_add (counter);if (err <0 ) - goto err_free_id; + goto err_remove_chrdev;
Quoted 8 lines
drivers/counter/counter-core.c int counter_register(struct counter_device *const counter) · line 86
Quoted 5 lines
drivers/counter/counter-core.c +1
-1/* Add device to system */ err =device_add (dev);if (err <0 ) - goto err_free_id; + goto err_remove_chrdev;It might be worth thinking about using
cdev_device_add()though will require a slightly different order of adding.
I think using cdev_device_add() should be possible. I'll adjust counter_chrdev_add() accordingly to account for this.
Quoted 71 lines
Quoted 40 lines
drivers/counter/counter-core.c +20
-1return 0 ; +err_remove_chrdev: +counter_chrdev_remove (counter); err_free_id:put_device (dev);return err;@@ -138,13 +150,30 @@ int devm_counter_register(struct device *dev, }EXPORT_SYMBOL_GPL (devm_counter_register); +#define COUNTER_DEV_MAX 256 +static int __init counter_init (void ) { -return bus_register (&counter_bus_type); +int err; + + err =bus_register (&counter_bus_type); +if (err <0 ) +return err; + + err =alloc_chrdev_region (&counter_devt,0 ,COUNTER_DEV_MAX ,"counter" ); +if (err <0 ) + goto err_unregister_bus; + +return 0 ; + +err_unregister_bus: +bus_unregister (&counter_bus_type); +return err; } static void __exit counter_exit(void) { +unregister_chrdev_region (counter_devt,COUNTER_DEV_MAX );bus_unregister (&counter_bus_type); }...
Quoted 28 lines
include/uapi/linux/counter.h +13
-0@@ -6,6 +6,19 @@#ifndef _UAPI_COUNTER_H_#define _UAPI_COUNTER_H_ +#include <linux/ioctl.h> +#include <linux/types.h> + +/* Component type definitions */ +enum counter_component_type { +COUNTER_COMPONENT_NONE , +COUNTER_COMPONENT_SIGNAL , +COUNTER_COMPONENT_COUNT , +COUNTER_COMPONENT_FUNCTION , +COUNTER_COMPONENT_SYNAPSE_ACTION , +COUNTER_COMPONENT_EXTENSION , +}; +/* Component scope definitions */ enum counter_scope { COUNTER_SCOPE_DEVICE,@@ -13,6 +26,63 @@ enum counter_scope { COUNTER_SCOPE_COUNT, };
Quoted 8 lines
include/uapi/linux/counter.h enum counter_scope { · line 34
Quoted 6 lines
include/uapi/linux/counter.h +6
-0+/** +* struct counter_component - Counter component identification +* @type: component type (one of enum counter_component_type) +* @scope: component scope (one of enum counter_scope) +* @parent: parent component ID (matching the Y/Z suffix of the respective sysfs +* path as described in Documentation/ABI/testing/sysfs-bus-counter) Probably good to give an example here as well as the cross reference.
Ack.
William Breathitt Gray
Re: [PATCH v8 17/22] counter: Add character device interface
In reply to William Breathitt GrayHi William,
Quoted 5 lines · William Breathitt Gray
This patch introduces a character device interface for the Counter subsystem. Device data is exposed through standard character device read operations. Device data is gathered when a Counter event is pushed by the respective Counter device driver. Configuration is handled via ioctl operations on the respective Counter character device node.
.....
Quoted 24 lines
drivers/counter/counter-chrdev.c new file +24
-0+/** +* counter_push_event - queue event for userspace reading +* @counter: pointer to Counter structure +* @event: triggered event +* @channel: event channel +* +* Note: If no one is watching for the respective event, it is silently +* discarded. +*/ +void counter_push_event (struct counter_device *const counter,const u8 event, +const u8 channel) +{ +struct counter_event ev = {0 }; +unsigned int copied =0 ; +unsigned long flags; +struct counter_event_node *event_node; +struct counter_comp_node *comp_node; + + ev.timestamp =ktime_get_ns (); + ev.watch.event = event; + ev.watch.channel = channel; + +/* Could be in an interrupt context, so use a raw spin lock */ +raw_spin_lock_irqsave (&counter->events_list_lock, flags);
drivers/counter/counter-chrdev.c line 480
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->events_list, l) +if (event_node->event == event && + event_node->channel == channel) +break ; + +/* If event is not in the list */ +if (&event_node->l == &counter->events_list) + goto exit_early;
To cover my "interrupt-counter" use case, I added following line here to convert the tail drop fifo to the head drop fifo:
+ list_for_each_entry(comp_node, &event_node->comp_list, l)
+ to_copy += sizeof(ev);
+
+ while (kfifo_avail(&counter->events) < to_copy)
+ kfifo_skip(&counter->events);
May be it make sense to make it optional and integrate in to you patches before it goes mainline?
Regards,
Oleksij
Signature · 4 lines
Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Re: [PATCH v8 17/22] counter: Add character device interface
Quoted 55 lines · Oleksij Rempel
Hi William,
Quoted 5 lines · William Breathitt Gray
This patch introduces a character device interface for the Counter subsystem. Device data is exposed through standard character device read operations. Device data is gathered when a Counter event is pushed by the respective Counter device driver. Configuration is handled via ioctl operations on the respective Counter character device node.
.....
Quoted 24 lines
drivers/counter/counter-chrdev.c new file +24
-0+/** +* counter_push_event - queue event for userspace reading +* @counter: pointer to Counter structure +* @event: triggered event +* @channel: event channel +* +* Note: If no one is watching for the respective event, it is silently +* discarded. +*/ +void counter_push_event (struct counter_device *const counter,const u8 event, +const u8 channel) +{ +struct counter_event ev = {0 }; +unsigned int copied =0 ; +unsigned long flags; +struct counter_event_node *event_node; +struct counter_comp_node *comp_node; + + ev.timestamp =ktime_get_ns (); + ev.watch.event = event; + ev.watch.channel = channel; + +/* Could be in an interrupt context, so use a raw spin lock */ +raw_spin_lock_irqsave (&counter->events_list_lock, flags);drivers/counter/counter-chrdev.c line 480
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->events_list, l) +if (event_node->event == event && + event_node->channel == channel) +break ; + +/* If event is not in the list */ +if (&event_node->l == &counter->events_list) + goto exit_early;To cover my "interrupt-counter" use case, I added following line here to convert the tail drop fifo to the head drop fifo:
(quoted diff) +5
-0+ list_for_each_entry(comp_node, &event_node->comp_list, l) + to_copy += sizeof(ev); + + while (kfifo_avail(&counter->events) < to_copy) + kfifo_skip(&counter->events);
Quoted 10 lines
May be it make sense to make it optional and integrate in to you patches before it goes mainline?
Regards,
OleksijSignature · 4 lines
Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Hello Oleksij,
I appreciate your suggestion, and I'm excited about your interrupt-counter driver -- it looks like the Counter character device interface will be central for that driver. However, I want to hold off on adding further functionality to this patchset so that we can stablize it enough to merge.
Once the Counter character device interface is merged, please send your changes again as a patch and we can review it further then.
Thank you,
William Breathitt Gray
PATCH v8 18/22 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 | 243 +++++++++++++++--- .../userspace-api/ioctl/ioctl-number.rst | 1 + 2 files changed, 203 insertions(+), 41 deletions(-)
Documentation/driver-api/generic-counter.rst +202 -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,170 @@ 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. + +For example, the following userspace code opens ``/dev/counter0``, +configures the ``COUNTER_EVENT_INDEX`` event channel 0 to gather Count 0 +and Count 1, and prints out the data as it becomes available on the +character device node:: + + #include <fcntl.h> + #include <linux/counter.h> + #include <stdio.h> + #include <string.h> + #include <sys/ioctl.h> + #include <unistd.h> + + struct counter_watch watches[2] = { + { + .component.type = COUNTER_COMPONENT_COUNT, + .component.scope = COUNTER_SCOPE_COUNT, + .component.parent = 0, + .event = COUNTER_EVENT_INDEX, + .channel = 0, + }, + { + .component.type = COUNTER_COMPONENT_COUNT, + .component.scope = COUNTER_SCOPE_COUNT, + .component.parent = 1, + .event = COUNTER_EVENT_INDEX, + .channel = 0, + }, + }; + + int main(void) + { + int fd; + struct counter_event event_data[2]; + + fd = open("/dev/counter0", O_RDWR); + + ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches); + ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + 1); + ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL); + + for (;;) { + read(fd, event_data, sizeof(event_data)); + + printf("Timestamp 0: %llu\tCount 0: %llu\n" + "Error Message 0: %s\n" + "Timestamp 1: %llu\tCount 1: %llu\n" + "Error Message 1: %s\n", + (unsigned long long)event_data[0].timestamp, + (unsigned long long)event_data[0].value, + strerror(event_data[0].status), + (unsigned long long)event_data[1].timestamp, + (unsigned long long)event_data[1].value, + strerror(event_data[1].status)); + } + + return 0; + }
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.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 18/22] docs: counter: Document character device interface
Quoted 199 lines · On Fri, 12 Feb 2021 21:13:42 +0900 William Breathitt Gray…
This patch adds high-level documentation about the Counter subsystem character device interface.
Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/driver-api/generic-counter.rst | 243 +++++++++++++++--- .../userspace-api/ioctl/ioctl-number.rst | 1 + 2 files changed, 203 insertions(+), 41 deletions(-)Documentation/driver-api/generic-counter.rst +113
-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,170 @@ 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.
Documentation/driver-api/generic-counter.rst and vice versa. · line 557
Quoted 10 lines
Documentation/driver-api/generic-counter.rst +10
-0+ +* 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.
Is there a way to remove a watch?
Quoted 17 lines
Documentation/driver-api/generic-counter.rst +17
-0+ +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.
Documentation/driver-api/generic-counter.rst and vice versa. · line 584
Quoted 10 lines
Documentation/driver-api/generic-counter.rst +10
-0+ +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. + +For example, the following userspace code opens ``/dev/counter0``, +configures the ``COUNTER_EVENT_INDEX`` event channel 0 to gather Count 0 +and Count 1, and prints out the data as it becomes available on the +character device node:: +
Consider adding an example program under tools/
Documentation/driver-api/generic-counter.rst and vice versa. · line 596
Quoted 12 lines
Documentation/driver-api/generic-counter.rst +12
-0+ #include <fcntl.h> + #include <linux/counter.h> + #include <stdio.h> + #include <string.h> + #include <sys/ioctl.h> + #include <unistd.h> + + struct counter_watch watches[2] = { + { + .component.type = COUNTER_COMPONENT_COUNT, + .component.scope = COUNTER_SCOPE_COUNT, + .component.parent = 0,
Good to add comments on what these elements actually are?
Quoted 52 lines
Documentation/driver-api/generic-counter.rst +40
-0+ .event = COUNTER_EVENT_INDEX, + .channel = 0, + }, + { + .component.type = COUNTER_COMPONENT_COUNT, + .component.scope = COUNTER_SCOPE_COUNT, + .component.parent = 1, + .event = COUNTER_EVENT_INDEX, + .channel = 0, + }, + }; + + int main(void) + { + int fd; + struct counter_event event_data[2]; + + fd = open("/dev/counter0", O_RDWR); + + ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches); + ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + 1); + ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL); + + for (;;) { + read(fd, event_data, sizeof(event_data)); + + printf("Timestamp 0: %llu\tCount 0: %llu\n" + "Error Message 0: %s\n" + "Timestamp 1: %llu\tCount 1: %llu\n" + "Error Message 1: %s\n", + (unsigned long long)event_data[0].timestamp, + (unsigned long long)event_data[0].value, + strerror(event_data[0].status), + (unsigned long long)event_data[1].timestamp, + (unsigned long long)event_data[1].value, + strerror(event_data[1].status)); + } + + return 0; + }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
Re: [PATCH v8 18/22] docs: counter: Document character device interface
Hi!
Quoted 11 lines
Documentation/driver-api/generic-counter.rst and vice versa. · line 557
Quoted 9 lines
Documentation/driver-api/generic-counter.rst +9
-0+* 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.Is there a way to remove a watch?
Is there a way to eat all kernel memory and crash the system by adding too many watches?
Quoted 21 lines
Documentation/driver-api/generic-counter.rst and vice versa. · line 584
Quoted 5 lines
Documentation/driver-api/generic-counter.rst +5
-0+For example, the following userspace code opens ``/dev/counter0``, +configures the ``COUNTER_EVENT_INDEX`` event channel 0 to gather Count 0 +and Count 1, and prints out the data as it becomes available on the +character device node:: +Consider adding an example program under
tools/Documentation/driver-api/generic-counter.rst and vice versa. · line 596
Quoted 12 lines
Documentation/driver-api/generic-counter.rst +12
-0+ #include <fcntl.h> + #include <linux/counter.h> + #include <stdio.h> + #include <string.h> + #include <sys/ioctl.h> + #include <unistd.h> + + struct counter_watch watches[2] = { + { + .component.type = COUNTER_COMPONENT_COUNT, + .component.scope = COUNTER_SCOPE_COUNT, + .component.parent = 0,
Quoted 10 lines
Good to add comments on what these elements actually are?
Quoted 8 lines
Documentation/driver-api/generic-counter.rst +7
-0+ fd = open("/dev/counter0", O_RDWR); + + ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches); + ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + 1); + ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL); + for (;;) { + read(fd, event_data, sizeof(event_data));
If this goes to tools it really should have error handling and handling of short read.
Best regards,
Pavel
Signature · 1 line
http://www.livejournal.com/~pavelmachek
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [PATCH v8 18/22] docs: counter: Document character device interface
Quoted 14 lines · Pavel Machek
Hi!
Quoted 11 lines
Documentation/driver-api/generic-counter.rst and vice versa. · line 557
Quoted 9 lines
Documentation/driver-api/generic-counter.rst +9
-0+* 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.Is there a way to remove a watch?
Quoted 2 lines
Is there a way to eat all kernel memory and crash the system by adding too many watches?
There can only ever be as many watches as there are Counter components for the respective Counter device. This is enforced by counter_set_event_node() which checks whether a particular watch has been created before and returns an EINVAL if it so has.
Quoted 29 lines
Quoted 28 lines
Documentation/driver-api/generic-counter.rst and vice versa. · line 584
Quoted 5 lines
Documentation/driver-api/generic-counter.rst +5
-0+For example, the following userspace code opens ``/dev/counter0``, +configures the ``COUNTER_EVENT_INDEX`` event channel 0 to gather Count 0 +and Count 1, and prints out the data as it becomes available on the +character device node:: +Consider adding an example program under
tools/Documentation/driver-api/generic-counter.rst and vice versa. · line 596
Quoted 12 lines
Documentation/driver-api/generic-counter.rst +12
-0+ #include <fcntl.h> + #include <linux/counter.h> + #include <stdio.h> + #include <string.h> + #include <sys/ioctl.h> + #include <unistd.h> + + struct counter_watch watches[2] = { + { + .component.type = COUNTER_COMPONENT_COUNT, + .component.scope = COUNTER_SCOPE_COUNT, + .component.parent = 0,Good to add comments on what these elements actually are?
Quoted 5 lines
Documentation/driver-api/generic-counter.rst +5
-0+ fd = open("/dev/counter0", O_RDWR); + + ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches); + ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + 1); + ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL);
Quoted 11 lines
Quoted 2 lines
Documentation/driver-api/generic-counter.rst and vice versa. · line 621
Quoted 2 lines
Documentation/driver-api/generic-counter.rst +2
-0+ for (;;) { + read(fd, event_data, sizeof(event_data));If this goes to tools it really should have error handling and handling of short read.
Best regards,
PavelSignature · 1 line
http://www.livejournal.com/~pavelmachek
Ack. I'll improve the error handling for this.
William Breathitt Gray
Re: [PATCH v8 18/22] docs: counter: Document character device interface
In reply to Jonathan CameronQuoted 206 lines · Jonathan Cameron
Quoted 203 lines · On Fri, 12 Feb 2021 21:13:42 +0900 William Breathitt Gray…
This patch adds high-level documentation about the Counter subsystem character device interface.
Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/driver-api/generic-counter.rst | 243 +++++++++++++++--- .../userspace-api/ioctl/ioctl-number.rst | 1 + 2 files changed, 203 insertions(+), 41 deletions(-)Documentation/driver-api/generic-counter.rst +117
-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,170 @@ 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
Quoted 8 lines
Documentation/driver-api/generic-counter.rst and vice versa. · line 557
Quoted 6 lines
Documentation/driver-api/generic-counter.rst +6
-0+ 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.Is there a way to remove a watch?
Both COUNTER_ENABLE_EVENTS_IOCTL and COUNTER_DISABLE_EVENTS_IOCTL remove the watches -- the only difference is that COUNTER_ENABLE_EVENTS_IOCTL will also swap in a new set of watches. The watches are also removed if a user closes the cdev.
If you mean whether there is a way to selectively remove a single watch, then the process for that would be to generate a new set of watches using COUNTER_ADD_WATCH_IOCTL and then swap them in by using COUNTER_ENABLE_EVENTS_IOCTL. This swap happens atomically so there's no risk of missing an event. The user should already know the current configuration of watches because they are the ones who added them after opening the cdev, so we don't need to worry about dealing with an old unknown watch configuration created by someone else.
Quoted 21 lines
Quoted 21 lines
Documentation/driver-api/generic-counter.rst +21
-0+ +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.
Quoted 8 lines
Documentation/driver-api/generic-counter.rst and vice versa. · line 584
Quoted 6 lines
Documentation/driver-api/generic-counter.rst +6
-0+ +For example, the following userspace code opens ``/dev/counter0``, +configures the ``COUNTER_EVENT_INDEX`` event channel 0 to gather Count 0 +and Count 1, and prints out the data as it becomes available on the +character device node:: +Consider adding an example program under
tools/
I can put this example program we have here below under tools/. I'd like to create a more general Counter test program in the future, but I think it will be a more involved project to undertake right now given the differences between the possible configurations available and possible for the Counter drivers we have.
Quoted 13 lines
Documentation/driver-api/generic-counter.rst and vice versa. · line 596
Quoted 12 lines
Documentation/driver-api/generic-counter.rst +12
-0+ #include <fcntl.h> + #include <linux/counter.h> + #include <stdio.h> + #include <string.h> + #include <sys/ioctl.h> + #include <unistd.h> + + struct counter_watch watches[2] = { + { + .component.type = COUNTER_COMPONENT_COUNT, + .component.scope = COUNTER_SCOPE_COUNT, + .component.parent = 0,
Quoted 1 line
Good to add comments on what these elements actually are?
Ack.
William Breathitt Gray
PATCH v8 19/22 counter: Implement extension*_name sysfs attributes
In reply to William Breathitt GrayThe Generic Counter chrdev interface expects users to supply extension IDs in order to select extensions for requests. In order for users to know what extension ID belongs to which extension this information must be exposed. The extension*_name attribute provides a way for users to discover what extension ID belongs to which extension by reading the respective extension name for an extension ID.
--- Documentation/ABI/testing/sysfs-bus-counter | 9 ++++ drivers/counter/counter-sysfs.c | 51 +++++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-)
Documentation/ABI/testing/sysfs-bus-counter +9 -0
@@ -100,6 +100,15 @@ Description: Read-only attribute that indicates whether excessive noise is present at the channel Y counter inputs. +What: /sys/bus/counter/devices/counterX/countY/extensionZ_name +What: /sys/bus/counter/devices/counterX/extensionZ_name +What: /sys/bus/counter/devices/counterX/signalY/extensionZ_name +KernelVersion: 5.13 +Contact: [email protected] +Description: + Read-only attribute that indicates the component name of + Extension Z. + What: /sys/bus/counter/devices/counterX/countY/function KernelVersion: 5.2 Contact: [email protected]
drivers/counter/counter-sysfs.c +41 -10
122 lines not on this page · raw message
Signature · 1 line
2.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 19/22] counter: Implement extension*_name sysfs attributes
Quoted 22 lines · On Fri, 12 Feb 2021 21:13:43 +0900 William Breathitt Gray…
The Generic Counter chrdev interface expects users to supply extension IDs in order to select extensions for requests. In order for users to know what extension ID belongs to which extension this information must be exposed. The extension*_name attribute provides a way for users to discover what extension ID belongs to which extension by reading the respective extension name for an extension ID.
Cc David Lechner <[email protected]>Cc Gwendal Grignou <[email protected]>Cc Dan Carpenter <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 9 ++++ drivers/counter/counter-sysfs.c | 51 +++++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-)Documentation/ABI/testing/sysfs-bus-counter +0
-0@@ -100,6 +100,15 @@ Description: Read-only attribute that indicates whether excessive noise is
Documentation/ABI/testing/sysfs-bus-counter Description: · line 110
Quoted 10 lines
Documentation/ABI/testing/sysfs-bus-counter +8
-0present at the channel Y counter inputs. +What: /sys/bus/counter/devices/counterX/countY/extensionZ_name +What: /sys/bus/counter/devices/counterX/extensionZ_name +What: /sys/bus/counter/devices/counterX/signalY/extensionZ_name +KernelVersion: 5.13 +Contact: [email protected] +Description: + Read-only attribute that indicates the component name of + Extension Z.
Good to say what form this takes.
Quoted 1 line
Documentation/ABI/testing/sysfs-bus-counter +1
-0+
Re: [PATCH v8 19/22] counter: Implement extension*_name sysfs attributes
Quoted 27 lines · Jonathan Cameron
Quoted 24 lines · On Fri, 12 Feb 2021 21:13:43 +0900 William Breathitt Gray…
The Generic Counter chrdev interface expects users to supply extension IDs in order to select extensions for requests. In order for users to know what extension ID belongs to which extension this information must be exposed. The extension*_name attribute provides a way for users to discover what extension ID belongs to which extension by reading the respective extension name for an extension ID.
Cc David Lechner <[email protected]>Cc Gwendal Grignou <[email protected]>Cc Dan Carpenter <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 9 ++++ drivers/counter/counter-sysfs.c | 51 +++++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-)Documentation/ABI/testing/sysfs-bus-counter +0
-0@@ -100,6 +100,15 @@ Description: Read-only attribute that indicates whether excessive noise is present at the channel Y counter inputs.
Quoted 10 lines
Documentation/ABI/testing/sysfs-bus-counter Description: · line 110
Quoted 8 lines
Documentation/ABI/testing/sysfs-bus-counter +8
-0+What: /sys/bus/counter/devices/counterX/countY/extensionZ_name +What: /sys/bus/counter/devices/counterX/extensionZ_name +What: /sys/bus/counter/devices/counterX/signalY/extensionZ_name +KernelVersion: 5.13 +Contact: [email protected] +Description: + Read-only attribute that indicates the component name of + Extension Z.Good to say what form this takes.
Do you mean a description like this: "Read-only string attribute that indicates the component name of Extension Z"?
William Breathitt Gray
Jonathan Cameron
maintainerRe: [PATCH v8 19/22] counter: Implement extension*_name sysfs attributes
Quoted 39 lines · On Fri, 19 Feb 2021 17:51:37 +0900 William Breathitt Gray…
Quoted 27 lines · Jonathan Cameron
Quoted 24 lines · On Fri, 12 Feb 2021 21:13:43 +0900 William Breathitt Gray…
The Generic Counter chrdev interface expects users to supply extension IDs in order to select extensions for requests. In order for users to know what extension ID belongs to which extension this information must be exposed. The extension*_name attribute provides a way for users to discover what extension ID belongs to which extension by reading the respective extension name for an extension ID.
Cc David Lechner <[email protected]>Cc Gwendal Grignou <[email protected]>Cc Dan Carpenter <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 9 ++++ drivers/counter/counter-sysfs.c | 51 +++++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-)Documentation/ABI/testing/sysfs-bus-counter +0
-0@@ -100,6 +100,15 @@ Description: Read-only attribute that indicates whether excessive noise is present at the channel Y counter inputs.Quoted 10 lines
Documentation/ABI/testing/sysfs-bus-counter Description: · line 110
Quoted 8 lines
Documentation/ABI/testing/sysfs-bus-counter +8
-0+What: /sys/bus/counter/devices/counterX/countY/extensionZ_name +What: /sys/bus/counter/devices/counterX/extensionZ_name +What: /sys/bus/counter/devices/counterX/signalY/extensionZ_name +KernelVersion: 5.13 +Contact: [email protected] +Description: + Read-only attribute that indicates the component name of + Extension Z.Good to say what form this takes.
Quoted 2 lines
Do you mean a description like this: "Read-only string attribute that indicates the component name of Extension Z"?
My expectation would be that the possible strings are tightly constrained (perhaps via review). So I'd like to see what they are and a brief description of what each one means.
Jonathan
Quoted 2 lines
William Breathitt Gray
Re: [PATCH v8 19/22] counter: Implement extension*_name sysfs attributes
Quoted 42 lines · Jonathan Cameron
Quoted 39 lines · On Fri, 19 Feb 2021 17:51:37 +0900 William Breathitt Gray…
Quoted 37 lines · Jonathan Cameron
Quoted 22 lines · On Fri, 12 Feb 2021 21:13:43 +0900 William Breathitt Gray…
The Generic Counter chrdev interface expects users to supply extension IDs in order to select extensions for requests. In order for users to know what extension ID belongs to which extension this information must be exposed. The extension*_name attribute provides a way for users to discover what extension ID belongs to which extension by reading the respective extension name for an extension ID.
Cc David Lechner <[email protected]>Cc Gwendal Grignou <[email protected]>Cc Dan Carpenter <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 9 ++++ drivers/counter/counter-sysfs.c | 51 +++++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-)Documentation/ABI/testing/sysfs-bus-counter +0
-0@@ -100,6 +100,15 @@ Description: Read-only attribute that indicates whether excessive noise isDocumentation/ABI/testing/sysfs-bus-counter Description: · line 110
Quoted 10 lines
Documentation/ABI/testing/sysfs-bus-counter +8
-0present at the channel Y counter inputs. +What: /sys/bus/counter/devices/counterX/countY/extensionZ_name +What: /sys/bus/counter/devices/counterX/extensionZ_name +What: /sys/bus/counter/devices/counterX/signalY/extensionZ_name +KernelVersion: 5.13 +Contact: [email protected] +Description: + Read-only attribute that indicates the component name of + Extension Z.Good to say what form this takes.
Quoted 8 lines
Quoted 2 lines
Do you mean a description like this: "Read-only string attribute that indicates the component name of Extension Z"?
My expectation would be that the possible strings are tightly constrained (perhaps via review). So I'd like to see what they are and a brief description of what each one means.
Jonathan
Okay I see what you mean now. These names will match the sysfs attribute filenames. So for example, if Extension 9 of Count 2 of Counter device is /sys/bus/counter/devices/counter4/count2/ceiling, then the attribute /sys/bus/counter/devices/counter4/count2/extension9_name will hold a value of "ceiling".
The idea is that the user walks down through each extension*_name to find sysfs attribute name for the Extension that they want. When they find the desired Extension name in say sysfs attribute extension9_name, then they know 9 is the ID number for that Extension.
There is an alternative design I was considering: instead of extension*_name attributes, we could have each Extension sysfs attribute have a matching *_extension_id attribute which provides the respective Extension ID. So for example, using the same Extension as before:/sys/bus/counter/devices/counter4/count2/ceiling_extension_id will hold a value of 9.
Do you think this alternative design would be more intuitive to users?
William Breathitt Gray
Jonathan Cameron
maintainerRe: [PATCH v8 19/22] counter: Implement extension*_name sysfs attributes
Quoted 63 lines · On Fri, 26 Feb 2021 08:32:59 +0900 William Breathitt Gray…
Quoted 42 lines · Jonathan Cameron
Quoted 39 lines · On Fri, 19 Feb 2021 17:51:37 +0900 William Breathitt Gray…
Quoted 37 lines · Jonathan Cameron
Quoted 22 lines · On Fri, 12 Feb 2021 21:13:43 +0900 William Breathitt Gray…
The Generic Counter chrdev interface expects users to supply extension IDs in order to select extensions for requests. In order for users to know what extension ID belongs to which extension this information must be exposed. The extension*_name attribute provides a way for users to discover what extension ID belongs to which extension by reading the respective extension name for an extension ID.
Cc David Lechner <[email protected]>Cc Gwendal Grignou <[email protected]>Cc Dan Carpenter <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 9 ++++ drivers/counter/counter-sysfs.c | 51 +++++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-)Documentation/ABI/testing/sysfs-bus-counter +0
-0@@ -100,6 +100,15 @@ Description: Read-only attribute that indicates whether excessive noise isDocumentation/ABI/testing/sysfs-bus-counter Description: · line 110
Quoted 10 lines
Documentation/ABI/testing/sysfs-bus-counter +8
-0present at the channel Y counter inputs. +What: /sys/bus/counter/devices/counterX/countY/extensionZ_name +What: /sys/bus/counter/devices/counterX/extensionZ_name +What: /sys/bus/counter/devices/counterX/signalY/extensionZ_name +KernelVersion: 5.13 +Contact: [email protected] +Description: + Read-only attribute that indicates the component name of + Extension Z.Good to say what form this takes.
Quoted 8 lines
Quoted 2 lines
Do you mean a description like this: "Read-only string attribute that indicates the component name of Extension Z"?
My expectation would be that the possible strings are tightly constrained (perhaps via review). So I'd like to see what they are and a brief description of what each one means.
Jonathan
Okay I see what you mean now. These names will match the sysfs attribute filenames. So for example, if Extension 9 of Count 2 of Counter device is
/sys/bus/counter/devices/counter4/count2/ceiling, then the attribute/sys/bus/counter/devices/counter4/count2/extension9_namewill hold a value of "ceiling".The idea is that the user walks down through each extension*_name to find sysfs attribute name for the Extension that they want. When they find the desired Extension name in say sysfs attribute
extension9_name, then they know 9 is the ID number for that Extension.
Quoted 8 lines
There is an alternative design I was considering: instead of extension*_name attributes, we could have each Extension sysfs attribute have a matching
*_extension_idattribute which provides the respective Extension ID. So for example, using the same Extension as before:/sys/bus/counter/devices/counter4/count2/ceiling_extension_idwill hold a value of 9.Do you think this alternative design would be more intuitive to users?
It feels like the user is going to start from what they want to enable
then get the ID from that. With the current way around they'll have
to search the extensionX_name files to find it, rather than a direct look up. So immediate thought is this second way would be easier to use, but perhaps others think differently.
Jonathan
Quoted 2 lines
William Breathitt Gray
PATCH v8 20/22 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 | 23 +++++++++++++++++++ drivers/counter/counter-chrdev.h | 2 ++ drivers/counter/counter-sysfs.c | 25 +++++++++++++++++++++ 4 files changed, 58 insertions(+)
Documentation/ABI/testing/sysfs-bus-counter +8 -0
@@ -212,6 +212,14 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.13 +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 +23 -0
@@ -375,6 +375,29 @@ void counter_chrdev_remove(struct counter_device *const counter)cdev_del (&counter->chrdev); } +int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size) +{ +int err; + DECLARE_KFIFO_PTR(events, struct counter_event); +unsigned long flags; + +/* Allocate new events queue */ + err =kfifo_alloc (&events, queue_size,GFP_ATOMIC ); +if (err) +return err; + +raw_spin_lock_irqsave (&counter->events_list_lock, flags); + +/* Swap in new events queue */ +kfifo_free (&counter->events); + counter->events.kfifo = events.kfifo; + +raw_spin_unlock_irqrestore (&counter->events_list_lock, flags); + +return 0 ; +} +static int counter_get_data (struct counter_device *const counter,const struct counter_comp_node *const comp_node,u64 *const value)
drivers/counter/counter-chrdev.h +2 -0
@@ -12,5 +12,7 @@int counter_chrdev_add (struct counter_device *const counter,const dev_t counter_devt);void counter_chrdev_remove (struct counter_device *const counter); +int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size);#endif /* _COUNTER_CHRDEV_H_ */
drivers/counter/counter-sysfs.c +25 -0
@@ -13,6 +13,7 @@#include <linux/sysfs.h> #include <linux/types.h> +#include "counter-chrdev.h" #include "counter-sysfs.h" /**
@@ -737,12 +738,30 @@ static int counter_num_counts_read(struct counter_device *counter, u8 *val)return 0 ; } +static int counter_events_queue_size_read (struct counter_device *counter, +u64 *val) +{ + *val = counter->events.kfifo.mask +1 ; +return 0 ; +} + +static int counter_events_queue_size_write (struct counter_device *counter, +u64 val) +{ +return counter_chrdev_realloc_queue (counter, val); +} +static struct counter_comp counter_num_signals_comp =COUNTER_COMP_DEVICE_U8 ("num_signals" , counter_num_signals_read,NULL );static struct counter_comp counter_num_counts_comp =COUNTER_COMP_DEVICE_U8 ("num_counts" , counter_num_counts_read,NULL ); +static struct counter_comp counter_events_queue_size_comp = +COUNTER_COMP_DEVICE_U64 ("events_queue_size" , + counter_events_queue_size_read, + counter_events_queue_size_write); +static int counter_sysfs_attr_add (struct counter_device *const counter,struct counter_attribute_group *group) {
@@ -781,6 +800,12 @@ static int counter_sysfs_attr_add(struct counter_device *const counter,if (err <0 )return err; +/* Create num_counts attribute */ + err =counter_attr_create (dev, group, &counter_events_queue_size_comp, + scope,NULL ); +if (err <0 ) +return err; +/* Create an attribute for each extension */ for (i =0 ; i < counter->num_ext; i++) { ext = counter->ext + i;
Signature · 1 line
2.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 20/22] counter: Implement events_queue_size sysfs attribute
Quoted 42 lines · On Fri, 12 Feb 2021 21:13:44 +0900 William Breathitt Gray…
The
events_queue_sizesysfs 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 structcounter_eventdata structures. The number of elements will be rounded-up to a power of 2 due to a requirement of thekfifo_allocfunction called during reallocation of the queue.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 8 +++++++ drivers/counter/counter-chrdev.c | 23 +++++++++++++++++++ drivers/counter/counter-chrdev.h | 2 ++ drivers/counter/counter-sysfs.c | 25 +++++++++++++++++++++ 4 files changed, 58 insertions(+)Documentation/ABI/testing/sysfs-bus-counter +8
-0@@ -212,6 +212,14 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.13 +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 +0
-0@@ -375,6 +375,29 @@ void counter_chrdev_remove(struct counter_device *const counter)cdev_del (&counter->chrdev); }
drivers/counter/counter-chrdev.c void counter_chrdev_remove(struct counter_device *const counter) · line 386
Quoted 10 lines
drivers/counter/counter-chrdev.c +9
-0+int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size) +{ +int err; + DECLARE_KFIFO_PTR(events, struct counter_event); +unsigned long flags; + +/* Allocate new events queue */ + err =kfifo_alloc (&events, queue_size,GFP_ATOMIC );
Is there any potential for losing events?
Quoted 42 lines
drivers/counter/counter-chrdev.c +14
-0+if (err) +return err; + +raw_spin_lock_irqsave (&counter->events_list_lock, flags); + +/* Swap in new events queue */ +kfifo_free (&counter->events); + counter->events.kfifo = events.kfifo; + +raw_spin_unlock_irqrestore (&counter->events_list_lock, flags); + +return 0 ; +} +static int counter_get_data (struct counter_device *const counter,const struct counter_comp_node *const comp_node,u64 *const value)drivers/counter/counter-chrdev.h +2
-0@@ -12,5 +12,7 @@int counter_chrdev_add (struct counter_device *const counter,const dev_t counter_devt);void counter_chrdev_remove (struct counter_device *const counter); +int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size);#endif /* _COUNTER_CHRDEV_H_ */ drivers/counter/counter-sysfs.c +1
-0@@ -13,6 +13,7 @@#include <linux/sysfs.h> #include <linux/types.h> +#include "counter-chrdev.h" #include "counter-sysfs.h" /**
drivers/counter/counter-sysfs.c static int counter_num_counts_read(struct counter_device *counter, u8 *val) · line 744
Quoted 7 lines
drivers/counter/counter-sysfs.c +4
-0@@ -737,12 +738,30 @@ static int counter_num_counts_read(struct counter_device *counter, u8 *val)return 0 ; } +static int counter_events_queue_size_read (struct counter_device *counter, +u64 *val) +{ + *val = counter->events.kfifo.mask +1 ;
kfifo_size() rather than open coding it?
Quoted 36 lines
drivers/counter/counter-sysfs.c +20
-0+return 0 ; +} + +static int counter_events_queue_size_write (struct counter_device *counter, +u64 val) +{ +return counter_chrdev_realloc_queue (counter, val); +} +static struct counter_comp counter_num_signals_comp =COUNTER_COMP_DEVICE_U8 ("num_signals" , counter_num_signals_read,NULL );static struct counter_comp counter_num_counts_comp =COUNTER_COMP_DEVICE_U8 ("num_counts" , counter_num_counts_read,NULL ); +static struct counter_comp counter_events_queue_size_comp = +COUNTER_COMP_DEVICE_U64 ("events_queue_size" , + counter_events_queue_size_read, + counter_events_queue_size_write); +static int counter_sysfs_attr_add (struct counter_device *const counter,struct counter_attribute_group *group) {@@ -781,6 +800,12 @@ static int counter_sysfs_attr_add(struct counter_device *const counter,if (err <0 )return err; +/* Create num_counts attribute */ + err =counter_attr_create (dev, group, &counter_events_queue_size_comp, + scope,NULL ); +if (err <0 ) +return err; +/* Create an attribute for each extension */ for (i =0 ; i < counter->num_ext; i++) { ext = counter->ext + i;
Re: [PATCH v8 20/22] counter: Implement events_queue_size sysfs attribute
Quoted 46 lines · Jonathan Cameron
Quoted 43 lines · On Fri, 12 Feb 2021 21:13:44 +0900 William Breathitt Gray…
The
events_queue_sizesysfs 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 structcounter_eventdata structures. The number of elements will be rounded-up to a power of 2 due to a requirement of thekfifo_allocfunction called during reallocation of the queue.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 8 +++++++ drivers/counter/counter-chrdev.c | 23 +++++++++++++++++++ drivers/counter/counter-chrdev.h | 2 ++ drivers/counter/counter-sysfs.c | 25 +++++++++++++++++++++ 4 files changed, 58 insertions(+)Documentation/ABI/testing/sysfs-bus-counter +8
-0@@ -212,6 +212,14 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.13 +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 +0
-0@@ -375,6 +375,29 @@ void counter_chrdev_remove(struct counter_device *const counter)cdev_del (&counter->chrdev); }
Quoted 11 lines
drivers/counter/counter-chrdev.c void counter_chrdev_remove(struct counter_device *const counter) · line 386
Quoted 9 lines
drivers/counter/counter-chrdev.c +9
-0+int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size) +{ +int err; + DECLARE_KFIFO_PTR(events, struct counter_event); +unsigned long flags; + +/* Allocate new events queue */ + err =kfifo_alloc (&events, queue_size,GFP_ATOMIC );Is there any potential for losing events?
We take the events_list_lock down below so we're safe against missing an event, but past events currently unread in the queue will be lost.
Shortening the size of the queue is inherently a destructive process if we have more events in the current queue than can fit in the new queue. Because we a liable to lose some events in such a case, I think it's best to keep the behavior of this reallocation consistent and have it provide a fresh empty queue every time, as opposed to sometimes dropping events and sometimes not.
I also suspect an actual user would be setting the size of their queue to the required amount before they begin watching events, rather than adjusting it sporadically during a live operation.
Quoted 45 lines
Quoted 45 lines
drivers/counter/counter-chrdev.c +14
-0+if (err) +return err; + +raw_spin_lock_irqsave (&counter->events_list_lock, flags); + +/* Swap in new events queue */ +kfifo_free (&counter->events); + counter->events.kfifo = events.kfifo; + +raw_spin_unlock_irqrestore (&counter->events_list_lock, flags); + +return 0 ; +} +static int counter_get_data (struct counter_device *const counter,const struct counter_comp_node *const comp_node,u64 *const value)drivers/counter/counter-chrdev.h +2
-0@@ -12,5 +12,7 @@int counter_chrdev_add (struct counter_device *const counter,const dev_t counter_devt);void counter_chrdev_remove (struct counter_device *const counter); +int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size);#endif /* _COUNTER_CHRDEV_H_ */ drivers/counter/counter-sysfs.c +1
-0@@ -13,6 +13,7 @@#include <linux/sysfs.h> #include <linux/types.h> +#include "counter-chrdev.h" #include "counter-sysfs.h" /** @@ -737,12 +738,30 @@ static int counter_num_counts_read(struct counter_device *counter, u8 *val)return 0 ; }
Quoted 6 lines
drivers/counter/counter-sysfs.c static int counter_num_counts_read(struct counter_device *counter, u8 *val) · line 744
Quoted 4 lines
drivers/counter/counter-sysfs.c +4
-0+static int counter_events_queue_size_read (struct counter_device *counter, +u64 *val) +{ + *val = counter->events.kfifo.mask +1 ;
kfifo_size()rather than open coding it?
Ack.
William Breathitt Gray
Quoted 27 lines
Quoted 27 lines
drivers/counter/counter-sysfs.c +14
-0+return 0 ; +} + +static int counter_events_queue_size_write (struct counter_device *counter, +u64 val) +{ +return counter_chrdev_realloc_queue (counter, val); +} +static struct counter_comp counter_num_signals_comp =COUNTER_COMP_DEVICE_U8 ("num_signals" , counter_num_signals_read,NULL );static struct counter_comp counter_num_counts_comp =COUNTER_COMP_DEVICE_U8 ("num_counts" , counter_num_counts_read,NULL ); +static struct counter_comp counter_events_queue_size_comp = +COUNTER_COMP_DEVICE_U64 ("events_queue_size" , + counter_events_queue_size_read, + counter_events_queue_size_write); +static int counter_sysfs_attr_add (struct counter_device *const counter,struct counter_attribute_group *group) {@@ -781,6 +800,12 @@ static int counter_sysfs_attr_add(struct counter_device *const counter,if (err <0 )return err;
Quoted 10 lines
drivers/counter/counter-sysfs.c static int counter_sysfs_attr_add(struct counter_device *const counter, · line 811
Quoted 9 lines
drivers/counter/counter-sysfs.c +6
-0+/* Create num_counts attribute */ + err =counter_attr_create (dev, group, &counter_events_queue_size_comp, + scope,NULL ); +if (err <0 ) +return err; +/* Create an attribute for each extension */ for (i =0 ; i < counter->num_ext; i++) { ext = counter->ext + i;
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Jonathan Cameron
maintainerRe: [PATCH v8 20/22] counter: Implement events_queue_size sysfs attribute
Quoted 69 lines · On Thu, 18 Feb 2021 19:32:16 +0900 William Breathitt Gray…
Quoted 46 lines · Jonathan Cameron
Quoted 43 lines · On Fri, 12 Feb 2021 21:13:44 +0900 William Breathitt Gray…
The
events_queue_sizesysfs 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 structcounter_eventdata structures. The number of elements will be rounded-up to a power of 2 due to a requirement of thekfifo_allocfunction called during reallocation of the queue.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 8 +++++++ drivers/counter/counter-chrdev.c | 23 +++++++++++++++++++ drivers/counter/counter-chrdev.h | 2 ++ drivers/counter/counter-sysfs.c | 25 +++++++++++++++++++++ 4 files changed, 58 insertions(+)Documentation/ABI/testing/sysfs-bus-counter +8
-0@@ -212,6 +212,14 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.13 +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 +0
-0@@ -375,6 +375,29 @@ void counter_chrdev_remove(struct counter_device *const counter)cdev_del (&counter->chrdev); }Quoted 11 lines
drivers/counter/counter-chrdev.c void counter_chrdev_remove(struct counter_device *const counter) · line 386
Quoted 9 lines
drivers/counter/counter-chrdev.c +9
-0+int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size) +{ +int err; + DECLARE_KFIFO_PTR(events, struct counter_event); +unsigned long flags; + +/* Allocate new events queue */ + err =kfifo_alloc (&events, queue_size,GFP_ATOMIC );Is there any potential for losing events?
We take the
events_list_lockdown below so we're safe against missing an event, but past events currently unread in the queue will be lost.Shortening the size of the queue is inherently a destructive process if we have more events in the current queue than can fit in the new queue. Because we a liable to lose some events in such a case, I think it's best to keep the behavior of this reallocation consistent and have it provide a fresh empty queue every time, as opposed to sometimes dropping events and sometimes not.
Quoted 4 lines
I also suspect an actual user would be setting the size of their queue to the required amount before they begin watching events, rather than adjusting it sporadically during a live operation.
Absolutely agree. As such I wonder if you are better off enforcing this
behaviour? If the cdev is open for reading, don't allow the fifo to be resized.
Jonathan
Re: [PATCH v8 20/22] counter: Implement events_queue_size sysfs attribute
Quoted 77 lines · Jonathan Cameron
Quoted 69 lines · On Thu, 18 Feb 2021 19:32:16 +0900 William Breathitt Gray…
Quoted 46 lines · Jonathan Cameron
Quoted 43 lines · On Fri, 12 Feb 2021 21:13:44 +0900 William Breathitt Gray…
The
events_queue_sizesysfs 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 structcounter_eventdata structures. The number of elements will be rounded-up to a power of 2 due to a requirement of thekfifo_allocfunction called during reallocation of the queue.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 8 +++++++ drivers/counter/counter-chrdev.c | 23 +++++++++++++++++++ drivers/counter/counter-chrdev.h | 2 ++ drivers/counter/counter-sysfs.c | 25 +++++++++++++++++++++ 4 files changed, 58 insertions(+)Documentation/ABI/testing/sysfs-bus-counter +8
-0@@ -212,6 +212,14 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.13 +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 +0
-0@@ -375,6 +375,29 @@ void counter_chrdev_remove(struct counter_device *const counter)cdev_del (&counter->chrdev); }Quoted 11 lines
drivers/counter/counter-chrdev.c void counter_chrdev_remove(struct counter_device *const counter) · line 386
Quoted 9 lines
drivers/counter/counter-chrdev.c +9
-0+int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size) +{ +int err; + DECLARE_KFIFO_PTR(events, struct counter_event); +unsigned long flags; + +/* Allocate new events queue */ + err =kfifo_alloc (&events, queue_size,GFP_ATOMIC );Is there any potential for losing events?
We take the
events_list_lockdown below so we're safe against missing an event, but past events currently unread in the queue will be lost.Shortening the size of the queue is inherently a destructive process if we have more events in the current queue than can fit in the new queue. Because we a liable to lose some events in such a case, I think it's best to keep the behavior of this reallocation consistent and have it provide a fresh empty queue every time, as opposed to sometimes dropping events and sometimes not.
Quoted 4 lines
I also suspect an actual user would be setting the size of their queue to the required amount before they begin watching events, rather than adjusting it sporadically during a live operation.
Quoted 5 lines
Absolutely agree. As such I wonder if you are better off enforcing this
behaviour? If the cdev is open for reading, don't allow the fifo to be resized.Jonathan
I can't really think of a good reason not to, so let's enforce it: if the cdev is open, then we'll return an EINVAL if the user attempts to resize the queue.
What is a good way to check for this condition? Should I just call kref_read() and see if it's greater than 1? For example, in counter_chrdev_realloc_queue():
if (kref_read(&counter->dev.kobj.kref) > 1) return -EINVAL;
William Breathitt Gray
David Lechner
reviewerRe: [PATCH v8 20/22] counter: Implement events_queue_size sysfs attribute
Quoted 88 lines · William Breathitt Gray
Quoted 77 lines · Jonathan Cameron
Quoted 69 lines · On Thu, 18 Feb 2021 19:32:16 +0900 William Breathitt Gray…
Quoted 46 lines · Jonathan Cameron
Quoted 43 lines · On Fri, 12 Feb 2021 21:13:44 +0900 William Breathitt Gray…
The
events_queue_sizesysfs 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 structcounter_eventdata structures. The number of elements will be rounded-up to a power of 2 due to a requirement of thekfifo_allocfunction called during reallocation of the queue.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 8 +++++++ drivers/counter/counter-chrdev.c | 23 +++++++++++++++++++ drivers/counter/counter-chrdev.h | 2 ++ drivers/counter/counter-sysfs.c | 25 +++++++++++++++++++++ 4 files changed, 58 insertions(+)Documentation/ABI/testing/sysfs-bus-counter +8
-0@@ -212,6 +212,14 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.13 +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 +0
-0@@ -375,6 +375,29 @@ void counter_chrdev_remove(struct counter_device *const counter)cdev_del (&counter->chrdev); }Quoted 11 lines
drivers/counter/counter-chrdev.c void counter_chrdev_remove(struct counter_device *const counter) · line 386
Quoted 9 lines
drivers/counter/counter-chrdev.c +9
-0+int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size) +{ +int err; + DECLARE_KFIFO_PTR(events, struct counter_event); +unsigned long flags; + +/* Allocate new events queue */ + err =kfifo_alloc (&events, queue_size,GFP_ATOMIC );Is there any potential for losing events?
We take the
events_list_lockdown below so we're safe against missing an event, but past events currently unread in the queue will be lost.Shortening the size of the queue is inherently a destructive process if we have more events in the current queue than can fit in the new queue. Because we a liable to lose some events in such a case, I think it's best to keep the behavior of this reallocation consistent and have it provide a fresh empty queue every time, as opposed to sometimes dropping events and sometimes not.
Quoted 4 lines
I also suspect an actual user would be setting the size of their queue to the required amount before they begin watching events, rather than adjusting it sporadically during a live operation.
Quoted 5 lines
Absolutely agree. As such I wonder if you are better off enforcing this
behaviour? If the cdev is open for reading, don't allow the fifo to be resized.Jonathan
I can't really think of a good reason not to, so let's enforce it: if the cdev is open, then we'll return an EINVAL if the user attempts to resize the queue.
Quoted 9 lines
What is a good way to check for this condition? Should I just call
kref_read()and see if it's greater than 1? For example, incounter_chrdev_realloc_queue():if (kref_read(&counter->dev.kobj.kref) > 1) return -EINVAL;William Breathitt Gray
Wouldn't EBUSY make more sense?
Re: [PATCH v8 20/22] counter: Implement events_queue_size sysfs attribute
Quoted 93 lines · David Lechner
Quoted 92 lines · William Breathitt Gray
Quoted 77 lines · Jonathan Cameron
Quoted 69 lines · On Thu, 18 Feb 2021 19:32:16 +0900 William Breathitt Gray…
Quoted 46 lines · Jonathan Cameron
Quoted 43 lines · On Fri, 12 Feb 2021 21:13:44 +0900 William Breathitt Gray…
The
events_queue_sizesysfs 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 structcounter_eventdata structures. The number of elements will be rounded-up to a power of 2 due to a requirement of thekfifo_allocfunction called during reallocation of the queue.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 8 +++++++ drivers/counter/counter-chrdev.c | 23 +++++++++++++++++++ drivers/counter/counter-chrdev.h | 2 ++ drivers/counter/counter-sysfs.c | 25 +++++++++++++++++++++ 4 files changed, 58 insertions(+)Documentation/ABI/testing/sysfs-bus-counter +8
-0@@ -212,6 +212,14 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.13 +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 +0
-0@@ -375,6 +375,29 @@ void counter_chrdev_remove(struct counter_device *const counter)cdev_del (&counter->chrdev); }Quoted 11 lines
drivers/counter/counter-chrdev.c void counter_chrdev_remove(struct counter_device *const counter) · line 386
Quoted 9 lines
drivers/counter/counter-chrdev.c +9
-0+int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size) +{ +int err; + DECLARE_KFIFO_PTR(events, struct counter_event); +unsigned long flags; + +/* Allocate new events queue */ + err =kfifo_alloc (&events, queue_size,GFP_ATOMIC );Is there any potential for losing events?
We take the
events_list_lockdown below so we're safe against missing an event, but past events currently unread in the queue will be lost.Shortening the size of the queue is inherently a destructive process if we have more events in the current queue than can fit in the new queue. Because we a liable to lose some events in such a case, I think it's best to keep the behavior of this reallocation consistent and have it provide a fresh empty queue every time, as opposed to sometimes dropping events and sometimes not.
Quoted 4 lines
I also suspect an actual user would be setting the size of their queue to the required amount before they begin watching events, rather than adjusting it sporadically during a live operation.
Quoted 5 lines
Absolutely agree. As such I wonder if you are better off enforcing this
behaviour? If the cdev is open for reading, don't allow the fifo to be resized.Jonathan
I can't really think of a good reason not to, so let's enforce it: if the cdev is open, then we'll return an EINVAL if the user attempts to resize the queue.
What is a good way to check for this condition? Should I just call
kref_read()and see if it's greater than 1? For example, incounter_chrdev_realloc_queue():
Quoted 7 lines
Quoted 5 lines
if (kref_read(&counter->dev.kobj.kref) > 1) return -EINVAL;William Breathitt Gray
Wouldn't EBUSY make more sense?
Yes, EBUSY would be better here because the operation isn't necessarily invalid, just unavailable because someone else has the cdev open.
William Breathitt Gray
Jonathan Cameron
maintainerRe: [PATCH v8 20/22] counter: Implement events_queue_size sysfs attribute
In reply to William Breathitt GrayQuoted 88 lines · On Fri, 26 Feb 2021 09:03:48 +0900 William Breathitt Gray…
Quoted 77 lines · Jonathan Cameron
Quoted 69 lines · On Thu, 18 Feb 2021 19:32:16 +0900 William Breathitt Gray…
Quoted 46 lines · Jonathan Cameron
Quoted 43 lines · On Fri, 12 Feb 2021 21:13:44 +0900 William Breathitt Gray…
The
events_queue_sizesysfs 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 structcounter_eventdata structures. The number of elements will be rounded-up to a power of 2 due to a requirement of thekfifo_allocfunction called during reallocation of the queue.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 8 +++++++ drivers/counter/counter-chrdev.c | 23 +++++++++++++++++++ drivers/counter/counter-chrdev.h | 2 ++ drivers/counter/counter-sysfs.c | 25 +++++++++++++++++++++ 4 files changed, 58 insertions(+)Documentation/ABI/testing/sysfs-bus-counter +8
-0@@ -212,6 +212,14 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.13 +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 +0
-0@@ -375,6 +375,29 @@ void counter_chrdev_remove(struct counter_device *const counter)cdev_del (&counter->chrdev); }Quoted 11 lines
drivers/counter/counter-chrdev.c void counter_chrdev_remove(struct counter_device *const counter) · line 386
Quoted 9 lines
drivers/counter/counter-chrdev.c +9
-0+int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size) +{ +int err; + DECLARE_KFIFO_PTR(events, struct counter_event); +unsigned long flags; + +/* Allocate new events queue */ + err =kfifo_alloc (&events, queue_size,GFP_ATOMIC );Is there any potential for losing events?
We take the
events_list_lockdown below so we're safe against missing an event, but past events currently unread in the queue will be lost.Shortening the size of the queue is inherently a destructive process if we have more events in the current queue than can fit in the new queue. Because we a liable to lose some events in such a case, I think it's best to keep the behavior of this reallocation consistent and have it provide a fresh empty queue every time, as opposed to sometimes dropping events and sometimes not.
Quoted 4 lines
I also suspect an actual user would be setting the size of their queue to the required amount before they begin watching events, rather than adjusting it sporadically during a live operation.
Quoted 5 lines
Absolutely agree. As such I wonder if you are better off enforcing this
behaviour? If the cdev is open for reading, don't allow the fifo to be resized.Jonathan
I can't really think of a good reason not to, so let's enforce it: if the cdev is open, then we'll return an EINVAL if the user attempts to resize the queue.
Quoted 6 lines
What is a good way to check for this condition? Should I just call
kref_read()and see if it's greater than 1? For example, incounter_chrdev_realloc_queue():if (kref_read(&counter->dev.kobj.kref) > 1) return -EINVAL;
In theory at least you might want the kobj.kref to be incremented
for other reasons than just open. So to keep different concepts
separate, perhaps it's worth a separate variable somewhere to track whether the file is open currently.
However, it's reasonable (I think) to assume the kref will have a minimum value if open, so perhaps what you suggest works fine.
Jonathan
Quoted 2 lines
William Breathitt Gray
Re: [PATCH v8 20/22] counter: Implement events_queue_size sysfs attribute
Quoted 102 lines · Jonathan Cameron
Quoted 88 lines · On Fri, 26 Feb 2021 09:03:48 +0900 William Breathitt Gray…
Quoted 77 lines · Jonathan Cameron
Quoted 69 lines · On Thu, 18 Feb 2021 19:32:16 +0900 William Breathitt Gray…
Quoted 46 lines · Jonathan Cameron
Quoted 43 lines · On Fri, 12 Feb 2021 21:13:44 +0900 William Breathitt Gray…
The
events_queue_sizesysfs 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 structcounter_eventdata structures. The number of elements will be rounded-up to a power of 2 due to a requirement of thekfifo_allocfunction called during reallocation of the queue.Cc Oleksij Rempel <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>--- Documentation/ABI/testing/sysfs-bus-counter | 8 +++++++ drivers/counter/counter-chrdev.c | 23 +++++++++++++++++++ drivers/counter/counter-chrdev.h | 2 ++ drivers/counter/counter-sysfs.c | 25 +++++++++++++++++++++ 4 files changed, 58 insertions(+)Documentation/ABI/testing/sysfs-bus-counter +8
-0@@ -212,6 +212,14 @@ Description: both edges: Any state transition. +What: /sys/bus/counter/devices/counterX/events_queue_size +KernelVersion: 5.13 +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 +0
-0@@ -375,6 +375,29 @@ void counter_chrdev_remove(struct counter_device *const counter)cdev_del (&counter->chrdev); }Quoted 11 lines
drivers/counter/counter-chrdev.c void counter_chrdev_remove(struct counter_device *const counter) · line 386
Quoted 9 lines
drivers/counter/counter-chrdev.c +9
-0+int counter_chrdev_realloc_queue (struct counter_device *const counter, +size_t queue_size) +{ +int err; + DECLARE_KFIFO_PTR(events, struct counter_event); +unsigned long flags; + +/* Allocate new events queue */ + err =kfifo_alloc (&events, queue_size,GFP_ATOMIC );Is there any potential for losing events?
We take the
events_list_lockdown below so we're safe against missing an event, but past events currently unread in the queue will be lost.Shortening the size of the queue is inherently a destructive process if we have more events in the current queue than can fit in the new queue. Because we a liable to lose some events in such a case, I think it's best to keep the behavior of this reallocation consistent and have it provide a fresh empty queue every time, as opposed to sometimes dropping events and sometimes not.
Quoted 4 lines
I also suspect an actual user would be setting the size of their queue to the required amount before they begin watching events, rather than adjusting it sporadically during a live operation.
Quoted 5 lines
Absolutely agree. As such I wonder if you are better off enforcing this
behaviour? If the cdev is open for reading, don't allow the fifo to be resized.Jonathan
I can't really think of a good reason not to, so let's enforce it: if the cdev is open, then we'll return an EINVAL if the user attempts to resize the queue.
Quoted 6 lines
What is a good way to check for this condition? Should I just call
kref_read()and see if it's greater than 1? For example, incounter_chrdev_realloc_queue():if (kref_read(&counter->dev.kobj.kref) > 1) return -EINVAL;In theory at least you might want the kobj.kref to be incremented
for other reasons than just open. So to keep different concepts
separate, perhaps it's worth a separate variable somewhere to track whether the file is open currently.
Quoted 4 lines
However, it's reasonable (I think) to assume the kref will have a minimum value if open, so perhaps what you suggest works fine.
Jonathan
I noticed an open() operation could occur right after this check, so we'll need a mutex here to ensure the the queue size is not modified during use. Because of that, I'll create a separate variable to track this and use a mutex_trylock() instead of the kref to test whether to return -EBUSY.
William Breathitt Gray
PATCH v8 21/22 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: synchronization lock to prevent I/O race conditions * @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; +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -407,9 +413,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); idr_cfg |= priv->synchronous_mode[channel_id];
@@ -418,7 +425,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -447,15 +454,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); +raw_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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return -EINVAL ; }
@@ -464,7 +472,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -511,6 +519,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) {
@@ -531,7 +540,7 @@ static int quad8_count_mode_write(struct counter_device *counter,return -EINVAL ; } -mutex_lock (&priv->lock); +raw_spin_lock_irqsave (&priv->lock, irqflags); priv->count_mode[count->id] = count_mode;
@@ -545,7 +554,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -565,9 +574,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); priv->ab_enable[count->id] = enable;
@@ -576,7 +586,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -627,16 +637,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); +raw_spin_lock_irqsave (&priv->lock, irqflags);quad8_preset_register_set (priv, count->id, preset); -mutex_unlock (&priv->lock); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -645,8 +656,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); +raw_spin_lock_irqsave (&priv->lock, irqflags);/* Range Limit and Modulo-N count modes use preset value as ceiling */ switch (priv->count_mode[count->id]) {
@@ -660,7 +672,7 @@ static int quad8_count_ceiling_read(struct counter_device *counter,break ; } -mutex_unlock (&priv->lock); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -669,23 +681,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); +raw_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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);quad8_preset_register_set (priv, count->id, ceiling);return 0 ; } -mutex_unlock (&priv->lock); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return -EINVAL ; }
@@ -707,12 +720,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); priv->preset_enable[count->id] = preset_enable;
@@ -721,7 +735,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -732,22 +746,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); disabled = !(priv->cable_fault_enable &BIT (channel_id));if (disabled) { -mutex_unlock (&priv->lock); +raw_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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);/* Mask respective channel and invert logic */ *cable_fault = !(status &BIT (channel_id));
@@ -773,9 +788,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); +raw_spin_lock_irqsave (&priv->lock, irqflags);if (enable) priv->cable_fault_enable |=BIT (channel_id);
@@ -787,7 +803,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -810,8 +826,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); priv->fck_prescaler[channel_id] = prescaler;
@@ -823,7 +840,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }
@@ -992,8 +1009,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); +raw_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.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 21/22] counter: 104-quad-8: Replace mutex with spinlock
Quoted 7 lines · On Fri, 12 Feb 2021 21:13:45 +0900 William Breathitt Gray…
This patch replaces the mutex I/O lock with a spinlock. This is in preparation for a subsequent patch adding IRQ support for 104-QUAD-8 devices; we can't sleep in an interrupt context, so we'll need to use a spinlock instead.
Cc Syed Nayyar Waris <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
Why do these need to be raw_spin_locks?
Normally only need to do that if in code related to interrupt chips etc, not their use.
Jonathan
Quoted 401 lines
--- 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: synchronization lock to prevent I/O race conditions * @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; +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -407,9 +413,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); idr_cfg |= priv->synchronous_mode[channel_id];@@ -418,7 +425,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -447,15 +454,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); +raw_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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return -EINVAL ; }@@ -464,7 +472,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -511,6 +519,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) {@@ -531,7 +540,7 @@ static int quad8_count_mode_write(struct counter_device *counter,return -EINVAL ; } -mutex_lock (&priv->lock); +raw_spin_lock_irqsave (&priv->lock, irqflags); priv->count_mode[count->id] = count_mode;@@ -545,7 +554,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -565,9 +574,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); priv->ab_enable[count->id] = enable;@@ -576,7 +586,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -627,16 +637,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); +raw_spin_lock_irqsave (&priv->lock, irqflags);quad8_preset_register_set (priv, count->id, preset); -mutex_unlock (&priv->lock); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -645,8 +656,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); +raw_spin_lock_irqsave (&priv->lock, irqflags);/* Range Limit and Modulo-N count modes use preset value as ceiling */ switch (priv->count_mode[count->id]) {@@ -660,7 +672,7 @@ static int quad8_count_ceiling_read(struct counter_device *counter,break ; } -mutex_unlock (&priv->lock); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -669,23 +681,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); +raw_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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);quad8_preset_register_set (priv, count->id, ceiling);return 0 ; } -mutex_unlock (&priv->lock); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return -EINVAL ; }@@ -707,12 +720,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); priv->preset_enable[count->id] = preset_enable;@@ -721,7 +735,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -732,22 +746,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); disabled = !(priv->cable_fault_enable &BIT (channel_id));if (disabled) { -mutex_unlock (&priv->lock); +raw_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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);/* Mask respective channel and invert logic */ *cable_fault = !(status &BIT (channel_id));@@ -773,9 +788,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); +raw_spin_lock_irqsave (&priv->lock, irqflags);if (enable) priv->cable_fault_enable |=BIT (channel_id);@@ -787,7 +803,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -810,8 +826,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); +raw_spin_lock_irqsave (&priv->lock, irqflags); priv->fck_prescaler[channel_id] = prescaler;@@ -823,7 +840,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); +raw_spin_unlock_irqrestore (&priv->lock, irqflags);return 0 ; }@@ -992,8 +1009,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); +raw_spin_lock_init (&priv->lock);/* Reset all counters and disable interrupt function */ outb (QUAD8_CHAN_OP_RESET_COUNTERS , base[id] +QUAD8_REG_CHAN_OP );
Re: [PATCH v8 21/22] counter: 104-quad-8: Replace mutex with spinlock
Quoted 8 lines · Jonathan Cameron
Quoted 5 lines · On Fri, 12 Feb 2021 21:13:45 +0900 William Breathitt Gray…
This patch replaces the mutex I/O lock with a spinlock. This is in preparation for a subsequent patch adding IRQ support for 104-QUAD-8 devices; we can't sleep in an interrupt context, so we'll need to use a spinlock instead.
Quoted 8 lines
Quoted 2 lines
Cc Syed Nayyar Waris <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>Why do these need to be
raw_spin_locks?
Normally only need to do that if in code related to interrupt chips etc, not their use.Jonathan
This lock can be taken in an interrupt context in a subsequent patch:counter_push_event() called by quad8_irq_handler() can end up calling the Counter component callbacks which take this lock. We can't use a mutex nor a regular spinlock because those can sleep on RT setups [1] which would result in a deadlock due to the interrupt context here -- so therefore we're left with using raw_spin_lock.
[1] https://lwn.net/Articles/367219/
William Breathitt Gray
Jonathan Cameron
maintainerRe: [PATCH v8 21/22] counter: 104-quad-8: Replace mutex with spinlock
Quoted 16 lines · On Tue, 16 Feb 2021 11:16:03 +0900 William Breathitt Gray…
Quoted 15 lines · Jonathan Cameron
Quoted 7 lines · On Fri, 12 Feb 2021 21:13:45 +0900 William Breathitt Gray…
This patch replaces the mutex I/O lock with a spinlock. This is in preparation for a subsequent patch adding IRQ support for 104-QUAD-8 devices; we can't sleep in an interrupt context, so we'll need to use a spinlock instead.
Cc Syed Nayyar Waris <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>Why do these need to be
raw_spin_locks?
Normally only need to do that if in code related to interrupt chips etc, not their use.
Quoted 6 lines
Quoted 1 line
Jonathan
This lock can be taken in an interrupt context in a subsequent patch:
counter_push_event()called byquad8_irq_handler()can end up calling the Counter component callbacks which take this lock. We can't use a mutex nor a regular spinlock because those can sleep on RT setups [1]
But on RT setups the interrupts become threads and are preemptable etc, so that shouldn't matter. There are a few corner cases that cause trouble, but in most normal drivers you should be fine with a spin_lock.
Jonathan
Quoted 6 lines
which would result in a deadlock due to the interrupt context here -- so therefore we're left with using
raw_spin_lock.[1] https://lwn.net/Articles/367219/
William Breathitt Gray
Re: [PATCH v8 21/22] counter: 104-quad-8: Replace mutex with spinlock
Quoted 26 lines · Jonathan Cameron
Quoted 16 lines · On Tue, 16 Feb 2021 11:16:03 +0900 William Breathitt Gray…
Quoted 15 lines · Jonathan Cameron
Quoted 7 lines · On Fri, 12 Feb 2021 21:13:45 +0900 William Breathitt Gray…
This patch replaces the mutex I/O lock with a spinlock. This is in preparation for a subsequent patch adding IRQ support for 104-QUAD-8 devices; we can't sleep in an interrupt context, so we'll need to use a spinlock instead.
Cc Syed Nayyar Waris <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>Why do these need to be
raw_spin_locks?
Normally only need to do that if in code related to interrupt chips etc, not their use.Quoted 6 lines
Quoted 1 line
Jonathan
This lock can be taken in an interrupt context in a subsequent patch:
counter_push_event()called byquad8_irq_handler()can end up calling the Counter component callbacks which take this lock. We can't use a mutex nor a regular spinlock because those can sleep on RT setups [1]
Quoted 6 lines
But on RT setups the interrupts become threads and are preemptable etc, so that shouldn't matter. There are a few corner cases that cause trouble, but in most normal drivers you should be fine with a
spin_lock.Jonathan
Thinking this over again I realize you're probably right. A simple spin_lock should be fine for these drivers, so I'll switch over to that instead of the raw_spin_lock for this driver and the Counter interface code.
William Breathitt Gray
Quoted 7 lines
Quoted 6 lines
which would result in a deadlock due to the interrupt context here -- so therefore we're left with using
raw_spin_lock.[1] https://lwn.net/Articles/367219/
William Breathitt Gray
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH v8 22/22 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 | 170 +++++++++++++++++++++++++++++++++-- drivers/counter/Kconfig | 6 +- 2 files changed, 165 insertions(+), 11 deletions(-)
drivers/counter/104-quad-8.c +162 -8
@@ -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,11 +26,15 @@ 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/** * struct quad8 - device private data structure -* @lock: synchronization lock to prevent I/O race conditions +* @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
@@ -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
@@ -380,13 +391,103 @@ static int quad8_action_read(struct counter_device *counter,return 0 ; } +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; + +raw_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 ); + +raw_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[] = {
@@ -581,7 +682,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 );
@@ -730,7 +832,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);
@@ -982,11 +1085,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",
@@ -1011,6 +1157,8 @@ static int quad8_probe(struct device *dev, unsigned int id)raw_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 */
@@ -1037,13 +1185,19 @@ 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; -/* Register Counter device */ 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 STM32_TIMER_CNT tristate "STM32 Timer encoder counter driver"
Signature · 1 line
2.30.0
Jonathan Cameron
maintainerRe: [PATCH v8 22/22] counter: 104-quad-8: Add IRQ support for the ACCES 104-QUAD-8
Quoted 32 lines · On Fri, 12 Feb 2021 21:13:46 +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.
Cc Syed Nayyar Waris <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>
A few minor bits inline.
Jonathan
Quoted 62 lines
--- drivers/counter/104-quad-8.c | 170 +++++++++++++++++++++++++++++++++-- drivers/counter/Kconfig | 6 +- 2 files changed, 165 insertions(+), 11 deletions(-)drivers/counter/104-quad-8.c +12
-1@@ -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,11 +26,15 @@ 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/** * struct quad8 - device private data structure -* @lock: synchronization lock to prevent I/O race conditions +* @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 @@ -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 */
drivers/counter/104-quad-8.c struct quad8 { · line 95
Quoted 4 lines
drivers/counter/104-quad-8.c +0
-1@@ -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
This seems like an unrelated change...
Quoted 8 lines
drivers/counter/104-quad-8.c +1
-0#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@@ -380,13 +391,103 @@ static int quad8_action_read(struct counter_device *counter,return 0 ; }
...
Quoted 28 lines
static int
quad8_probe(struct device *dev, unsigned int id){drivers/counter/104-quad-8.c +5
-1struct 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",@@ -1011,6 +1157,8 @@ static int quad8_probe(struct device *dev, unsigned int id)raw_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 */ @@ -1037,13 +1185,19 @@ 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 */
drivers/counter/104-quad-8.c static int quad8_probe(struct device *dev, unsigned int id) · line 1046
Quoted 10 lines
drivers/counter/104-quad-8.c +7
-2-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; -/* Register Counter device */
Whilst I would agree with removing this comment as being pointless as it's obvious, it doesn't really belong in this patch.
Quoted 22 lines
drivers/counter/104-quad-8.c +0
-0return 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 STM32_TIMER_CNT tristate "STM32 Timer encoder counter driver"
Re: [PATCH v8 22/22] counter: 104-quad-8: Add IRQ support for the ACCES 104-QUAD-8
Quoted 101 lines · Jonathan Cameron
Quoted 32 lines · On Fri, 12 Feb 2021 21:13:46 +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.
Cc Syed Nayyar Waris <[email protected]>Signed-off-by William Breathitt Gray <[email protected]>A few minor bits inline.
Jonathan
Quoted 55 lines
--- drivers/counter/104-quad-8.c | 170 +++++++++++++++++++++++++++++++++-- drivers/counter/Kconfig | 6 +- 2 files changed, 165 insertions(+), 11 deletions(-)drivers/counter/104-quad-8.c +10
-1@@ -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,11 +26,15 @@ 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/** * struct quad8 - device private data structure -* @lock: synchronization lock to prevent I/O race conditions +* @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 @@ -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; };
Quoted 13 lines
drivers/counter/104-quad-8.c struct quad8 { · line 95
Quoted 11 lines
drivers/counter/104-quad-8.c +2
-1+#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 0x00This seems like an unrelated change...
This register has a bit to enable the interrupt functions in addition to the counters. When I first introduced these macro defines, I ignored mentioning the interrupt functionality because we weren't supporting IRQ at the time. The change in this patch here is actually a rename of this register configuration with the new respective bit now properly enabled:QUAD8_CHAN_OP_ENABLE_COUNTERS -> QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC.
Quoted 48 lines
Quoted 8 lines
drivers/counter/104-quad-8.c +1
-0#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@@ -380,13 +391,103 @@ static int quad8_action_read(struct counter_device *counter,return 0 ; }...
Quoted 37 lines
static int
quad8_probe(struct device *dev, unsigned int id){drivers/counter/104-quad-8.c +12
-2struct 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",@@ -1011,6 +1157,8 @@ static int quad8_probe(struct device *dev, unsigned int id)raw_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 */ @@ -1037,13 +1185,19 @@ 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;
Quoted 4 lines
drivers/counter/104-quad-8.c static int quad8_probe(struct device *dev, unsigned int id) · line 1046
Quoted 1 line
drivers/counter/104-quad-8.c +0
-1-/* Register Counter device */ Whilst I would agree with removing this comment as being pointless as it's obvious, it doesn't really belong in this patch.
I'll move this to its own patch.
William Breathitt Gray
Quoted 23 lines
Quoted 22 lines
drivers/counter/104-quad-8.c +0
-0return 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 STM32_TIMER_CNT tristate "STM32 Timer encoder counter driver"