All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/16] Introduce SCMI test driver and related Kselftest
@ 2022-02-27 20:55 ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Hi all,

this RFC series is meant to introduce and gather some initial feedback on
a new possible SCMI test infrastructure.

The aim is to be able to test the core SCMI Kernel stack in isolation
exercising directly the SCMI protocol interface defined in scmi_protocol.h
without relying on the normal SCMI driver users already present in the
Kernel (like clk-scmi or cpufreq-scmi).

The reason for this approach is twofold, on one side the SCMI protocol
operations interface in scmi_protocol.h is not necessarily used to its full
exent by the existenting SCMI drivers users, on the other side we don't
want to be constrained in our testing by possible internal constraints
imposed by such subsystems on a production system (for good resasons) or by
the usage patterns enforced by their related API.
As an example the CLK subsystem enforces refcounts on enable/disable ops
and the limited debugfs that is made available for testing does not cover
all the possible SCMI operations and it is hardly configurable at compile
time since such flexibility in setting clk rates is deemed dangerous on a
production system. (for good reasons in fact)

In order to do so, a new SCMI test driver is introduced which is in all
regards a regular SCMI driver (like cpufreq-scmi or clk-scmi) that, first
of all, at probe time, registers as a user for each and every SCMI protocol
(if supported by the underlying SCMI platform server and by this testing
driver) and then takes care to expose on a dedicated SCMI debugfs each
and every SCMI protocol operation and some informational data.

The only fundamental differences with a regular SCMI production driver
(like clk-scmi or cpufreq-scmi) are that it:

 - registers itself for ALL the available and supported SCMI protocols
   (not just one)
 - excludes from the SCMI stack any other production SCMI driver
   (unless cohexistence is allowed by an explicit Kconfig in patch 16/16)

The idea is, on one side, to avoid any possible interference during testing
from concurrently running production drivers possibly accessing the same
SCMI protocol stack and, on the other side, avoid the possibility of
deploying by mistake a system in production which exposes also all the
SCMI interface in debugfs via the SCMI testing driver.

Once the SCMI protocols interface is exposed in debugfs as such we can
happily script our testcases in terms of kselftest as esemplified in patch
15/16. (only reported here as an example ... the KSelftests are RFC^2 and
to be fully re-written)

The resulting SCMI debugfs is roughly structured as detailed down below.

At the top layer, there are two main informational directories (info/ and
transport/ holding some general data related to SCMI stack versioning and
current transport configuration and then there is one directory for each
SCMI protocol that has been found available on the system (as advertised
by the backend SCMI server) and that this driver currently supports.

/sys/kernel/debug/scmi/
├── info
├── protocol_0x14
├── protocol_0x15
└── transport

Looking inside the protocol directory we found:

/sys/kernel/debug/scmi/protocol_0x14/
├── 000
│   ├── enable
│   ├── enable_atomic_irqs_off
│   ├── enable_atomic_irqs_on
│   ├── info
│   │   ├── enable_latency
│   │   ├── name
│   │   ├── num_rates
│   │   ├── rate_discrete
│   │   └── rates
│   └── rate_get_set
├── 001
│   ├── enable
│   ├── enable_atomic_irqs_off
│   ├── enable_atomic_irqs_on
│   ├── info
│   │   ├── enable_latency
│   │   ├── name
│   │   ├── num_rates
│   │   ├── rate_discrete
│   │   └── rates
│   └── rate_get_set
├── 002
│   ├── enable
│   ├── enable_atomic_irqs_off
│   ├── enable_atomic_irqs_on
│   ├── info
│   │   ├── enable_latency
│   │   ├── max_rate
│   │   ├── min_rate
│   │   ├── name
│   │   ├── rate_discrete
│   │   └── step_size
│   └── rate_get_set
└── version

- one toplevel 'version' entry to state SCMI Clock protocol version
  supported by the platform

- one subdirectory for each resource (clocks in this case) that has been
  found on the system and named by its ID: inside these resource subdir we
  found a resource specific info/ subdir describing the resource and the
  SCMI protocol operations available as exposed by the SCMI protocol.
  (mostly reflecting operations defined in scmi_protocol.h)

Note that, the operations exposed here could be some variations of the
basic SCMI operations (like the above enable/disable with IRQs on/off).

The KSelftest are basically structured in the same way, a bunch of tests
scripts organized by protocol directories mimicking this layout.

The fundamental issue with all of this is that, the above level of freedom
in testing the SCMI stack pose a serious risk of shooting ourselves in the
foot:

 - what if some clock test just kills the machine disablling something
   fundamental at runtime ?

 - what if instead our clock rate test is so good that spots an issue
   with the SCMI backend server (inadvertenly) and we fry the board ?

All of the above depends really on what SCMI backend we use for testing:
we should stick to more conservative tests on real HW, while we could
engage in more radical and invasive testcases at the presence of some more
virtualized backend where, ideally, nothing is real and everything is
mocked.

For this reasons the SCMI debugfs exposes some detailed information about
the running backend SCMI stack like 

/sys/kernel/debug/scmi/info/
├── impl_ver
├── major_ver
├── minor_ver
├── num_agents
├── num_protocols
├── sub_vendor_id
└── vendor_id

so that the examples tests in the Kselftest patch have been structured to
check for the running SCMI incarnation and eventually skip the most
invasive testcases (like clk rate set) if not in presence of a mocked
virtualized backend.

In other words this driver and the KSelftest try to stay agnostic and be
as general as possible so that can be used, with different extents, on a
number of different backend SCMI server implementations.

All the current SCMI debugfs entries are mre extensively documented in
Documentation/ABI/testing,

Remaining TODO:

- implement test driver support for all the other std protocols
- more tests (restructuring these armm64/scmi KSelftests)
- expose stats/timeouts/errors
- expose Base protocol ?
  (note that for its nature the SCMI Test driver loads only after the
   SCMI core stack has been loaded and the Base operations have been
   issued already to gather basic info from the platform)

This series is based on top of sudeep/for-next/scmi/updates [1]

commit 38a0e5b735d6 ("clk: scmi: Support atomic clock enable/disable API")

Thanks,
Cristian

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/log/?h=for-next/scmi/updates

Cristian Marussi (16):
  firmware: arm_scmi: Simplify scmi_devm_notifier_unregister
  firmware: arm_scmi: Make protocols init fail on basic errors
  firmware: arm_scmi: Add multiple protocols registration support
  firmware: arm_scmi: Add .version_get protocol operation
  firmware: arm_scmi: Expose information on configured transport
  firmware: arm_scmi: Define a common SCMI_MAX_PROTOCOLS value
  debugfs: Add signed versions of debugfs_create_u32/64 helpers
  firmware: arm_scmi: Add SCMI Testing driver
  firmware: arm_scmi: testing: Add Clock protocol full support
  firmware: arm_scmi: testing: Add Sensor protocol basic support
  firmware: arm_scmi: Add test driver generic notification helpers
  firmware: arm_scmi: Add Sensor notifications testing support
  firmware: arm_scmi: Add testing Power protocol support
  firmware: arm_scmi: Add testing Voltage protocol support
  selftests: arm64: Add initial SCMI testcases
  [DEBUG]: firmware: arm_scmi: Add Kconfig to allow SCMI Testing driver
    coexistence

 Documentation/ABI/testing/debugfs-scmi        | 269 ++++++++
 drivers/firmware/arm_scmi/Kconfig             |  18 +
 drivers/firmware/arm_scmi/Makefile            |   2 +
 drivers/firmware/arm_scmi/base.c              |   5 +-
 drivers/firmware/arm_scmi/bus.c               |   4 +-
 drivers/firmware/arm_scmi/clock.c             |   9 +-
 drivers/firmware/arm_scmi/common.h            |  24 +-
 drivers/firmware/arm_scmi/driver.c            |  46 +-
 drivers/firmware/arm_scmi/notify.c            |  34 +-
 drivers/firmware/arm_scmi/perf.c              |  11 +-
 drivers/firmware/arm_scmi/power.c             |  11 +-
 drivers/firmware/arm_scmi/reset.c             |  11 +-
 .../arm_scmi/scmi_test_driver/Makefile        |   5 +
 .../arm_scmi/scmi_test_driver/scmi_test.c     | 160 +++++
 .../arm_scmi/scmi_test_driver/test_clocks.c   | 287 ++++++++
 .../arm_scmi/scmi_test_driver/test_common.c   | 285 ++++++++
 .../arm_scmi/scmi_test_driver/test_common.h   | 108 +++
 .../arm_scmi/scmi_test_driver/test_powers.c   | 105 +++
 .../arm_scmi/scmi_test_driver/test_sensors.c  | 627 ++++++++++++++++++
 .../arm_scmi/scmi_test_driver/test_voltages.c |  51 ++
 drivers/firmware/arm_scmi/sensors.c           |   5 +-
 drivers/firmware/arm_scmi/system.c            |  11 +-
 drivers/firmware/arm_scmi/voltage.c           |   1 +
 fs/debugfs/file.c                             |  74 +++
 fs/libfs.c                                    |  12 +-
 include/linux/debugfs.h                       |   4 +
 include/linux/scmi_protocol.h                 |  47 +-
 tools/testing/selftests/arm64/Makefile        |   2 +-
 tools/testing/selftests/arm64/scmi/Makefile   |   6 +
 tools/testing/selftests/arm64/scmi/config     |   1 +
 .../arm64/scmi/kselftest_scmi_lib.sh          | 118 ++++
 .../selftests/arm64/scmi/run_scmi_tests.sh    |  69 ++
 .../testcases/protocol_0x14/clock_enable.sh   |  33 +
 .../protocol_0x14/clock_rate_read.sh          |  18 +
 .../protocol_0x14/clock_rate_write.sh         |  29 +
 .../testcases/protocol_0x15/sensor_reading.sh |  17 +
 36 files changed, 2463 insertions(+), 56 deletions(-)
 create mode 100644 Documentation/ABI/testing/debugfs-scmi
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/Makefile
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
 create mode 100644 tools/testing/selftests/arm64/scmi/Makefile
 create mode 100644 tools/testing/selftests/arm64/scmi/config
 create mode 100644 tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh

-- 
2.17.1


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFC PATCH 00/16] Introduce SCMI test driver and related Kselftest
@ 2022-02-27 20:55 ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Hi all,

this RFC series is meant to introduce and gather some initial feedback on
a new possible SCMI test infrastructure.

The aim is to be able to test the core SCMI Kernel stack in isolation
exercising directly the SCMI protocol interface defined in scmi_protocol.h
without relying on the normal SCMI driver users already present in the
Kernel (like clk-scmi or cpufreq-scmi).

The reason for this approach is twofold, on one side the SCMI protocol
operations interface in scmi_protocol.h is not necessarily used to its full
exent by the existenting SCMI drivers users, on the other side we don't
want to be constrained in our testing by possible internal constraints
imposed by such subsystems on a production system (for good resasons) or by
the usage patterns enforced by their related API.
As an example the CLK subsystem enforces refcounts on enable/disable ops
and the limited debugfs that is made available for testing does not cover
all the possible SCMI operations and it is hardly configurable at compile
time since such flexibility in setting clk rates is deemed dangerous on a
production system. (for good reasons in fact)

In order to do so, a new SCMI test driver is introduced which is in all
regards a regular SCMI driver (like cpufreq-scmi or clk-scmi) that, first
of all, at probe time, registers as a user for each and every SCMI protocol
(if supported by the underlying SCMI platform server and by this testing
driver) and then takes care to expose on a dedicated SCMI debugfs each
and every SCMI protocol operation and some informational data.

The only fundamental differences with a regular SCMI production driver
(like clk-scmi or cpufreq-scmi) are that it:

 - registers itself for ALL the available and supported SCMI protocols
   (not just one)
 - excludes from the SCMI stack any other production SCMI driver
   (unless cohexistence is allowed by an explicit Kconfig in patch 16/16)

The idea is, on one side, to avoid any possible interference during testing
from concurrently running production drivers possibly accessing the same
SCMI protocol stack and, on the other side, avoid the possibility of
deploying by mistake a system in production which exposes also all the
SCMI interface in debugfs via the SCMI testing driver.

Once the SCMI protocols interface is exposed in debugfs as such we can
happily script our testcases in terms of kselftest as esemplified in patch
15/16. (only reported here as an example ... the KSelftests are RFC^2 and
to be fully re-written)

The resulting SCMI debugfs is roughly structured as detailed down below.

At the top layer, there are two main informational directories (info/ and
transport/ holding some general data related to SCMI stack versioning and
current transport configuration and then there is one directory for each
SCMI protocol that has been found available on the system (as advertised
by the backend SCMI server) and that this driver currently supports.

/sys/kernel/debug/scmi/
├── info
├── protocol_0x14
├── protocol_0x15
└── transport

Looking inside the protocol directory we found:

/sys/kernel/debug/scmi/protocol_0x14/
├── 000
│   ├── enable
│   ├── enable_atomic_irqs_off
│   ├── enable_atomic_irqs_on
│   ├── info
│   │   ├── enable_latency
│   │   ├── name
│   │   ├── num_rates
│   │   ├── rate_discrete
│   │   └── rates
│   └── rate_get_set
├── 001
│   ├── enable
│   ├── enable_atomic_irqs_off
│   ├── enable_atomic_irqs_on
│   ├── info
│   │   ├── enable_latency
│   │   ├── name
│   │   ├── num_rates
│   │   ├── rate_discrete
│   │   └── rates
│   └── rate_get_set
├── 002
│   ├── enable
│   ├── enable_atomic_irqs_off
│   ├── enable_atomic_irqs_on
│   ├── info
│   │   ├── enable_latency
│   │   ├── max_rate
│   │   ├── min_rate
│   │   ├── name
│   │   ├── rate_discrete
│   │   └── step_size
│   └── rate_get_set
└── version

- one toplevel 'version' entry to state SCMI Clock protocol version
  supported by the platform

- one subdirectory for each resource (clocks in this case) that has been
  found on the system and named by its ID: inside these resource subdir we
  found a resource specific info/ subdir describing the resource and the
  SCMI protocol operations available as exposed by the SCMI protocol.
  (mostly reflecting operations defined in scmi_protocol.h)

Note that, the operations exposed here could be some variations of the
basic SCMI operations (like the above enable/disable with IRQs on/off).

The KSelftest are basically structured in the same way, a bunch of tests
scripts organized by protocol directories mimicking this layout.

The fundamental issue with all of this is that, the above level of freedom
in testing the SCMI stack pose a serious risk of shooting ourselves in the
foot:

 - what if some clock test just kills the machine disablling something
   fundamental at runtime ?

 - what if instead our clock rate test is so good that spots an issue
   with the SCMI backend server (inadvertenly) and we fry the board ?

All of the above depends really on what SCMI backend we use for testing:
we should stick to more conservative tests on real HW, while we could
engage in more radical and invasive testcases at the presence of some more
virtualized backend where, ideally, nothing is real and everything is
mocked.

For this reasons the SCMI debugfs exposes some detailed information about
the running backend SCMI stack like 

/sys/kernel/debug/scmi/info/
├── impl_ver
├── major_ver
├── minor_ver
├── num_agents
├── num_protocols
├── sub_vendor_id
└── vendor_id

so that the examples tests in the Kselftest patch have been structured to
check for the running SCMI incarnation and eventually skip the most
invasive testcases (like clk rate set) if not in presence of a mocked
virtualized backend.

In other words this driver and the KSelftest try to stay agnostic and be
as general as possible so that can be used, with different extents, on a
number of different backend SCMI server implementations.

All the current SCMI debugfs entries are mre extensively documented in
Documentation/ABI/testing,

Remaining TODO:

- implement test driver support for all the other std protocols
- more tests (restructuring these armm64/scmi KSelftests)
- expose stats/timeouts/errors
- expose Base protocol ?
  (note that for its nature the SCMI Test driver loads only after the
   SCMI core stack has been loaded and the Base operations have been
   issued already to gather basic info from the platform)

This series is based on top of sudeep/for-next/scmi/updates [1]

commit 38a0e5b735d6 ("clk: scmi: Support atomic clock enable/disable API")

Thanks,
Cristian

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/log/?h=for-next/scmi/updates

Cristian Marussi (16):
  firmware: arm_scmi: Simplify scmi_devm_notifier_unregister
  firmware: arm_scmi: Make protocols init fail on basic errors
  firmware: arm_scmi: Add multiple protocols registration support
  firmware: arm_scmi: Add .version_get protocol operation
  firmware: arm_scmi: Expose information on configured transport
  firmware: arm_scmi: Define a common SCMI_MAX_PROTOCOLS value
  debugfs: Add signed versions of debugfs_create_u32/64 helpers
  firmware: arm_scmi: Add SCMI Testing driver
  firmware: arm_scmi: testing: Add Clock protocol full support
  firmware: arm_scmi: testing: Add Sensor protocol basic support
  firmware: arm_scmi: Add test driver generic notification helpers
  firmware: arm_scmi: Add Sensor notifications testing support
  firmware: arm_scmi: Add testing Power protocol support
  firmware: arm_scmi: Add testing Voltage protocol support
  selftests: arm64: Add initial SCMI testcases
  [DEBUG]: firmware: arm_scmi: Add Kconfig to allow SCMI Testing driver
    coexistence

 Documentation/ABI/testing/debugfs-scmi        | 269 ++++++++
 drivers/firmware/arm_scmi/Kconfig             |  18 +
 drivers/firmware/arm_scmi/Makefile            |   2 +
 drivers/firmware/arm_scmi/base.c              |   5 +-
 drivers/firmware/arm_scmi/bus.c               |   4 +-
 drivers/firmware/arm_scmi/clock.c             |   9 +-
 drivers/firmware/arm_scmi/common.h            |  24 +-
 drivers/firmware/arm_scmi/driver.c            |  46 +-
 drivers/firmware/arm_scmi/notify.c            |  34 +-
 drivers/firmware/arm_scmi/perf.c              |  11 +-
 drivers/firmware/arm_scmi/power.c             |  11 +-
 drivers/firmware/arm_scmi/reset.c             |  11 +-
 .../arm_scmi/scmi_test_driver/Makefile        |   5 +
 .../arm_scmi/scmi_test_driver/scmi_test.c     | 160 +++++
 .../arm_scmi/scmi_test_driver/test_clocks.c   | 287 ++++++++
 .../arm_scmi/scmi_test_driver/test_common.c   | 285 ++++++++
 .../arm_scmi/scmi_test_driver/test_common.h   | 108 +++
 .../arm_scmi/scmi_test_driver/test_powers.c   | 105 +++
 .../arm_scmi/scmi_test_driver/test_sensors.c  | 627 ++++++++++++++++++
 .../arm_scmi/scmi_test_driver/test_voltages.c |  51 ++
 drivers/firmware/arm_scmi/sensors.c           |   5 +-
 drivers/firmware/arm_scmi/system.c            |  11 +-
 drivers/firmware/arm_scmi/voltage.c           |   1 +
 fs/debugfs/file.c                             |  74 +++
 fs/libfs.c                                    |  12 +-
 include/linux/debugfs.h                       |   4 +
 include/linux/scmi_protocol.h                 |  47 +-
 tools/testing/selftests/arm64/Makefile        |   2 +-
 tools/testing/selftests/arm64/scmi/Makefile   |   6 +
 tools/testing/selftests/arm64/scmi/config     |   1 +
 .../arm64/scmi/kselftest_scmi_lib.sh          | 118 ++++
 .../selftests/arm64/scmi/run_scmi_tests.sh    |  69 ++
 .../testcases/protocol_0x14/clock_enable.sh   |  33 +
 .../protocol_0x14/clock_rate_read.sh          |  18 +
 .../protocol_0x14/clock_rate_write.sh         |  29 +
 .../testcases/protocol_0x15/sensor_reading.sh |  17 +
 36 files changed, 2463 insertions(+), 56 deletions(-)
 create mode 100644 Documentation/ABI/testing/debugfs-scmi
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/Makefile
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
 create mode 100644 tools/testing/selftests/arm64/scmi/Makefile
 create mode 100644 tools/testing/selftests/arm64/scmi/config
 create mode 100644 tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh

-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFC PATCH 01/16] firmware: arm_scmi: Simplify scmi_devm_notifier_unregister
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:55   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Unregistering SCMI notifications using the managed devres interface can be
done providing as a reference simply the previously successfully registered
notification block since it could have been registered only on one kernel
notification_chain: drop any reference to SCMI protocol, events and
sources.

Devres internal helpers can search for the provided notification block
reference and, once found, the associated devres object will already
provide the above SCMI references for the event.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/notify.c | 30 ++++--------------------------
 include/linux/scmi_protocol.h      |  2 --
 2 files changed, 4 insertions(+), 28 deletions(-)

diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index 0efd20cd9d69..7d0b01b59616 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -1498,17 +1498,12 @@ static int scmi_devm_notifier_register(struct scmi_device *sdev,
 static int scmi_devm_notifier_match(struct device *dev, void *res, void *data)
 {
 	struct scmi_notifier_devres *dres = res;
-	struct scmi_notifier_devres *xres = data;
+	struct notifier_block *nb = data;
 
-	if (WARN_ON(!dres || !xres))
+	if (WARN_ON(!dres || !nb))
 		return 0;
 
-	return dres->proto_id == xres->proto_id &&
-		dres->evt_id == xres->evt_id &&
-		dres->nb == xres->nb &&
-		((!dres->src_id && !xres->src_id) ||
-		  (dres->src_id && xres->src_id &&
-		   dres->__src_id == xres->__src_id));
+	return dres->nb == nb;
 }
 
 /**
@@ -1516,10 +1511,6 @@ static int scmi_devm_notifier_match(struct device *dev, void *res, void *data)
  * notifier_block for an event
  * @sdev: A reference to an scmi_device whose embedded struct device is to
  *	  be used for devres accounting.
- * @proto_id: Protocol ID
- * @evt_id: Event ID
- * @src_id: Source ID, when NULL register for events coming form ALL possible
- *	    sources
  * @nb: A standard notifier block to register for the specified event
  *
  * Generic devres managed helper to explicitly un-register a notifier_block
@@ -1529,25 +1520,12 @@ static int scmi_devm_notifier_match(struct device *dev, void *res, void *data)
  * Return: 0 on Success
  */
 static int scmi_devm_notifier_unregister(struct scmi_device *sdev,
-					 u8 proto_id, u8 evt_id,
-					 const u32 *src_id,
 					 struct notifier_block *nb)
 {
 	int ret;
-	struct scmi_notifier_devres dres;
-
-	dres.handle = sdev->handle;
-	dres.proto_id = proto_id;
-	dres.evt_id = evt_id;
-	if (src_id) {
-		dres.__src_id = *src_id;
-		dres.src_id = &dres.__src_id;
-	} else {
-		dres.src_id = NULL;
-	}
 
 	ret = devres_release(&sdev->dev, scmi_devm_release_notifier,
-			     scmi_devm_notifier_match, &dres);
+			     scmi_devm_notifier_match, nb);
 
 	WARN_ON(ret);
 
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index b87551f41f9f..b0652f1411b9 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -595,8 +595,6 @@ struct scmi_notify_ops {
 					    const u32 *src_id,
 					    struct notifier_block *nb);
 	int (*devm_event_notifier_unregister)(struct scmi_device *sdev,
-					      u8 proto_id, u8 evt_id,
-					      const u32 *src_id,
 					      struct notifier_block *nb);
 	int (*event_notifier_register)(const struct scmi_handle *handle,
 				       u8 proto_id, u8 evt_id,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 01/16] firmware: arm_scmi: Simplify scmi_devm_notifier_unregister
@ 2022-02-27 20:55   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Unregistering SCMI notifications using the managed devres interface can be
done providing as a reference simply the previously successfully registered
notification block since it could have been registered only on one kernel
notification_chain: drop any reference to SCMI protocol, events and
sources.

Devres internal helpers can search for the provided notification block
reference and, once found, the associated devres object will already
provide the above SCMI references for the event.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/notify.c | 30 ++++--------------------------
 include/linux/scmi_protocol.h      |  2 --
 2 files changed, 4 insertions(+), 28 deletions(-)

diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index 0efd20cd9d69..7d0b01b59616 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -1498,17 +1498,12 @@ static int scmi_devm_notifier_register(struct scmi_device *sdev,
 static int scmi_devm_notifier_match(struct device *dev, void *res, void *data)
 {
 	struct scmi_notifier_devres *dres = res;
-	struct scmi_notifier_devres *xres = data;
+	struct notifier_block *nb = data;
 
-	if (WARN_ON(!dres || !xres))
+	if (WARN_ON(!dres || !nb))
 		return 0;
 
-	return dres->proto_id == xres->proto_id &&
-		dres->evt_id == xres->evt_id &&
-		dres->nb == xres->nb &&
-		((!dres->src_id && !xres->src_id) ||
-		  (dres->src_id && xres->src_id &&
-		   dres->__src_id == xres->__src_id));
+	return dres->nb == nb;
 }
 
 /**
@@ -1516,10 +1511,6 @@ static int scmi_devm_notifier_match(struct device *dev, void *res, void *data)
  * notifier_block for an event
  * @sdev: A reference to an scmi_device whose embedded struct device is to
  *	  be used for devres accounting.
- * @proto_id: Protocol ID
- * @evt_id: Event ID
- * @src_id: Source ID, when NULL register for events coming form ALL possible
- *	    sources
  * @nb: A standard notifier block to register for the specified event
  *
  * Generic devres managed helper to explicitly un-register a notifier_block
@@ -1529,25 +1520,12 @@ static int scmi_devm_notifier_match(struct device *dev, void *res, void *data)
  * Return: 0 on Success
  */
 static int scmi_devm_notifier_unregister(struct scmi_device *sdev,
-					 u8 proto_id, u8 evt_id,
-					 const u32 *src_id,
 					 struct notifier_block *nb)
 {
 	int ret;
-	struct scmi_notifier_devres dres;
-
-	dres.handle = sdev->handle;
-	dres.proto_id = proto_id;
-	dres.evt_id = evt_id;
-	if (src_id) {
-		dres.__src_id = *src_id;
-		dres.src_id = &dres.__src_id;
-	} else {
-		dres.src_id = NULL;
-	}
 
 	ret = devres_release(&sdev->dev, scmi_devm_release_notifier,
-			     scmi_devm_notifier_match, &dres);
+			     scmi_devm_notifier_match, nb);
 
 	WARN_ON(ret);
 
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index b87551f41f9f..b0652f1411b9 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -595,8 +595,6 @@ struct scmi_notify_ops {
 					    const u32 *src_id,
 					    struct notifier_block *nb);
 	int (*devm_event_notifier_unregister)(struct scmi_device *sdev,
-					      u8 proto_id, u8 evt_id,
-					      const u32 *src_id,
 					      struct notifier_block *nb);
 	int (*event_notifier_register)(const struct scmi_handle *handle,
 				       u8 proto_id, u8 evt_id,
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 02/16] firmware: arm_scmi: Make protocols init fail on basic errors
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:55   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Bail out of protocol initialization routine early when basic information
about protocol version and attributes could not be retrieved: failing to
act this way can lead to a successfully initialized SCMI protocol which
is in fact not functional.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/base.c    |  5 ++++-
 drivers/firmware/arm_scmi/clock.c   |  8 ++++++--
 drivers/firmware/arm_scmi/perf.c    | 10 +++++++---
 drivers/firmware/arm_scmi/power.c   | 10 +++++++---
 drivers/firmware/arm_scmi/reset.c   | 10 +++++++---
 drivers/firmware/arm_scmi/sensors.c |  4 +++-
 drivers/firmware/arm_scmi/system.c  |  5 ++++-
 7 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
index f5219334fd3a..ebaef5d320af 100644
--- a/drivers/firmware/arm_scmi/base.c
+++ b/drivers/firmware/arm_scmi/base.c
@@ -359,7 +359,10 @@ static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
 	rev->minor_ver = PROTOCOL_REV_MINOR(version);
 	ph->set_priv(ph, rev);
 
-	scmi_base_attributes_get(ph);
+	ret = scmi_base_attributes_get(ph);
+	if (ret)
+		return ret;
+
 	scmi_base_vendor_id_get(ph, false);
 	scmi_base_vendor_id_get(ph, true);
 	scmi_base_implementation_version_get(ph);
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index cf6fed6dec77..e2059d2025a2 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -360,7 +360,9 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
 	int clkid, ret;
 	struct clock_info *cinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Clock Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
@@ -369,7 +371,9 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
 	if (!cinfo)
 		return -ENOMEM;
 
-	scmi_clock_protocol_attributes_get(ph, cinfo);
+	ret = scmi_clock_protocol_attributes_get(ph, cinfo);
+	if (ret)
+		return ret;
 
 	cinfo->clk = devm_kcalloc(ph->dev, cinfo->num_clocks,
 				  sizeof(*cinfo->clk), GFP_KERNEL);
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index f4cd5193b961..e9f68b91580c 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -873,11 +873,13 @@ static const struct scmi_protocol_events perf_protocol_events = {
 
 static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
 {
-	int domain;
+	int domain, ret;
 	u32 version;
 	struct scmi_perf_info *pinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Performance Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
@@ -886,7 +888,9 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
 	if (!pinfo)
 		return -ENOMEM;
 
-	scmi_perf_attributes_get(ph, pinfo);
+	ret = scmi_perf_attributes_get(ph, pinfo);
+	if (ret)
+		return ret;
 
 	pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
 				       sizeof(*pinfo->dom_info), GFP_KERNEL);
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index ad2ab080f344..0f0b94f0b624 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -280,11 +280,13 @@ static const struct scmi_protocol_events power_protocol_events = {
 
 static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
 {
-	int domain;
+	int domain, ret;
 	u32 version;
 	struct scmi_power_info *pinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Power Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
@@ -293,7 +295,9 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
 	if (!pinfo)
 		return -ENOMEM;
 
-	scmi_power_attributes_get(ph, pinfo);
+	ret = scmi_power_attributes_get(ph, pinfo);
+	if (ret)
+		return ret;
 
 	pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
 				       sizeof(*pinfo->dom_info), GFP_KERNEL);
diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 9bf2478ec6d1..9cdbd133db10 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -293,11 +293,13 @@ static const struct scmi_protocol_events reset_protocol_events = {
 
 static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
 {
-	int domain;
+	int domain, ret;
 	u32 version;
 	struct scmi_reset_info *pinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Reset Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
@@ -306,7 +308,9 @@ static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
 	if (!pinfo)
 		return -ENOMEM;
 
-	scmi_reset_attributes_get(ph, pinfo);
+	ret = scmi_reset_attributes_get(ph, pinfo);
+	if (ret)
+		return ret;
 
 	pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
 				       sizeof(*pinfo->dom_info), GFP_KERNEL);
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index cdbb287bd8bc..f37ac9824a87 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -966,7 +966,9 @@ static int scmi_sensors_protocol_init(const struct scmi_protocol_handle *ph)
 	int ret;
 	struct sensors_info *sinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Sensor Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c
index e5175ef73b40..cbfc19f7a463 100644
--- a/drivers/firmware/arm_scmi/system.c
+++ b/drivers/firmware/arm_scmi/system.c
@@ -113,10 +113,13 @@ static const struct scmi_protocol_events system_protocol_events = {
 
 static int scmi_system_protocol_init(const struct scmi_protocol_handle *ph)
 {
+	int ret;
 	u32 version;
 	struct scmi_system_info *pinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "System Power Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 02/16] firmware: arm_scmi: Make protocols init fail on basic errors
@ 2022-02-27 20:55   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Bail out of protocol initialization routine early when basic information
about protocol version and attributes could not be retrieved: failing to
act this way can lead to a successfully initialized SCMI protocol which
is in fact not functional.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/base.c    |  5 ++++-
 drivers/firmware/arm_scmi/clock.c   |  8 ++++++--
 drivers/firmware/arm_scmi/perf.c    | 10 +++++++---
 drivers/firmware/arm_scmi/power.c   | 10 +++++++---
 drivers/firmware/arm_scmi/reset.c   | 10 +++++++---
 drivers/firmware/arm_scmi/sensors.c |  4 +++-
 drivers/firmware/arm_scmi/system.c  |  5 ++++-
 7 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
index f5219334fd3a..ebaef5d320af 100644
--- a/drivers/firmware/arm_scmi/base.c
+++ b/drivers/firmware/arm_scmi/base.c
@@ -359,7 +359,10 @@ static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
 	rev->minor_ver = PROTOCOL_REV_MINOR(version);
 	ph->set_priv(ph, rev);
 
-	scmi_base_attributes_get(ph);
+	ret = scmi_base_attributes_get(ph);
+	if (ret)
+		return ret;
+
 	scmi_base_vendor_id_get(ph, false);
 	scmi_base_vendor_id_get(ph, true);
 	scmi_base_implementation_version_get(ph);
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index cf6fed6dec77..e2059d2025a2 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -360,7 +360,9 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
 	int clkid, ret;
 	struct clock_info *cinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Clock Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
@@ -369,7 +371,9 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
 	if (!cinfo)
 		return -ENOMEM;
 
-	scmi_clock_protocol_attributes_get(ph, cinfo);
+	ret = scmi_clock_protocol_attributes_get(ph, cinfo);
+	if (ret)
+		return ret;
 
 	cinfo->clk = devm_kcalloc(ph->dev, cinfo->num_clocks,
 				  sizeof(*cinfo->clk), GFP_KERNEL);
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index f4cd5193b961..e9f68b91580c 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -873,11 +873,13 @@ static const struct scmi_protocol_events perf_protocol_events = {
 
 static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
 {
-	int domain;
+	int domain, ret;
 	u32 version;
 	struct scmi_perf_info *pinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Performance Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
@@ -886,7 +888,9 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
 	if (!pinfo)
 		return -ENOMEM;
 
-	scmi_perf_attributes_get(ph, pinfo);
+	ret = scmi_perf_attributes_get(ph, pinfo);
+	if (ret)
+		return ret;
 
 	pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
 				       sizeof(*pinfo->dom_info), GFP_KERNEL);
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index ad2ab080f344..0f0b94f0b624 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -280,11 +280,13 @@ static const struct scmi_protocol_events power_protocol_events = {
 
 static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
 {
-	int domain;
+	int domain, ret;
 	u32 version;
 	struct scmi_power_info *pinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Power Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
@@ -293,7 +295,9 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
 	if (!pinfo)
 		return -ENOMEM;
 
-	scmi_power_attributes_get(ph, pinfo);
+	ret = scmi_power_attributes_get(ph, pinfo);
+	if (ret)
+		return ret;
 
 	pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
 				       sizeof(*pinfo->dom_info), GFP_KERNEL);
diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 9bf2478ec6d1..9cdbd133db10 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -293,11 +293,13 @@ static const struct scmi_protocol_events reset_protocol_events = {
 
 static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
 {
-	int domain;
+	int domain, ret;
 	u32 version;
 	struct scmi_reset_info *pinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Reset Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
@@ -306,7 +308,9 @@ static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
 	if (!pinfo)
 		return -ENOMEM;
 
-	scmi_reset_attributes_get(ph, pinfo);
+	ret = scmi_reset_attributes_get(ph, pinfo);
+	if (ret)
+		return ret;
 
 	pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
 				       sizeof(*pinfo->dom_info), GFP_KERNEL);
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index cdbb287bd8bc..f37ac9824a87 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -966,7 +966,9 @@ static int scmi_sensors_protocol_init(const struct scmi_protocol_handle *ph)
 	int ret;
 	struct sensors_info *sinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "Sensor Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c
index e5175ef73b40..cbfc19f7a463 100644
--- a/drivers/firmware/arm_scmi/system.c
+++ b/drivers/firmware/arm_scmi/system.c
@@ -113,10 +113,13 @@ static const struct scmi_protocol_events system_protocol_events = {
 
 static int scmi_system_protocol_init(const struct scmi_protocol_handle *ph)
 {
+	int ret;
 	u32 version;
 	struct scmi_system_info *pinfo;
 
-	ph->xops->version_get(ph, &version);
+	ret = ph->xops->version_get(ph, &version);
+	if (ret)
+		return ret;
 
 	dev_dbg(ph->dev, "System Power Version %d.%d\n",
 		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 03/16] firmware: arm_scmi: Add multiple protocols registration support
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:55   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add the capability for one SCMI driver to register with the core SCMI stack
to use multiple SCMI protocols: in such a case the SCMI driver probe
function will end up being called once for each registered protocol which
have been also found as implemented on the platform.

This is especially useful in testing scenarios.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/bus.c    |  4 ++--
 drivers/firmware/arm_scmi/common.h |  4 ++--
 drivers/firmware/arm_scmi/driver.c | 24 ++++++++++++++++++++++--
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index f6fe723ab869..e417e84249f2 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -135,7 +135,7 @@ int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
 	if (!driver->probe)
 		return -EINVAL;
 
-	retval = scmi_protocol_device_request(driver->id_table);
+	retval = scmi_protocol_table_register(driver->id_table);
 	if (retval)
 		return retval;
 
@@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(scmi_driver_register);
 void scmi_driver_unregister(struct scmi_driver *driver)
 {
 	driver_unregister(&driver->driver);
-	scmi_protocol_device_unrequest(driver->id_table);
+	scmi_protocol_table_unregister(driver->id_table);
 }
 EXPORT_SYMBOL_GPL(scmi_driver_unregister);
 
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 4fda84bfab42..ffaf74a36b30 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -388,8 +388,8 @@ struct scmi_transport_ops {
 	bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer);
 };
 
-int scmi_protocol_device_request(const struct scmi_device_id *id_table);
-void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table);
+int scmi_protocol_table_register(const struct scmi_device_id *id_table);
+void scmi_protocol_table_unregister(const struct scmi_device_id *id_table);
 struct scmi_device *scmi_child_dev_find(struct device *parent,
 					int prot_id, const char *name);
 
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 4cb9e0ad7af5..8d356d4da0bd 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1771,7 +1771,7 @@ static void scmi_create_protocol_devices(struct device_node *np,
  *
  * Return: 0 on Success
  */
-int scmi_protocol_device_request(const struct scmi_device_id *id_table)
+static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 {
 	int ret = 0;
 	unsigned int id = 0;
@@ -1882,6 +1882,17 @@ int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 	return ret;
 }
 
+int scmi_protocol_table_register(const struct scmi_device_id *id_table)
+{
+	int ret = 0;
+	const struct scmi_device_id *entry;
+
+	for (entry = id_table; entry->name && ret == 0; entry++)
+		ret = scmi_protocol_device_request(entry);
+
+	return ret;
+}
+
 /**
  * scmi_protocol_device_unrequest  - Helper to unrequest a device
  *
@@ -1896,7 +1907,8 @@ int scmi_protocol_device_request(const struct scmi_device_id *id_table)
  * that cannot be safely destroyed till the whole SCMI stack is removed.
  * (unless adding further burden of refcounting.)
  */
-void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
+static void
+scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
 {
 	struct list_head *phead;
 
@@ -1925,6 +1937,14 @@ void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
 	mutex_unlock(&scmi_requested_devices_mtx);
 }
 
+void scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
+{
+	const struct scmi_device_id *entry;
+
+	for (entry = id_table; entry->name; entry++)
+		scmi_protocol_device_unrequest(entry);
+}
+
 static int scmi_cleanup_txrx_channels(struct scmi_info *info)
 {
 	int ret;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 03/16] firmware: arm_scmi: Add multiple protocols registration support
@ 2022-02-27 20:55   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add the capability for one SCMI driver to register with the core SCMI stack
to use multiple SCMI protocols: in such a case the SCMI driver probe
function will end up being called once for each registered protocol which
have been also found as implemented on the platform.

This is especially useful in testing scenarios.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/bus.c    |  4 ++--
 drivers/firmware/arm_scmi/common.h |  4 ++--
 drivers/firmware/arm_scmi/driver.c | 24 ++++++++++++++++++++++--
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index f6fe723ab869..e417e84249f2 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -135,7 +135,7 @@ int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
 	if (!driver->probe)
 		return -EINVAL;
 
-	retval = scmi_protocol_device_request(driver->id_table);
+	retval = scmi_protocol_table_register(driver->id_table);
 	if (retval)
 		return retval;
 
@@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(scmi_driver_register);
 void scmi_driver_unregister(struct scmi_driver *driver)
 {
 	driver_unregister(&driver->driver);
-	scmi_protocol_device_unrequest(driver->id_table);
+	scmi_protocol_table_unregister(driver->id_table);
 }
 EXPORT_SYMBOL_GPL(scmi_driver_unregister);
 
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 4fda84bfab42..ffaf74a36b30 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -388,8 +388,8 @@ struct scmi_transport_ops {
 	bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer);
 };
 
-int scmi_protocol_device_request(const struct scmi_device_id *id_table);
-void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table);
+int scmi_protocol_table_register(const struct scmi_device_id *id_table);
+void scmi_protocol_table_unregister(const struct scmi_device_id *id_table);
 struct scmi_device *scmi_child_dev_find(struct device *parent,
 					int prot_id, const char *name);
 
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 4cb9e0ad7af5..8d356d4da0bd 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1771,7 +1771,7 @@ static void scmi_create_protocol_devices(struct device_node *np,
  *
  * Return: 0 on Success
  */
-int scmi_protocol_device_request(const struct scmi_device_id *id_table)
+static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 {
 	int ret = 0;
 	unsigned int id = 0;
@@ -1882,6 +1882,17 @@ int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 	return ret;
 }
 
+int scmi_protocol_table_register(const struct scmi_device_id *id_table)
+{
+	int ret = 0;
+	const struct scmi_device_id *entry;
+
+	for (entry = id_table; entry->name && ret == 0; entry++)
+		ret = scmi_protocol_device_request(entry);
+
+	return ret;
+}
+
 /**
  * scmi_protocol_device_unrequest  - Helper to unrequest a device
  *
@@ -1896,7 +1907,8 @@ int scmi_protocol_device_request(const struct scmi_device_id *id_table)
  * that cannot be safely destroyed till the whole SCMI stack is removed.
  * (unless adding further burden of refcounting.)
  */
-void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
+static void
+scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
 {
 	struct list_head *phead;
 
@@ -1925,6 +1937,14 @@ void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
 	mutex_unlock(&scmi_requested_devices_mtx);
 }
 
+void scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
+{
+	const struct scmi_device_id *entry;
+
+	for (entry = id_table; entry->name; entry++)
+		scmi_protocol_device_unrequest(entry);
+}
+
 static int scmi_cleanup_txrx_channels(struct scmi_info *info)
 {
 	int ret;
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 04/16] firmware: arm_scmi: Add .version_get protocol operation
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:55   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add new .version_get protocol operation so as to allow interested SCMI
driver users to lookup protocol versions implemented by the underlying
SCMI platform.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/clock.c   |  1 +
 drivers/firmware/arm_scmi/common.h  | 20 ++++++++++++++++++++
 drivers/firmware/arm_scmi/perf.c    |  1 +
 drivers/firmware/arm_scmi/power.c   |  1 +
 drivers/firmware/arm_scmi/reset.c   |  1 +
 drivers/firmware/arm_scmi/sensors.c |  1 +
 drivers/firmware/arm_scmi/system.c  |  6 +++++-
 drivers/firmware/arm_scmi/voltage.c |  1 +
 include/linux/scmi_protocol.h       | 22 ++++++++++++++++++++++
 9 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index e2059d2025a2..c19b6bff370d 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -344,6 +344,7 @@ scmi_clock_info_get(const struct scmi_protocol_handle *ph, u32 clk_id)
 }
 
 static const struct scmi_clk_proto_ops clk_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.count_get = scmi_clock_count_get,
 	.info_get = scmi_clock_info_get,
 	.rate_get = scmi_clock_rate_get,
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index ffaf74a36b30..e7e9c8c5d48c 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -269,6 +269,26 @@ struct scmi_xfer_ops {
 			 struct scmi_xfer *xfer);
 };
 
+/**
+ * scmi_protocol_version_get  - Common helper to get protocol version
+ *
+ * @ph: A reference to an initialized protocol handle
+ *
+ * Exposed as .version_get for each protocol operations, it can be called by
+ * SCMI drivers only on initialized protocol instances so it cannot fail.
+ *
+ * Return: Protocol version for the specified protocol handle
+ */
+static inline
+unsigned int scmi_protocol_version_get(struct scmi_protocol_handle *ph)
+{
+	u32 version = 0;
+
+	ph->xops->version_get(ph, &version);
+
+	return version;
+}
+
 struct scmi_revision_info *
 scmi_revision_area_get(const struct scmi_protocol_handle *ph);
 int scmi_handle_put(const struct scmi_handle *handle);
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index e9f68b91580c..e58490a8d0e7 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -756,6 +756,7 @@ static bool scmi_power_scale_mw_get(const struct scmi_protocol_handle *ph)
 }
 
 static const struct scmi_perf_proto_ops perf_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.limits_set = scmi_perf_limits_set,
 	.limits_get = scmi_perf_limits_get,
 	.level_set = scmi_perf_level_set,
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index 0f0b94f0b624..c14bdb9a9ccd 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -184,6 +184,7 @@ static char *scmi_power_name_get(const struct scmi_protocol_handle *ph,
 }
 
 static const struct scmi_power_proto_ops power_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.num_domains_get = scmi_power_num_domains_get,
 	.name_get = scmi_power_name_get,
 	.state_set = scmi_power_state_set,
diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 9cdbd133db10..acf83ea361ed 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -196,6 +196,7 @@ scmi_reset_domain_deassert(const struct scmi_protocol_handle *ph, u32 domain)
 }
 
 static const struct scmi_reset_proto_ops reset_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.num_domains_get = scmi_reset_num_domains_get,
 	.name_get = scmi_reset_name_get,
 	.latency_get = scmi_reset_latency_get,
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index f37ac9824a87..4ee578cf0c23 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -828,6 +828,7 @@ static int scmi_sensor_count_get(const struct scmi_protocol_handle *ph)
 }
 
 static const struct scmi_sensor_proto_ops sensor_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.count_get = scmi_sensor_count_get,
 	.info_get = scmi_sensor_info_get,
 	.trip_point_config = scmi_sensor_trip_point_config,
diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c
index cbfc19f7a463..90157d7f45bc 100644
--- a/drivers/firmware/arm_scmi/system.c
+++ b/drivers/firmware/arm_scmi/system.c
@@ -33,6 +33,10 @@ struct scmi_system_info {
 	u32 version;
 };
 
+static struct scmi_system_proto_ops system_proto_ops = {
+	.version_get = scmi_protocol_version_get,
+};
+
 static int scmi_system_request_notify(const struct scmi_protocol_handle *ph,
 				      bool enable)
 {
@@ -136,7 +140,7 @@ static const struct scmi_protocol scmi_system = {
 	.id = SCMI_PROTOCOL_SYSTEM,
 	.owner = THIS_MODULE,
 	.instance_init = &scmi_system_protocol_init,
-	.ops = NULL,
+	.ops = &system_proto_ops,
 	.events = &system_protocol_events,
 };
 
diff --git a/drivers/firmware/arm_scmi/voltage.c b/drivers/firmware/arm_scmi/voltage.c
index ac08e819088b..c9a7cbdc9164 100644
--- a/drivers/firmware/arm_scmi/voltage.c
+++ b/drivers/firmware/arm_scmi/voltage.c
@@ -324,6 +324,7 @@ static int scmi_voltage_domains_num_get(const struct scmi_protocol_handle *ph)
 }
 
 static struct scmi_voltage_proto_ops voltage_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.num_domains_get = scmi_voltage_domains_num_get,
 	.info_get = scmi_voltage_info_get,
 	.config_set = scmi_voltage_config_set,
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index b0652f1411b9..c5881d15f7d9 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -65,6 +65,7 @@ struct scmi_protocol_handle;
  * struct scmi_clk_proto_ops - represents the various operations provided
  *	by SCMI Clock Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @count_get: get the count of clocks provided by SCMI
  * @info_get: get the information of the specified clock
  * @rate_get: request the current clock rate of a clock
@@ -73,6 +74,7 @@ struct scmi_protocol_handle;
  * @disable: disables the specified clock
  */
 struct scmi_clk_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*count_get)(const struct scmi_protocol_handle *ph);
 
 	const struct scmi_clock_info *(*info_get)
@@ -92,6 +94,7 @@ struct scmi_clk_proto_ops {
  * struct scmi_perf_proto_ops - represents the various operations provided
  *	by SCMI Performance Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @limits_set: sets limits on the performance level of a domain
  * @limits_get: gets limits on the performance level of a domain
  * @level_set: sets the performance level of a domain
@@ -111,6 +114,7 @@ struct scmi_clk_proto_ops {
  *	or in some other (abstract) scale
  */
 struct scmi_perf_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*limits_set)(const struct scmi_protocol_handle *ph, u32 domain,
 			  u32 max_perf, u32 min_perf);
 	int (*limits_get)(const struct scmi_protocol_handle *ph, u32 domain,
@@ -139,12 +143,14 @@ struct scmi_perf_proto_ops {
  * struct scmi_power_proto_ops - represents the various operations provided
  *	by SCMI Power Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @num_domains_get: get the count of power domains provided by SCMI
  * @name_get: gets the name of a power domain
  * @state_set: sets the power state of a power domain
  * @state_get: gets the power state of a power domain
  */
 struct scmi_power_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*num_domains_get)(const struct scmi_protocol_handle *ph);
 	char *(*name_get)(const struct scmi_protocol_handle *ph, u32 domain);
 #define SCMI_POWER_STATE_TYPE_SHIFT	30
@@ -442,6 +448,7 @@ enum scmi_sensor_class {
  * struct scmi_sensor_proto_ops - represents the various operations provided
  *	by SCMI Sensor Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @count_get: get the count of sensors provided by SCMI
  * @info_get: get the information of the specified sensor
  * @trip_point_config: selects and configures a trip-point of interest
@@ -455,6 +462,7 @@ enum scmi_sensor_class {
  * @config_set: Set sensor current configuration
  */
 struct scmi_sensor_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*count_get)(const struct scmi_protocol_handle *ph);
 	const struct scmi_sensor_info *(*info_get)
 		(const struct scmi_protocol_handle *ph, u32 sensor_id);
@@ -475,6 +483,7 @@ struct scmi_sensor_proto_ops {
  * struct scmi_reset_proto_ops - represents the various operations provided
  *	by SCMI Reset Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @num_domains_get: get the count of reset domains provided by SCMI
  * @name_get: gets the name of a reset domain
  * @latency_get: gets the reset latency for the specified reset domain
@@ -483,6 +492,7 @@ struct scmi_sensor_proto_ops {
  * @deassert: explicitly deassert reset signal of the specified reset domain
  */
 struct scmi_reset_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*num_domains_get)(const struct scmi_protocol_handle *ph);
 	char *(*name_get)(const struct scmi_protocol_handle *ph, u32 domain);
 	int (*latency_get)(const struct scmi_protocol_handle *ph, u32 domain);
@@ -526,6 +536,7 @@ struct scmi_voltage_info {
  * struct scmi_voltage_proto_ops - represents the various operations provided
  * by SCMI Voltage Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @num_domains_get: get the count of voltage domains provided by SCMI
  * @info_get: get the information of the specified domain
  * @config_set: set the config for the specified domain
@@ -534,6 +545,7 @@ struct scmi_voltage_info {
  * @level_get: get the voltage level of the specified domain
  */
 struct scmi_voltage_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*num_domains_get)(const struct scmi_protocol_handle *ph);
 	const struct scmi_voltage_info __must_check *(*info_get)
 		(const struct scmi_protocol_handle *ph, u32 domain_id);
@@ -549,6 +561,16 @@ struct scmi_voltage_proto_ops {
 			 s32 *volt_uV);
 };
 
+/**
+ * struct scmi_system_proto_ops - represents the various operations provided
+ * by SCMI System Power Protocol
+ *
+ * @version_get: get the protocol version implemented by this SCMI instance
+ */
+struct scmi_system_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
+};
+
 /**
  * struct scmi_notify_ops  - represents notifications' operations provided by
  * SCMI core
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 04/16] firmware: arm_scmi: Add .version_get protocol operation
@ 2022-02-27 20:55   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add new .version_get protocol operation so as to allow interested SCMI
driver users to lookup protocol versions implemented by the underlying
SCMI platform.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/clock.c   |  1 +
 drivers/firmware/arm_scmi/common.h  | 20 ++++++++++++++++++++
 drivers/firmware/arm_scmi/perf.c    |  1 +
 drivers/firmware/arm_scmi/power.c   |  1 +
 drivers/firmware/arm_scmi/reset.c   |  1 +
 drivers/firmware/arm_scmi/sensors.c |  1 +
 drivers/firmware/arm_scmi/system.c  |  6 +++++-
 drivers/firmware/arm_scmi/voltage.c |  1 +
 include/linux/scmi_protocol.h       | 22 ++++++++++++++++++++++
 9 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index e2059d2025a2..c19b6bff370d 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -344,6 +344,7 @@ scmi_clock_info_get(const struct scmi_protocol_handle *ph, u32 clk_id)
 }
 
 static const struct scmi_clk_proto_ops clk_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.count_get = scmi_clock_count_get,
 	.info_get = scmi_clock_info_get,
 	.rate_get = scmi_clock_rate_get,
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index ffaf74a36b30..e7e9c8c5d48c 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -269,6 +269,26 @@ struct scmi_xfer_ops {
 			 struct scmi_xfer *xfer);
 };
 
+/**
+ * scmi_protocol_version_get  - Common helper to get protocol version
+ *
+ * @ph: A reference to an initialized protocol handle
+ *
+ * Exposed as .version_get for each protocol operations, it can be called by
+ * SCMI drivers only on initialized protocol instances so it cannot fail.
+ *
+ * Return: Protocol version for the specified protocol handle
+ */
+static inline
+unsigned int scmi_protocol_version_get(struct scmi_protocol_handle *ph)
+{
+	u32 version = 0;
+
+	ph->xops->version_get(ph, &version);
+
+	return version;
+}
+
 struct scmi_revision_info *
 scmi_revision_area_get(const struct scmi_protocol_handle *ph);
 int scmi_handle_put(const struct scmi_handle *handle);
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index e9f68b91580c..e58490a8d0e7 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -756,6 +756,7 @@ static bool scmi_power_scale_mw_get(const struct scmi_protocol_handle *ph)
 }
 
 static const struct scmi_perf_proto_ops perf_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.limits_set = scmi_perf_limits_set,
 	.limits_get = scmi_perf_limits_get,
 	.level_set = scmi_perf_level_set,
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index 0f0b94f0b624..c14bdb9a9ccd 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -184,6 +184,7 @@ static char *scmi_power_name_get(const struct scmi_protocol_handle *ph,
 }
 
 static const struct scmi_power_proto_ops power_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.num_domains_get = scmi_power_num_domains_get,
 	.name_get = scmi_power_name_get,
 	.state_set = scmi_power_state_set,
diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 9cdbd133db10..acf83ea361ed 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -196,6 +196,7 @@ scmi_reset_domain_deassert(const struct scmi_protocol_handle *ph, u32 domain)
 }
 
 static const struct scmi_reset_proto_ops reset_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.num_domains_get = scmi_reset_num_domains_get,
 	.name_get = scmi_reset_name_get,
 	.latency_get = scmi_reset_latency_get,
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index f37ac9824a87..4ee578cf0c23 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -828,6 +828,7 @@ static int scmi_sensor_count_get(const struct scmi_protocol_handle *ph)
 }
 
 static const struct scmi_sensor_proto_ops sensor_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.count_get = scmi_sensor_count_get,
 	.info_get = scmi_sensor_info_get,
 	.trip_point_config = scmi_sensor_trip_point_config,
diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c
index cbfc19f7a463..90157d7f45bc 100644
--- a/drivers/firmware/arm_scmi/system.c
+++ b/drivers/firmware/arm_scmi/system.c
@@ -33,6 +33,10 @@ struct scmi_system_info {
 	u32 version;
 };
 
+static struct scmi_system_proto_ops system_proto_ops = {
+	.version_get = scmi_protocol_version_get,
+};
+
 static int scmi_system_request_notify(const struct scmi_protocol_handle *ph,
 				      bool enable)
 {
@@ -136,7 +140,7 @@ static const struct scmi_protocol scmi_system = {
 	.id = SCMI_PROTOCOL_SYSTEM,
 	.owner = THIS_MODULE,
 	.instance_init = &scmi_system_protocol_init,
-	.ops = NULL,
+	.ops = &system_proto_ops,
 	.events = &system_protocol_events,
 };
 
diff --git a/drivers/firmware/arm_scmi/voltage.c b/drivers/firmware/arm_scmi/voltage.c
index ac08e819088b..c9a7cbdc9164 100644
--- a/drivers/firmware/arm_scmi/voltage.c
+++ b/drivers/firmware/arm_scmi/voltage.c
@@ -324,6 +324,7 @@ static int scmi_voltage_domains_num_get(const struct scmi_protocol_handle *ph)
 }
 
 static struct scmi_voltage_proto_ops voltage_proto_ops = {
+	.version_get = scmi_protocol_version_get,
 	.num_domains_get = scmi_voltage_domains_num_get,
 	.info_get = scmi_voltage_info_get,
 	.config_set = scmi_voltage_config_set,
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index b0652f1411b9..c5881d15f7d9 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -65,6 +65,7 @@ struct scmi_protocol_handle;
  * struct scmi_clk_proto_ops - represents the various operations provided
  *	by SCMI Clock Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @count_get: get the count of clocks provided by SCMI
  * @info_get: get the information of the specified clock
  * @rate_get: request the current clock rate of a clock
@@ -73,6 +74,7 @@ struct scmi_protocol_handle;
  * @disable: disables the specified clock
  */
 struct scmi_clk_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*count_get)(const struct scmi_protocol_handle *ph);
 
 	const struct scmi_clock_info *(*info_get)
@@ -92,6 +94,7 @@ struct scmi_clk_proto_ops {
  * struct scmi_perf_proto_ops - represents the various operations provided
  *	by SCMI Performance Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @limits_set: sets limits on the performance level of a domain
  * @limits_get: gets limits on the performance level of a domain
  * @level_set: sets the performance level of a domain
@@ -111,6 +114,7 @@ struct scmi_clk_proto_ops {
  *	or in some other (abstract) scale
  */
 struct scmi_perf_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*limits_set)(const struct scmi_protocol_handle *ph, u32 domain,
 			  u32 max_perf, u32 min_perf);
 	int (*limits_get)(const struct scmi_protocol_handle *ph, u32 domain,
@@ -139,12 +143,14 @@ struct scmi_perf_proto_ops {
  * struct scmi_power_proto_ops - represents the various operations provided
  *	by SCMI Power Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @num_domains_get: get the count of power domains provided by SCMI
  * @name_get: gets the name of a power domain
  * @state_set: sets the power state of a power domain
  * @state_get: gets the power state of a power domain
  */
 struct scmi_power_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*num_domains_get)(const struct scmi_protocol_handle *ph);
 	char *(*name_get)(const struct scmi_protocol_handle *ph, u32 domain);
 #define SCMI_POWER_STATE_TYPE_SHIFT	30
@@ -442,6 +448,7 @@ enum scmi_sensor_class {
  * struct scmi_sensor_proto_ops - represents the various operations provided
  *	by SCMI Sensor Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @count_get: get the count of sensors provided by SCMI
  * @info_get: get the information of the specified sensor
  * @trip_point_config: selects and configures a trip-point of interest
@@ -455,6 +462,7 @@ enum scmi_sensor_class {
  * @config_set: Set sensor current configuration
  */
 struct scmi_sensor_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*count_get)(const struct scmi_protocol_handle *ph);
 	const struct scmi_sensor_info *(*info_get)
 		(const struct scmi_protocol_handle *ph, u32 sensor_id);
@@ -475,6 +483,7 @@ struct scmi_sensor_proto_ops {
  * struct scmi_reset_proto_ops - represents the various operations provided
  *	by SCMI Reset Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @num_domains_get: get the count of reset domains provided by SCMI
  * @name_get: gets the name of a reset domain
  * @latency_get: gets the reset latency for the specified reset domain
@@ -483,6 +492,7 @@ struct scmi_sensor_proto_ops {
  * @deassert: explicitly deassert reset signal of the specified reset domain
  */
 struct scmi_reset_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*num_domains_get)(const struct scmi_protocol_handle *ph);
 	char *(*name_get)(const struct scmi_protocol_handle *ph, u32 domain);
 	int (*latency_get)(const struct scmi_protocol_handle *ph, u32 domain);
@@ -526,6 +536,7 @@ struct scmi_voltage_info {
  * struct scmi_voltage_proto_ops - represents the various operations provided
  * by SCMI Voltage Protocol
  *
+ * @version_get: get the protocol version implemented by this SCMI instance
  * @num_domains_get: get the count of voltage domains provided by SCMI
  * @info_get: get the information of the specified domain
  * @config_set: set the config for the specified domain
@@ -534,6 +545,7 @@ struct scmi_voltage_info {
  * @level_get: get the voltage level of the specified domain
  */
 struct scmi_voltage_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
 	int (*num_domains_get)(const struct scmi_protocol_handle *ph);
 	const struct scmi_voltage_info __must_check *(*info_get)
 		(const struct scmi_protocol_handle *ph, u32 domain_id);
@@ -549,6 +561,16 @@ struct scmi_voltage_proto_ops {
 			 s32 *volt_uV);
 };
 
+/**
+ * struct scmi_system_proto_ops - represents the various operations provided
+ * by SCMI System Power Protocol
+ *
+ * @version_get: get the protocol version implemented by this SCMI instance
+ */
+struct scmi_system_proto_ops {
+	unsigned int (*version_get)(struct scmi_protocol_handle *ph);
+};
+
 /**
  * struct scmi_notify_ops  - represents notifications' operations provided by
  * SCMI core
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 05/16] firmware: arm_scmi: Expose information on configured transport
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:55   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add a common descriptor to describe transport features and expose it via
the SCMI instance handle.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/driver.c | 12 ++++++++++++
 include/linux/scmi_protocol.h      | 20 ++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 8d356d4da0bd..8c5429529946 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1966,6 +1966,7 @@ static int scmi_probe(struct platform_device *pdev)
 	struct scmi_handle *handle;
 	const struct scmi_desc *desc;
 	struct scmi_info *info;
+	struct scmi_transport_info *trans;
 	struct device *dev = &pdev->dev;
 	struct device_node *child, *np = dev->of_node;
 
@@ -2023,6 +2024,17 @@ static int scmi_probe(struct platform_device *pdev)
 		dev_err(dev,
 			"Transport is not polling capable. Atomic mode not supported.\n");
 
+	trans = devm_kzalloc(dev, sizeof(*trans), GFP_KERNEL);
+	if (!trans)
+		return -ENOMEM;
+
+	of_property_read_string(dev->of_node, "compatible", &trans->compatible);
+	trans->is_atomic =
+		handle->is_transport_atomic(handle,
+					    &trans->atomic_threshold_us);
+	trans->max_rx_timeout_ms = info->desc->max_rx_timeout_ms;
+	handle->transport = trans;
+
 	/*
 	 * Trigger SCMI Base protocol initialization.
 	 * It's mandatory and won't be ever released/deinit until the
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index c5881d15f7d9..0b024d23a9b3 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -40,6 +40,24 @@ struct scmi_revision_info {
 	char sub_vendor_id[SCMI_MAX_STR_SIZE];
 };
 
+/**
+ * struct scmi_transport_info  - transport related information
+ *
+ * @compatible: Transport name picked from compatible string
+ * @is_atomic: True if the underlying transport can support atomic transactions
+ *	       and atomic mode is enabled.
+ * @atomic_threshold_us: Optional system wide DT-configured threshold, expressed
+ *			 in microseconds, for atomic operations.
+ * @max_rx_timeout_ms: configured maximum timeout in milliseconds for command
+ *		       replies.
+ */
+struct scmi_transport_info {
+	const char *compatible;
+	bool is_atomic;
+	unsigned int atomic_threshold_us;
+	unsigned int max_rx_timeout_ms;
+};
+
 struct scmi_clock_info {
 	char name[SCMI_MAX_STR_SIZE];
 	unsigned int enable_latency;
@@ -633,6 +651,7 @@ struct scmi_notify_ops {
  *
  * @dev: pointer to the SCMI device
  * @version: pointer to the structure containing SCMI version information
+ * @transport: pointer to the structure containing SCMI transport information
  * @devm_protocol_get: devres managed method to acquire a protocol and get specific
  *		       operations and a dedicated protocol handler
  * @devm_protocol_put: devres managed method to release a protocol
@@ -650,6 +669,7 @@ struct scmi_notify_ops {
 struct scmi_handle {
 	struct device *dev;
 	struct scmi_revision_info *version;
+	struct scmi_transport_info *transport;
 
 	const void __must_check *
 		(*devm_protocol_get)(struct scmi_device *sdev, u8 proto,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 05/16] firmware: arm_scmi: Expose information on configured transport
@ 2022-02-27 20:55   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add a common descriptor to describe transport features and expose it via
the SCMI instance handle.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/driver.c | 12 ++++++++++++
 include/linux/scmi_protocol.h      | 20 ++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 8d356d4da0bd..8c5429529946 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1966,6 +1966,7 @@ static int scmi_probe(struct platform_device *pdev)
 	struct scmi_handle *handle;
 	const struct scmi_desc *desc;
 	struct scmi_info *info;
+	struct scmi_transport_info *trans;
 	struct device *dev = &pdev->dev;
 	struct device_node *child, *np = dev->of_node;
 
@@ -2023,6 +2024,17 @@ static int scmi_probe(struct platform_device *pdev)
 		dev_err(dev,
 			"Transport is not polling capable. Atomic mode not supported.\n");
 
+	trans = devm_kzalloc(dev, sizeof(*trans), GFP_KERNEL);
+	if (!trans)
+		return -ENOMEM;
+
+	of_property_read_string(dev->of_node, "compatible", &trans->compatible);
+	trans->is_atomic =
+		handle->is_transport_atomic(handle,
+					    &trans->atomic_threshold_us);
+	trans->max_rx_timeout_ms = info->desc->max_rx_timeout_ms;
+	handle->transport = trans;
+
 	/*
 	 * Trigger SCMI Base protocol initialization.
 	 * It's mandatory and won't be ever released/deinit until the
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index c5881d15f7d9..0b024d23a9b3 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -40,6 +40,24 @@ struct scmi_revision_info {
 	char sub_vendor_id[SCMI_MAX_STR_SIZE];
 };
 
+/**
+ * struct scmi_transport_info  - transport related information
+ *
+ * @compatible: Transport name picked from compatible string
+ * @is_atomic: True if the underlying transport can support atomic transactions
+ *	       and atomic mode is enabled.
+ * @atomic_threshold_us: Optional system wide DT-configured threshold, expressed
+ *			 in microseconds, for atomic operations.
+ * @max_rx_timeout_ms: configured maximum timeout in milliseconds for command
+ *		       replies.
+ */
+struct scmi_transport_info {
+	const char *compatible;
+	bool is_atomic;
+	unsigned int atomic_threshold_us;
+	unsigned int max_rx_timeout_ms;
+};
+
 struct scmi_clock_info {
 	char name[SCMI_MAX_STR_SIZE];
 	unsigned int enable_latency;
@@ -633,6 +651,7 @@ struct scmi_notify_ops {
  *
  * @dev: pointer to the SCMI device
  * @version: pointer to the structure containing SCMI version information
+ * @transport: pointer to the structure containing SCMI transport information
  * @devm_protocol_get: devres managed method to acquire a protocol and get specific
  *		       operations and a dedicated protocol handler
  * @devm_protocol_put: devres managed method to release a protocol
@@ -650,6 +669,7 @@ struct scmi_notify_ops {
 struct scmi_handle {
 	struct device *dev;
 	struct scmi_revision_info *version;
+	struct scmi_transport_info *transport;
 
 	const void __must_check *
 		(*devm_protocol_get)(struct scmi_device *sdev, u8 proto,
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 06/16] firmware: arm_scmi: Define a common SCMI_MAX_PROTOCOLS value
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:55   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add a common definition of SCMI_MAX_PROTOCOLS and use it all over the
SCMI stack.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/notify.c | 4 +---
 include/linux/scmi_protocol.h      | 3 +++
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index 7d0b01b59616..5ccee248c22e 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -94,8 +94,6 @@
 #include "common.h"
 #include "notify.h"
 
-#define SCMI_MAX_PROTO		256
-
 #define PROTO_ID_MASK		GENMASK(31, 24)
 #define EVT_ID_MASK		GENMASK(23, 16)
 #define SRC_ID_MASK		GENMASK(15, 0)
@@ -1637,7 +1635,7 @@ int scmi_notification_init(struct scmi_handle *handle)
 	ni->gid = gid;
 	ni->handle = handle;
 
-	ni->registered_protocols = devm_kcalloc(handle->dev, SCMI_MAX_PROTO,
+	ni->registered_protocols = devm_kcalloc(handle->dev, SCMI_MAX_PROTOCOLS,
 						sizeof(char *), GFP_KERNEL);
 	if (!ni->registered_protocols)
 		goto err;
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 0b024d23a9b3..63c1d1cc20ff 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -690,8 +690,11 @@ enum scmi_std_protocol {
 	SCMI_PROTOCOL_SENSOR = 0x15,
 	SCMI_PROTOCOL_RESET = 0x16,
 	SCMI_PROTOCOL_VOLTAGE = 0x17,
+	SCMI_PROTOCOL_LAST = 0xff,
 };
 
+#define SCMI_MAX_PROTOCOLS	(SCMI_PROTOCOL_LAST + 1)
+
 enum scmi_system_events {
 	SCMI_SYSTEM_SHUTDOWN,
 	SCMI_SYSTEM_COLDRESET,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 06/16] firmware: arm_scmi: Define a common SCMI_MAX_PROTOCOLS value
@ 2022-02-27 20:55   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add a common definition of SCMI_MAX_PROTOCOLS and use it all over the
SCMI stack.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/notify.c | 4 +---
 include/linux/scmi_protocol.h      | 3 +++
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index 7d0b01b59616..5ccee248c22e 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -94,8 +94,6 @@
 #include "common.h"
 #include "notify.h"
 
-#define SCMI_MAX_PROTO		256
-
 #define PROTO_ID_MASK		GENMASK(31, 24)
 #define EVT_ID_MASK		GENMASK(23, 16)
 #define SRC_ID_MASK		GENMASK(15, 0)
@@ -1637,7 +1635,7 @@ int scmi_notification_init(struct scmi_handle *handle)
 	ni->gid = gid;
 	ni->handle = handle;
 
-	ni->registered_protocols = devm_kcalloc(handle->dev, SCMI_MAX_PROTO,
+	ni->registered_protocols = devm_kcalloc(handle->dev, SCMI_MAX_PROTOCOLS,
 						sizeof(char *), GFP_KERNEL);
 	if (!ni->registered_protocols)
 		goto err;
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 0b024d23a9b3..63c1d1cc20ff 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -690,8 +690,11 @@ enum scmi_std_protocol {
 	SCMI_PROTOCOL_SENSOR = 0x15,
 	SCMI_PROTOCOL_RESET = 0x16,
 	SCMI_PROTOCOL_VOLTAGE = 0x17,
+	SCMI_PROTOCOL_LAST = 0xff,
 };
 
+#define SCMI_MAX_PROTOCOLS	(SCMI_PROTOCOL_LAST + 1)
+
 enum scmi_system_events {
 	SCMI_SYSTEM_SHUTDOWN,
 	SCMI_SYSTEM_COLDRESET,
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:55   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi, Greg Kroah-Hartman, Rafael J. Wysocki,
	Alexander Viro

Add a few helpers to deal with signed values integers; built on existing
debugfs internal helpers as the existing unsigned functions already do.

Make the simple_attr_write() internal helper detect the sign of the
requested set operation from the related format string: this is needed
to be able to properly parse negatively signed input strings.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
Note that in the rest of the series I do NOT need the s64 WRITE/SET
operations, that required the more invasive simple_attr_write() change,
but it seemed odd to implement a get only debug_create_s32/64 API.
---
 fs/debugfs/file.c       | 74 +++++++++++++++++++++++++++++++++++++++++
 fs/libfs.c              | 12 +++++--
 include/linux/debugfs.h |  4 +++
 3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 950c63fa4d0b..5363b12c3dcb 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -556,6 +556,80 @@ void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent,
 }
 EXPORT_SYMBOL_GPL(debugfs_create_u64);
 
+static int debugfs_s32_set(void *data, u64 val)
+{
+	*(s32 *)data = val;
+	return 0;
+}
+
+static int debugfs_s32_get(void *data, u64 *val)
+{
+	*val = *(s32 *)data;
+	return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s32, debugfs_s32_get, debugfs_s32_set, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s32_ro, debugfs_s32_get, NULL, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s32_wo, NULL, debugfs_s32_set, "%lld\n");
+
+/**
+ * debugfs_create_s32 - create a debugfs file that is used to read and write an signed 32-bit value
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this parameter is %NULL, then the
+ *          file will be created in the root of the debugfs filesystem.
+ * @value: a pointer to the variable that the file should read to and write
+ *         from.
+ *
+ * This function creates a file in debugfs with the given name that
+ * contains the value of the variable @value.  If the @mode variable is so
+ * set, it can be read from, and written to.
+ */
+void debugfs_create_s32(const char *name, umode_t mode, struct dentry *parent,
+			s32 *value)
+{
+	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_s32,
+				   &fops_s32_ro, &fops_s32_wo);
+}
+EXPORT_SYMBOL_GPL(debugfs_create_s32);
+
+static int debugfs_s64_set(void *data, u64 val)
+{
+	*(s64 *)data = val;
+	return 0;
+}
+
+static int debugfs_s64_get(void *data, u64 *val)
+{
+	*val = *(s64 *)data;
+	return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s64, debugfs_s64_get, debugfs_s64_set, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s64_ro, debugfs_s64_get, NULL, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s64_wo, NULL, debugfs_s64_set, "%lld\n");
+
+/**
+ * debugfs_create_s64 - create a debugfs file that is used to read and write a signed 64-bit value
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this parameter is %NULL, then the
+ *          file will be created in the root of the debugfs filesystem.
+ * @value: a pointer to the variable that the file should read to and write
+ *         from.
+ *
+ * This function creates a file in debugfs with the given name that
+ * contains the value of the variable @value.  If the @mode variable is so
+ * set, it can be read from, and written to.
+ */
+void debugfs_create_s64(const char *name, umode_t mode, struct dentry *parent,
+			s64 *value)
+{
+	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_s64,
+				   &fops_s64_ro, &fops_s64_wo);
+}
+EXPORT_SYMBOL_GPL(debugfs_create_s64);
+
 static int debugfs_ulong_set(void *data, u64 val)
 {
 	*(unsigned long *)data = val;
diff --git a/fs/libfs.c b/fs/libfs.c
index ba7438ab9371..f5a554ed363b 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -917,8 +917,8 @@ EXPORT_SYMBOL(simple_transaction_release);
 struct simple_attr {
 	int (*get)(void *, u64 *);
 	int (*set)(void *, u64);
-	char get_buf[24];	/* enough to store a u64 and "\n\0" */
-	char set_buf[24];
+	char get_buf[25];	/* enough to store a u64, a sign and "\n\0" */
+	char set_buf[25];
 	void *data;
 	const char *fmt;	/* format for read operation */
 	struct mutex mutex;	/* protects access to these buffers */
@@ -1001,6 +1001,7 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
 	unsigned long long val;
 	size_t size;
 	ssize_t ret;
+	char *_fmt;
 
 	attr = file->private_data;
 	if (!attr->set)
@@ -1016,7 +1017,12 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
 		goto out;
 
 	attr->set_buf[size] = '\0';
-	ret = kstrtoull(attr->set_buf, 0, &val);
+	_fmt = strchr(attr->fmt, '%');
+	/* Deduce signedness from read format string specifier */
+	if (_fmt &&  (strchr(_fmt, 'd') || strchr(_fmt, 'i')))
+		ret = kstrtoll(attr->set_buf, 0, (long long *)&val);
+	else
+		ret = kstrtoull(attr->set_buf, 0, &val);
 	if (ret)
 		goto out;
 	ret = attr->set(attr->data, val);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index c869f1e73d75..1b8ea858f261 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -114,6 +114,10 @@ void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent,
 			u64 *value);
 void debugfs_create_ulong(const char *name, umode_t mode, struct dentry *parent,
 			  unsigned long *value);
+void debugfs_create_s32(const char *name, umode_t mode, struct dentry *parent,
+			s32 *value);
+void debugfs_create_s64(const char *name, umode_t mode, struct dentry *parent,
+			s64 *value);
 void debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent,
 		       u8 *value);
 void debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers
@ 2022-02-27 20:55   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:55 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi, Greg Kroah-Hartman, Rafael J. Wysocki,
	Alexander Viro

Add a few helpers to deal with signed values integers; built on existing
debugfs internal helpers as the existing unsigned functions already do.

Make the simple_attr_write() internal helper detect the sign of the
requested set operation from the related format string: this is needed
to be able to properly parse negatively signed input strings.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
Note that in the rest of the series I do NOT need the s64 WRITE/SET
operations, that required the more invasive simple_attr_write() change,
but it seemed odd to implement a get only debug_create_s32/64 API.
---
 fs/debugfs/file.c       | 74 +++++++++++++++++++++++++++++++++++++++++
 fs/libfs.c              | 12 +++++--
 include/linux/debugfs.h |  4 +++
 3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 950c63fa4d0b..5363b12c3dcb 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -556,6 +556,80 @@ void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent,
 }
 EXPORT_SYMBOL_GPL(debugfs_create_u64);
 
+static int debugfs_s32_set(void *data, u64 val)
+{
+	*(s32 *)data = val;
+	return 0;
+}
+
+static int debugfs_s32_get(void *data, u64 *val)
+{
+	*val = *(s32 *)data;
+	return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s32, debugfs_s32_get, debugfs_s32_set, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s32_ro, debugfs_s32_get, NULL, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s32_wo, NULL, debugfs_s32_set, "%lld\n");
+
+/**
+ * debugfs_create_s32 - create a debugfs file that is used to read and write an signed 32-bit value
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this parameter is %NULL, then the
+ *          file will be created in the root of the debugfs filesystem.
+ * @value: a pointer to the variable that the file should read to and write
+ *         from.
+ *
+ * This function creates a file in debugfs with the given name that
+ * contains the value of the variable @value.  If the @mode variable is so
+ * set, it can be read from, and written to.
+ */
+void debugfs_create_s32(const char *name, umode_t mode, struct dentry *parent,
+			s32 *value)
+{
+	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_s32,
+				   &fops_s32_ro, &fops_s32_wo);
+}
+EXPORT_SYMBOL_GPL(debugfs_create_s32);
+
+static int debugfs_s64_set(void *data, u64 val)
+{
+	*(s64 *)data = val;
+	return 0;
+}
+
+static int debugfs_s64_get(void *data, u64 *val)
+{
+	*val = *(s64 *)data;
+	return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s64, debugfs_s64_get, debugfs_s64_set, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s64_ro, debugfs_s64_get, NULL, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s64_wo, NULL, debugfs_s64_set, "%lld\n");
+
+/**
+ * debugfs_create_s64 - create a debugfs file that is used to read and write a signed 64-bit value
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this parameter is %NULL, then the
+ *          file will be created in the root of the debugfs filesystem.
+ * @value: a pointer to the variable that the file should read to and write
+ *         from.
+ *
+ * This function creates a file in debugfs with the given name that
+ * contains the value of the variable @value.  If the @mode variable is so
+ * set, it can be read from, and written to.
+ */
+void debugfs_create_s64(const char *name, umode_t mode, struct dentry *parent,
+			s64 *value)
+{
+	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_s64,
+				   &fops_s64_ro, &fops_s64_wo);
+}
+EXPORT_SYMBOL_GPL(debugfs_create_s64);
+
 static int debugfs_ulong_set(void *data, u64 val)
 {
 	*(unsigned long *)data = val;
diff --git a/fs/libfs.c b/fs/libfs.c
index ba7438ab9371..f5a554ed363b 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -917,8 +917,8 @@ EXPORT_SYMBOL(simple_transaction_release);
 struct simple_attr {
 	int (*get)(void *, u64 *);
 	int (*set)(void *, u64);
-	char get_buf[24];	/* enough to store a u64 and "\n\0" */
-	char set_buf[24];
+	char get_buf[25];	/* enough to store a u64, a sign and "\n\0" */
+	char set_buf[25];
 	void *data;
 	const char *fmt;	/* format for read operation */
 	struct mutex mutex;	/* protects access to these buffers */
@@ -1001,6 +1001,7 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
 	unsigned long long val;
 	size_t size;
 	ssize_t ret;
+	char *_fmt;
 
 	attr = file->private_data;
 	if (!attr->set)
@@ -1016,7 +1017,12 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
 		goto out;
 
 	attr->set_buf[size] = '\0';
-	ret = kstrtoull(attr->set_buf, 0, &val);
+	_fmt = strchr(attr->fmt, '%');
+	/* Deduce signedness from read format string specifier */
+	if (_fmt &&  (strchr(_fmt, 'd') || strchr(_fmt, 'i')))
+		ret = kstrtoll(attr->set_buf, 0, (long long *)&val);
+	else
+		ret = kstrtoull(attr->set_buf, 0, &val);
 	if (ret)
 		goto out;
 	ret = attr->set(attr->data, val);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index c869f1e73d75..1b8ea858f261 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -114,6 +114,10 @@ void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent,
 			u64 *value);
 void debugfs_create_ulong(const char *name, umode_t mode, struct dentry *parent,
 			  unsigned long *value);
+void debugfs_create_s32(const char *name, umode_t mode, struct dentry *parent,
+			s32 *value);
+void debugfs_create_s64(const char *name, umode_t mode, struct dentry *parent,
+			s64 *value);
 void debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent,
 		       u8 *value);
 void debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent,
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 08/16] firmware: arm_scmi: Add SCMI Testing driver
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:56   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add an SCMI driver that would expose all of the available SCMI protocol
operations and resources under a debugfs rooted at /sys/kernel/debug/scmi,
so as to be then able to script generic SCMI testcases simply accessing the
available debugfs entries.

The aim is to be able to test the Kernel SCMI stack in isolation without
the constraints or interferences carried by the original SCMI drivers that
by their nature belong and are driven by a number of Kernel subsystems:
indeed, if this testing driver is enabled at compilation time, loading of
all the other regular SCMI drivers is inhibited.

Beside such generic SCMI test driver infrastructure, add also basic support
for testing SCMI Clock protocol.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 Documentation/ABI/testing/debugfs-scmi        | 101 ++++++++++++
 drivers/firmware/arm_scmi/Kconfig             |  12 ++
 drivers/firmware/arm_scmi/Makefile            |   2 +
 drivers/firmware/arm_scmi/driver.c            |   9 +
 .../arm_scmi/scmi_test_driver/Makefile        |   4 +
 .../arm_scmi/scmi_test_driver/scmi_test.c     | 154 ++++++++++++++++++
 .../arm_scmi/scmi_test_driver/test_clocks.c   | 139 ++++++++++++++++
 .../arm_scmi/scmi_test_driver/test_common.c   |  60 +++++++
 .../arm_scmi/scmi_test_driver/test_common.h   |  76 +++++++++
 9 files changed, 557 insertions(+)
 create mode 100644 Documentation/ABI/testing/debugfs-scmi
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/Makefile
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.h

diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/testing/debugfs-scmi
new file mode 100644
index 000000000000..85177f3723c8
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-scmi
@@ -0,0 +1,101 @@
+What:		/sys/kernel/debug/scmi/info/major_ver
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack major version
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/minor_ver
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack minor version
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/impl_ver
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack (vendor-specific) implementation version
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/vendor_id
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack vendor identifier ASCII string
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/sub_vendor_id
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack sub_vendor identifier ASCII string
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/num_agents
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	Number of detected SCMI agents on the system
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/num_protocols
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	Number of detected SCMI protocols implemented on the system
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/transport/compatible
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	Name of the configured underlying SCMI transport identified
+		using the same compatible strings as defined in the bindings
+		at Documentation/devicetree/bindings/firmware/arm,scmi.yaml
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/transport/is_atomic
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	A boolen flag that states if the underlying SCMI transport
+		currently used is configured to support atomic mode of
+		operation.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/transport/max_rx_timeout_ms
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	Represents the timeout, as configured in the underlying SCMI
+		transport, that is enforced while waiting for SCMI synchronous
+		command replies.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/transport/atomic_threshold_us
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	System wide threshold optionally used to decide if honour or not
+		SCMI atomic transactions requests; its usage is described in
+		Documentation/devicetree/bindings/firmware/arm,scmi.yaml
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x<NN>/version
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Protocol 0x<NN> version implemented on this system
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/info/*
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol informational RO data for clock resource
+		with id <XXX>: each entry under info/ subdir maps to an equally
+		named field of struct scmi_clock_info as documented in
+		include/scmi/protocol.h
+Users:		KSelftest, Debugging
diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
index 7794bd41eaa0..a3726074c89e 100644
--- a/drivers/firmware/arm_scmi/Kconfig
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -148,4 +148,16 @@ config ARM_SCMI_POWER_DOMAIN
 	  will be called scmi_pm_domain. Note this may needed early in boot
 	  before rootfs may be available.
 
+config ARM_SCMI_TEST_DRIVER
+	tristate "SCMI Testing driver"
+	depends on (ARM_SCMI_PROTOCOL && DEBUG_FS) || (COMPILE_TEST && OF)
+	help
+	  This enables support for an SCMI testing driver.
+	  Note that this driver will register as an SCMI driver user for
+	  all SCMI standard protocols and at the same time will inhibit
+	  the registration of any of regular SCMI drivers.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called scmi_test_driver.
+
 endmenu
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 8d4afadda38c..8382a5da9e39 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -13,6 +13,8 @@ scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \
 obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o
 obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
 
+obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver/
+
 ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
 # The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame
 # pointer in Thumb2 mode, which is forcibly enabled by Clang when profiling
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 8c5429529946..8c4706b24368 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1782,6 +1782,15 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 	pr_debug("Requesting SCMI device (%s) for protocol %x\n",
 		 id_table->name, id_table->protocol_id);
 
+#if IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER)
+	/* Reject non-testing SCMI drivers */
+	if (strncmp(id_table->name, "__scmi_test", strlen("__scmi_test"))) {
+		pr_warn("SCMI Test driver loaded. Rejecting '%s'/0x%X\n",
+			id_table->name, id_table->protocol_id);
+		return -EINVAL;
+	}
+#endif
+
 	/*
 	 * Search for the matching protocol rdev list and then search
 	 * of any existent equally named device...fails if any duplicate found.
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
new file mode 100644
index 000000000000..6e3ddd177827
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o
+obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
+
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
new file mode 100644
index 000000000000..f99aa621684c
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver.
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+
+#include "test_common.h"
+
+static struct dentry *scmi_dentry, *scmi_info_dentry, *scmi_trans_dentry;
+DEFINE_MUTEX(scmi_test_mtx);
+
+static
+int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
+	[SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
+};
+
+static void
+scmi_debugfs_common_info_create(struct scmi_revision_info *info,
+				struct dentry *parent)
+{
+	debugfs_create_u16("major_ver", 0400, parent, &info->major_ver);
+	debugfs_create_u16("minor_ver", 0400, parent, &info->minor_ver);
+	debugfs_create_u8("num_protocols", 0400, parent,
+			  &info->num_protocols);
+	debugfs_create_u8("num_agents", 0400, parent, &info->num_agents);
+	debugfs_create_x32("impl_ver", 0400, parent, &info->impl_ver);
+
+	debugfs_create_file("vendor_id", 0400, parent,
+			    info->vendor_id, &scmi_test_string_file_fops);
+	debugfs_create_file("sub_vendor_id", 0400, parent,
+			    info->sub_vendor_id, &scmi_test_string_file_fops);
+}
+
+static void
+scmi_debugfs_trans_info_create(struct scmi_transport_info *info,
+			       struct dentry *parent)
+{
+	debugfs_create_file("compatible", 0400, parent,
+			    (void *)info->compatible,
+			    &scmi_test_string_file_fops);
+	debugfs_create_bool("is_atomic", 0400, parent, &info->is_atomic);
+	debugfs_create_u32("atomic_threshold_us", 0400, parent,
+			   &info->atomic_threshold_us);
+	debugfs_create_u32("max_rx_timeout_ms", 0400, parent,
+			   &info->max_rx_timeout_ms);
+}
+
+static int scmi_testing_probe(struct scmi_device *sdev)
+{
+	int ret;
+	const void *ops;
+	struct scmi_protocol_handle *ph;
+	const struct scmi_handle *handle = sdev->handle;
+	struct device *dev = &sdev->dev;
+	struct scmi_test_setup *tsp;
+	char proto_dir[16];
+
+	if (!handle)
+		return -ENODEV;
+
+	if (sdev->protocol_id > SCMI_PROTOCOL_LAST ||
+	    !scmi_test_init[sdev->protocol_id]) {
+		dev_warn(dev, "Testing protocol 0x%X NOT supported.\n",
+			 sdev->protocol_id);
+		return -EINVAL;
+	}
+
+	ops = handle->devm_protocol_get(sdev, sdev->protocol_id, &ph);
+	if (IS_ERR(ops)) {
+		dev_err(dev, "Cannot access protocol:0x%X - err:%ld\n",
+			sdev->protocol_id, PTR_ERR(ops));
+		return PTR_ERR(ops);
+	}
+
+	tsp = devm_kzalloc(&sdev->dev, sizeof(*tsp), GFP_KERNEL);
+	if (!tsp)
+		return -ENOMEM;
+
+	tsp->sdev = sdev;
+	tsp->ops = ops;
+	tsp->ph = ph;
+
+	snprintf(proto_dir, 16, "protocol_0x%02X", sdev->protocol_id);
+	tsp->parent = debugfs_create_dir(proto_dir, scmi_dentry);
+	if (IS_ERR(tsp->parent))
+		return PTR_ERR(tsp->parent);
+
+	ret = scmi_test_init[sdev->protocol_id](tsp);
+	if (ret)
+		return ret;
+
+	/* Setup common information entries if not already done */
+	mutex_lock(&scmi_test_mtx);
+	if (!scmi_info_dentry) {
+		scmi_info_dentry = debugfs_create_dir("info", scmi_dentry);
+		if (!IS_ERR(scmi_info_dentry))
+			scmi_debugfs_common_info_create(sdev->handle->version,
+							scmi_info_dentry);
+	}
+
+	if (!scmi_trans_dentry) {
+		scmi_trans_dentry =
+			debugfs_create_dir("transport", scmi_dentry);
+		if (!IS_ERR(scmi_trans_dentry))
+			scmi_debugfs_trans_info_create(sdev->handle->transport,
+						       scmi_trans_dentry);
+	}
+	mutex_unlock(&scmi_test_mtx);
+
+	return ret;
+}
+
+static const struct scmi_device_id scmi_id_table[] = {
+	{ SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
+	{ },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_id_table);
+
+static struct scmi_driver scmi_testing_driver = {
+	.name = "scmi-testing-driver",
+	.probe = scmi_testing_probe,
+	.id_table = scmi_id_table,
+};
+
+static int __init scmi_testing_driver_init(void)
+{
+	scmi_dentry = debugfs_create_dir("scmi", NULL);
+	return scmi_driver_register(&scmi_testing_driver,
+				    THIS_MODULE, KBUILD_MODNAME);
+}
+module_init(scmi_testing_driver_init);
+
+static void __exit scmi_testing_driver_exit(void)
+{
+	debugfs_remove_recursive(scmi_dentry);
+	scmi_driver_unregister(&scmi_testing_driver);
+}
+module_exit(scmi_testing_driver_exit);
+
+MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI Testing Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
new file mode 100644
index 000000000000..3b9e92baa509
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver - Clock Protocol
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+
+#include "test_common.h"
+
+/* Clock Proto Test */
+struct scmi_clock_data {
+	unsigned int version;
+	int count;
+	const struct scmi_clock_info **clk_info;
+};
+
+static ssize_t scmi_test_clock_rates_read(struct file *filp, char __user *buf,
+					  size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		int c;
+		struct scmi_clock_info *ci = filp->f_inode->i_private;
+
+		for (c = 0; c < ci->list.num_rates; c++)
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used,
+						"%lld ",
+						ci->list.rates[c]);
+
+		data->used += scnprintf(data->buf + data->used,
+					data->len - data->used, "\n");
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static const struct file_operations test_clk_rates_fops = {
+	.open = scmi_test_fixed_buffer_open,
+	.release = scmi_test_release,
+	.read = scmi_test_clock_rates_read,
+};
+
+static void
+scmi_test_debugfs_clock_info_create(const struct scmi_clock_info *ci,
+				    struct dentry *top_dentry)
+{
+	struct dentry *parent;
+	struct scmi_clock_info *cinfo = (struct scmi_clock_info *)ci;
+
+	parent = debugfs_create_dir("info", top_dentry);
+	if (IS_ERR(parent))
+		return;
+
+	debugfs_create_file("name", 0400, parent, cinfo->name,
+			    &scmi_test_string_file_fops);
+	debugfs_create_u32("enable_latency", 0400, parent,
+			   &cinfo->enable_latency);
+
+	debugfs_create_bool("rate_discrete", 0400, parent,
+			    &cinfo->rate_discrete);
+
+	if (cinfo->rate_discrete) {
+		debugfs_create_u32("num_rates", 0400, parent,
+				   &cinfo->list.num_rates);
+		debugfs_create_file("rates", 0400, parent, cinfo,
+				    &test_clk_rates_fops);
+	} else {
+		debugfs_create_u64("min_rate", 0400, parent,
+				   &cinfo->range.min_rate);
+		debugfs_create_u64("max_rate", 0400, parent,
+				   &cinfo->range.max_rate);
+		debugfs_create_u64("step_size", 0400, parent,
+				   &cinfo->range.step_size);
+	}
+}
+
+int scmi_test_clock_init(struct scmi_test_setup *tsp)
+{
+	int i;
+	struct scmi_clock_data *cdata;
+	const struct scmi_clk_proto_ops *clock_ops;
+	struct device *dev = &tsp->sdev->dev;
+
+	cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
+	if (!cdata)
+		return -ENOMEM;
+
+	clock_ops = tsp->ops;
+	cdata->version = clock_ops->version_get(tsp->ph);
+	cdata->count = clock_ops->count_get(tsp->ph);
+
+	if (cdata->count <= 0) {
+		dev_err(dev, "number of domains invalid: %d\n",
+			cdata->count);
+		return cdata->count ?: -EINVAL;
+	}
+
+	cdata->clk_info = devm_kcalloc(dev, cdata->count,
+				       sizeof(cdata->clk_info), GFP_KERNEL);
+	if (!cdata->clk_info)
+		return -ENOMEM;
+
+	for (i = 0; i < cdata->count; i++)
+		cdata->clk_info[i] = clock_ops->info_get(tsp->ph, i);
+
+	tsp->priv = cdata;
+
+	debugfs_create_x32("version", 0400, tsp->parent, &cdata->version);
+
+	dev_info(dev, "Found %d clock resources.\n", cdata->count);
+
+	for (i = 0; i < cdata->count; i++) {
+		char clock_dir[16];
+		struct dentry *clock_dentry;
+
+		snprintf(clock_dir, 16, "%03d", i);
+		clock_dentry = debugfs_create_dir(clock_dir, tsp->parent);
+		if (!IS_ERR(clock_dentry))
+			scmi_test_debugfs_clock_info_create(cdata->clk_info[i],
+							    clock_dentry);
+	}
+
+	return 0;
+}
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
new file mode 100644
index 000000000000..1a4b6aa35095
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver.
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/kstrtox.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+
+#include "test_common.h"
+
+/* Common File operations */
+int scmi_test_release(struct inode *ino, struct file *filp)
+{
+	kfree(filp->private_data);
+
+	return 0;
+}
+
+int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp)
+{
+	struct scmi_test_buffer *data;
+
+	data = kzalloc(sizeof(*data) + SCMI_TEST_DEFAULT_BUF_SZ, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->len = SCMI_TEST_DEFAULT_BUF_SZ;
+	filp->private_data = data;
+
+	return 0;
+}
+
+static ssize_t scmi_test_string_file_read(struct file *filp, char __user *buf,
+					  size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		char *str = filp->f_inode->i_private;
+
+		data->used = scnprintf(data->buf, data->len, "%s\n", str);
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+const struct file_operations scmi_test_string_file_fops = {
+	.open = scmi_test_fixed_buffer_open,
+	.release = scmi_test_release,
+	.read = scmi_test_string_file_read,
+};
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
new file mode 100644
index 000000000000..1ff5bbc32ae3
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * SCMI Testing Driver.
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#ifndef __SCMI_TEST_COMMON_H
+#define __SCMI_TEST_COMMON_H
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+/**
+ * struct scmi_test_setup  - Test protocol setup descriptor
+ * @parent: A reference to the parent dentry
+ * @sdev: A reference to the related SCMI device
+ * @ops: A reference to the protocol ops
+ * @ph: A reference to the protocol handle to be used with the ops
+ * @blen: An optional minimum requested buffer length for output data; if zero
+ *	  the output test buffer is allocated of SCMI_TEST_DEFAULT_BUF_SZ bytes.
+ * @priv: A reference to optional protocol-specific data
+ * @n_priv: A reference to optional protocol-specific data needed by
+ *	    notifications
+ *
+ * This descriptor is created and initialized once per protocol in the
+ * main probe function and passed down to the testing protocol initialization
+ * functions where can be further customized before being optionally made
+ * available to the specific debugfs entries via inode i_private reference.
+ */
+struct scmi_test_setup {
+	struct dentry *parent;
+	struct scmi_device *sdev;
+	const void *ops;
+	struct scmi_protocol_handle *ph;
+	size_t blen;
+	void *priv;
+	void *n_priv;
+};
+
+/**
+ * struct scmi_test_buffer  - Output test buffer descriptor
+ * @id: An optional resource id parsed at open from the debugfs entry name
+ * @len: Size of the allocated buffer len as pointed by @buf
+ * @used: Current number of used bytes in @buf
+ * @buf: Actual buffer for output data: default allocation size (@len), if not
+ * otherwise specified in scmi_test_setup.blen, is SCMI_TEST_DEFAULT_BUF_SZ.
+ *
+ * This describes a dynamically allocated output buffer which will be made
+ * available to each r/w debugfs entry file_operations.
+ */
+struct scmi_test_buffer {
+	unsigned int id;
+	size_t len;
+	size_t used;
+#define SCMI_TEST_DEFAULT_BUF_SZ	64
+	unsigned char buf[];
+};
+
+extern const struct file_operations scmi_test_string_file_fops;
+
+int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp);
+int scmi_test_release(struct inode *ino, struct file *filp);
+
+int scmi_test_clock_init(struct scmi_test_setup *tsp);
+
+#endif /* __SCMI_TEST_COMMON_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 08/16] firmware: arm_scmi: Add SCMI Testing driver
@ 2022-02-27 20:56   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add an SCMI driver that would expose all of the available SCMI protocol
operations and resources under a debugfs rooted at /sys/kernel/debug/scmi,
so as to be then able to script generic SCMI testcases simply accessing the
available debugfs entries.

The aim is to be able to test the Kernel SCMI stack in isolation without
the constraints or interferences carried by the original SCMI drivers that
by their nature belong and are driven by a number of Kernel subsystems:
indeed, if this testing driver is enabled at compilation time, loading of
all the other regular SCMI drivers is inhibited.

Beside such generic SCMI test driver infrastructure, add also basic support
for testing SCMI Clock protocol.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 Documentation/ABI/testing/debugfs-scmi        | 101 ++++++++++++
 drivers/firmware/arm_scmi/Kconfig             |  12 ++
 drivers/firmware/arm_scmi/Makefile            |   2 +
 drivers/firmware/arm_scmi/driver.c            |   9 +
 .../arm_scmi/scmi_test_driver/Makefile        |   4 +
 .../arm_scmi/scmi_test_driver/scmi_test.c     | 154 ++++++++++++++++++
 .../arm_scmi/scmi_test_driver/test_clocks.c   | 139 ++++++++++++++++
 .../arm_scmi/scmi_test_driver/test_common.c   |  60 +++++++
 .../arm_scmi/scmi_test_driver/test_common.h   |  76 +++++++++
 9 files changed, 557 insertions(+)
 create mode 100644 Documentation/ABI/testing/debugfs-scmi
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/Makefile
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_common.h

diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/testing/debugfs-scmi
new file mode 100644
index 000000000000..85177f3723c8
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-scmi
@@ -0,0 +1,101 @@
+What:		/sys/kernel/debug/scmi/info/major_ver
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack major version
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/minor_ver
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack minor version
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/impl_ver
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack (vendor-specific) implementation version
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/vendor_id
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack vendor identifier ASCII string
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/sub_vendor_id
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI protocol stack sub_vendor identifier ASCII string
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/num_agents
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	Number of detected SCMI agents on the system
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/info/num_protocols
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	Number of detected SCMI protocols implemented on the system
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/transport/compatible
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	Name of the configured underlying SCMI transport identified
+		using the same compatible strings as defined in the bindings
+		at Documentation/devicetree/bindings/firmware/arm,scmi.yaml
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/transport/is_atomic
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	A boolen flag that states if the underlying SCMI transport
+		currently used is configured to support atomic mode of
+		operation.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/transport/max_rx_timeout_ms
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	Represents the timeout, as configured in the underlying SCMI
+		transport, that is enforced while waiting for SCMI synchronous
+		command replies.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/transport/atomic_threshold_us
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	System wide threshold optionally used to decide if honour or not
+		SCMI atomic transactions requests; its usage is described in
+		Documentation/devicetree/bindings/firmware/arm,scmi.yaml
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x<NN>/version
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Protocol 0x<NN> version implemented on this system
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/info/*
+Date:		Feb 2022
+KernelVersion:	5.18
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol informational RO data for clock resource
+		with id <XXX>: each entry under info/ subdir maps to an equally
+		named field of struct scmi_clock_info as documented in
+		include/scmi/protocol.h
+Users:		KSelftest, Debugging
diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
index 7794bd41eaa0..a3726074c89e 100644
--- a/drivers/firmware/arm_scmi/Kconfig
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -148,4 +148,16 @@ config ARM_SCMI_POWER_DOMAIN
 	  will be called scmi_pm_domain. Note this may needed early in boot
 	  before rootfs may be available.
 
+config ARM_SCMI_TEST_DRIVER
+	tristate "SCMI Testing driver"
+	depends on (ARM_SCMI_PROTOCOL && DEBUG_FS) || (COMPILE_TEST && OF)
+	help
+	  This enables support for an SCMI testing driver.
+	  Note that this driver will register as an SCMI driver user for
+	  all SCMI standard protocols and at the same time will inhibit
+	  the registration of any of regular SCMI drivers.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called scmi_test_driver.
+
 endmenu
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 8d4afadda38c..8382a5da9e39 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -13,6 +13,8 @@ scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \
 obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o
 obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
 
+obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver/
+
 ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
 # The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame
 # pointer in Thumb2 mode, which is forcibly enabled by Clang when profiling
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 8c5429529946..8c4706b24368 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1782,6 +1782,15 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 	pr_debug("Requesting SCMI device (%s) for protocol %x\n",
 		 id_table->name, id_table->protocol_id);
 
+#if IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER)
+	/* Reject non-testing SCMI drivers */
+	if (strncmp(id_table->name, "__scmi_test", strlen("__scmi_test"))) {
+		pr_warn("SCMI Test driver loaded. Rejecting '%s'/0x%X\n",
+			id_table->name, id_table->protocol_id);
+		return -EINVAL;
+	}
+#endif
+
 	/*
 	 * Search for the matching protocol rdev list and then search
 	 * of any existent equally named device...fails if any duplicate found.
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
new file mode 100644
index 000000000000..6e3ddd177827
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o
+obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
+
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
new file mode 100644
index 000000000000..f99aa621684c
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver.
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+
+#include "test_common.h"
+
+static struct dentry *scmi_dentry, *scmi_info_dentry, *scmi_trans_dentry;
+DEFINE_MUTEX(scmi_test_mtx);
+
+static
+int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
+	[SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
+};
+
+static void
+scmi_debugfs_common_info_create(struct scmi_revision_info *info,
+				struct dentry *parent)
+{
+	debugfs_create_u16("major_ver", 0400, parent, &info->major_ver);
+	debugfs_create_u16("minor_ver", 0400, parent, &info->minor_ver);
+	debugfs_create_u8("num_protocols", 0400, parent,
+			  &info->num_protocols);
+	debugfs_create_u8("num_agents", 0400, parent, &info->num_agents);
+	debugfs_create_x32("impl_ver", 0400, parent, &info->impl_ver);
+
+	debugfs_create_file("vendor_id", 0400, parent,
+			    info->vendor_id, &scmi_test_string_file_fops);
+	debugfs_create_file("sub_vendor_id", 0400, parent,
+			    info->sub_vendor_id, &scmi_test_string_file_fops);
+}
+
+static void
+scmi_debugfs_trans_info_create(struct scmi_transport_info *info,
+			       struct dentry *parent)
+{
+	debugfs_create_file("compatible", 0400, parent,
+			    (void *)info->compatible,
+			    &scmi_test_string_file_fops);
+	debugfs_create_bool("is_atomic", 0400, parent, &info->is_atomic);
+	debugfs_create_u32("atomic_threshold_us", 0400, parent,
+			   &info->atomic_threshold_us);
+	debugfs_create_u32("max_rx_timeout_ms", 0400, parent,
+			   &info->max_rx_timeout_ms);
+}
+
+static int scmi_testing_probe(struct scmi_device *sdev)
+{
+	int ret;
+	const void *ops;
+	struct scmi_protocol_handle *ph;
+	const struct scmi_handle *handle = sdev->handle;
+	struct device *dev = &sdev->dev;
+	struct scmi_test_setup *tsp;
+	char proto_dir[16];
+
+	if (!handle)
+		return -ENODEV;
+
+	if (sdev->protocol_id > SCMI_PROTOCOL_LAST ||
+	    !scmi_test_init[sdev->protocol_id]) {
+		dev_warn(dev, "Testing protocol 0x%X NOT supported.\n",
+			 sdev->protocol_id);
+		return -EINVAL;
+	}
+
+	ops = handle->devm_protocol_get(sdev, sdev->protocol_id, &ph);
+	if (IS_ERR(ops)) {
+		dev_err(dev, "Cannot access protocol:0x%X - err:%ld\n",
+			sdev->protocol_id, PTR_ERR(ops));
+		return PTR_ERR(ops);
+	}
+
+	tsp = devm_kzalloc(&sdev->dev, sizeof(*tsp), GFP_KERNEL);
+	if (!tsp)
+		return -ENOMEM;
+
+	tsp->sdev = sdev;
+	tsp->ops = ops;
+	tsp->ph = ph;
+
+	snprintf(proto_dir, 16, "protocol_0x%02X", sdev->protocol_id);
+	tsp->parent = debugfs_create_dir(proto_dir, scmi_dentry);
+	if (IS_ERR(tsp->parent))
+		return PTR_ERR(tsp->parent);
+
+	ret = scmi_test_init[sdev->protocol_id](tsp);
+	if (ret)
+		return ret;
+
+	/* Setup common information entries if not already done */
+	mutex_lock(&scmi_test_mtx);
+	if (!scmi_info_dentry) {
+		scmi_info_dentry = debugfs_create_dir("info", scmi_dentry);
+		if (!IS_ERR(scmi_info_dentry))
+			scmi_debugfs_common_info_create(sdev->handle->version,
+							scmi_info_dentry);
+	}
+
+	if (!scmi_trans_dentry) {
+		scmi_trans_dentry =
+			debugfs_create_dir("transport", scmi_dentry);
+		if (!IS_ERR(scmi_trans_dentry))
+			scmi_debugfs_trans_info_create(sdev->handle->transport,
+						       scmi_trans_dentry);
+	}
+	mutex_unlock(&scmi_test_mtx);
+
+	return ret;
+}
+
+static const struct scmi_device_id scmi_id_table[] = {
+	{ SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
+	{ },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_id_table);
+
+static struct scmi_driver scmi_testing_driver = {
+	.name = "scmi-testing-driver",
+	.probe = scmi_testing_probe,
+	.id_table = scmi_id_table,
+};
+
+static int __init scmi_testing_driver_init(void)
+{
+	scmi_dentry = debugfs_create_dir("scmi", NULL);
+	return scmi_driver_register(&scmi_testing_driver,
+				    THIS_MODULE, KBUILD_MODNAME);
+}
+module_init(scmi_testing_driver_init);
+
+static void __exit scmi_testing_driver_exit(void)
+{
+	debugfs_remove_recursive(scmi_dentry);
+	scmi_driver_unregister(&scmi_testing_driver);
+}
+module_exit(scmi_testing_driver_exit);
+
+MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI Testing Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
new file mode 100644
index 000000000000..3b9e92baa509
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver - Clock Protocol
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+
+#include "test_common.h"
+
+/* Clock Proto Test */
+struct scmi_clock_data {
+	unsigned int version;
+	int count;
+	const struct scmi_clock_info **clk_info;
+};
+
+static ssize_t scmi_test_clock_rates_read(struct file *filp, char __user *buf,
+					  size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		int c;
+		struct scmi_clock_info *ci = filp->f_inode->i_private;
+
+		for (c = 0; c < ci->list.num_rates; c++)
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used,
+						"%lld ",
+						ci->list.rates[c]);
+
+		data->used += scnprintf(data->buf + data->used,
+					data->len - data->used, "\n");
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static const struct file_operations test_clk_rates_fops = {
+	.open = scmi_test_fixed_buffer_open,
+	.release = scmi_test_release,
+	.read = scmi_test_clock_rates_read,
+};
+
+static void
+scmi_test_debugfs_clock_info_create(const struct scmi_clock_info *ci,
+				    struct dentry *top_dentry)
+{
+	struct dentry *parent;
+	struct scmi_clock_info *cinfo = (struct scmi_clock_info *)ci;
+
+	parent = debugfs_create_dir("info", top_dentry);
+	if (IS_ERR(parent))
+		return;
+
+	debugfs_create_file("name", 0400, parent, cinfo->name,
+			    &scmi_test_string_file_fops);
+	debugfs_create_u32("enable_latency", 0400, parent,
+			   &cinfo->enable_latency);
+
+	debugfs_create_bool("rate_discrete", 0400, parent,
+			    &cinfo->rate_discrete);
+
+	if (cinfo->rate_discrete) {
+		debugfs_create_u32("num_rates", 0400, parent,
+				   &cinfo->list.num_rates);
+		debugfs_create_file("rates", 0400, parent, cinfo,
+				    &test_clk_rates_fops);
+	} else {
+		debugfs_create_u64("min_rate", 0400, parent,
+				   &cinfo->range.min_rate);
+		debugfs_create_u64("max_rate", 0400, parent,
+				   &cinfo->range.max_rate);
+		debugfs_create_u64("step_size", 0400, parent,
+				   &cinfo->range.step_size);
+	}
+}
+
+int scmi_test_clock_init(struct scmi_test_setup *tsp)
+{
+	int i;
+	struct scmi_clock_data *cdata;
+	const struct scmi_clk_proto_ops *clock_ops;
+	struct device *dev = &tsp->sdev->dev;
+
+	cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
+	if (!cdata)
+		return -ENOMEM;
+
+	clock_ops = tsp->ops;
+	cdata->version = clock_ops->version_get(tsp->ph);
+	cdata->count = clock_ops->count_get(tsp->ph);
+
+	if (cdata->count <= 0) {
+		dev_err(dev, "number of domains invalid: %d\n",
+			cdata->count);
+		return cdata->count ?: -EINVAL;
+	}
+
+	cdata->clk_info = devm_kcalloc(dev, cdata->count,
+				       sizeof(cdata->clk_info), GFP_KERNEL);
+	if (!cdata->clk_info)
+		return -ENOMEM;
+
+	for (i = 0; i < cdata->count; i++)
+		cdata->clk_info[i] = clock_ops->info_get(tsp->ph, i);
+
+	tsp->priv = cdata;
+
+	debugfs_create_x32("version", 0400, tsp->parent, &cdata->version);
+
+	dev_info(dev, "Found %d clock resources.\n", cdata->count);
+
+	for (i = 0; i < cdata->count; i++) {
+		char clock_dir[16];
+		struct dentry *clock_dentry;
+
+		snprintf(clock_dir, 16, "%03d", i);
+		clock_dentry = debugfs_create_dir(clock_dir, tsp->parent);
+		if (!IS_ERR(clock_dentry))
+			scmi_test_debugfs_clock_info_create(cdata->clk_info[i],
+							    clock_dentry);
+	}
+
+	return 0;
+}
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
new file mode 100644
index 000000000000..1a4b6aa35095
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver.
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/kstrtox.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+
+#include "test_common.h"
+
+/* Common File operations */
+int scmi_test_release(struct inode *ino, struct file *filp)
+{
+	kfree(filp->private_data);
+
+	return 0;
+}
+
+int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp)
+{
+	struct scmi_test_buffer *data;
+
+	data = kzalloc(sizeof(*data) + SCMI_TEST_DEFAULT_BUF_SZ, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->len = SCMI_TEST_DEFAULT_BUF_SZ;
+	filp->private_data = data;
+
+	return 0;
+}
+
+static ssize_t scmi_test_string_file_read(struct file *filp, char __user *buf,
+					  size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		char *str = filp->f_inode->i_private;
+
+		data->used = scnprintf(data->buf, data->len, "%s\n", str);
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+const struct file_operations scmi_test_string_file_fops = {
+	.open = scmi_test_fixed_buffer_open,
+	.release = scmi_test_release,
+	.read = scmi_test_string_file_read,
+};
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
new file mode 100644
index 000000000000..1ff5bbc32ae3
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * SCMI Testing Driver.
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#ifndef __SCMI_TEST_COMMON_H
+#define __SCMI_TEST_COMMON_H
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+/**
+ * struct scmi_test_setup  - Test protocol setup descriptor
+ * @parent: A reference to the parent dentry
+ * @sdev: A reference to the related SCMI device
+ * @ops: A reference to the protocol ops
+ * @ph: A reference to the protocol handle to be used with the ops
+ * @blen: An optional minimum requested buffer length for output data; if zero
+ *	  the output test buffer is allocated of SCMI_TEST_DEFAULT_BUF_SZ bytes.
+ * @priv: A reference to optional protocol-specific data
+ * @n_priv: A reference to optional protocol-specific data needed by
+ *	    notifications
+ *
+ * This descriptor is created and initialized once per protocol in the
+ * main probe function and passed down to the testing protocol initialization
+ * functions where can be further customized before being optionally made
+ * available to the specific debugfs entries via inode i_private reference.
+ */
+struct scmi_test_setup {
+	struct dentry *parent;
+	struct scmi_device *sdev;
+	const void *ops;
+	struct scmi_protocol_handle *ph;
+	size_t blen;
+	void *priv;
+	void *n_priv;
+};
+
+/**
+ * struct scmi_test_buffer  - Output test buffer descriptor
+ * @id: An optional resource id parsed at open from the debugfs entry name
+ * @len: Size of the allocated buffer len as pointed by @buf
+ * @used: Current number of used bytes in @buf
+ * @buf: Actual buffer for output data: default allocation size (@len), if not
+ * otherwise specified in scmi_test_setup.blen, is SCMI_TEST_DEFAULT_BUF_SZ.
+ *
+ * This describes a dynamically allocated output buffer which will be made
+ * available to each r/w debugfs entry file_operations.
+ */
+struct scmi_test_buffer {
+	unsigned int id;
+	size_t len;
+	size_t used;
+#define SCMI_TEST_DEFAULT_BUF_SZ	64
+	unsigned char buf[];
+};
+
+extern const struct file_operations scmi_test_string_file_fops;
+
+int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp);
+int scmi_test_release(struct inode *ino, struct file *filp);
+
+int scmi_test_clock_init(struct scmi_test_setup *tsp);
+
+#endif /* __SCMI_TEST_COMMON_H */
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 09/16] firmware: arm_scmi: testing: Add Clock protocol full support
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:56   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add SCMI Clock protocol testing support exposing SCMI Clock protocol
operations under debugfs /sys/kernel/debug/scmi/protocol_0x14/<XXX>/, where
the subdirectories <XXX> represents each a distinct clock resource with
ID equal <XXX>.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 Documentation/ABI/testing/debugfs-scmi        |  56 +++++++
 .../arm_scmi/scmi_test_driver/test_clocks.c   | 150 +++++++++++++++++-
 .../arm_scmi/scmi_test_driver/test_common.c   |  48 ++++++
 .../arm_scmi/scmi_test_driver/test_common.h   |   1 +
 4 files changed, 254 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/testing/debugfs-scmi
index 85177f3723c8..e91c19e7a323 100644
--- a/Documentation/ABI/testing/debugfs-scmi
+++ b/Documentation/ABI/testing/debugfs-scmi
@@ -99,3 +99,59 @@ Description:	SCMI Clock Protocol informational RO data for clock resource
 		named field of struct scmi_clock_info as documented in
 		include/scmi/protocol.h
 Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/rate_get_set
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol rate get/set operation for clock resource
+		with id <XXX>; a read returns the currently set clock rate value
+		as a base-10 integer while the write of a base-10 integer sets a
+		new clock rate value.
+		Each R/W access invokes the corresponding SCMI Clock protocol
+		operations and issuing of needed SCMI commands.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/enable
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol enable operation for clock resource with id
+		<XXX>; writing a boolean value causes that specific clock to be
+		enabled or disabled.
+		No reference counting is kept: each write access invokes the
+		corresponding SCMI Clock protocol operations and issuing of
+		needed SCMI commands.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/enable_atomic_irqs_on
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol enable atomic operation for clock resource
+		with id <XXX>; writing a boolean value causes that specific
+		clock to be enabled or disabled using SCMI transport in polling
+		mode, if allowed by the underlying SCMI transport.
+		No reference counting is kept: each write access invokes the
+		corresponding SCMI Clock protocol operations and issuing of
+		needed SCMI commands.
+		Available only if the underlying SCMI transport is atomic
+		capable (/sys/kernel/debug/scmi/transport/is_atomic is True).
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/enable_atomic_irqs_off
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol enable atomic operation for clock resource
+		with id <XXX>; writing a boolean value causes that specific
+		clock to be enabled or disabled using SCMI transport in polling
+		mode, if allowed by the underlying SCMI transport.
+		Local IRQs are disabled while the SCMI command transaction is
+		executed.
+		No reference counting is kept: each write access invokes the
+		corresponding SCMI Clock protocol operations and issuing of
+		needed SCMI commands.
+		Available only if the underlying SCMI transport is atomic
+		capable (/sys/kernel/debug/scmi/transport/is_atomic is True).
+Users:		KSelftest, Debugging
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
index 3b9e92baa509..ae5b1af88f60 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
@@ -24,6 +24,139 @@ struct scmi_clock_data {
 	const struct scmi_clock_info **clk_info;
 };
 
+static ssize_t scmi_test_clk_rate_get_read(struct file *filp, char __user *buf,
+					   size_t count, loff_t *ppos)
+{
+	int ret;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		u64 rate;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_clk_proto_ops *clock_ops = tsp->ops;
+
+		ret = clock_ops->rate_get(tsp->ph, data->id, &rate);
+		if (ret)
+			return ret;
+
+		data->used = scnprintf(data->buf, data->len, "%lld\n", rate);
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static ssize_t scmi_test_clk_rate_get_write(struct file *filp,
+					    const char __user *buf,
+					    size_t count, loff_t *ppos)
+{
+	int ret;
+	u64 rate;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_clk_proto_ops *clock_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtou64_from_user(buf, count, 10, &rate);
+	if (ret < 0)
+		return ret;
+
+	ret = clock_ops->rate_set(tsp->ph, data->id, rate);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_clk_rate_get_set_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_clk_rate_get_read,
+	.write = scmi_test_clk_rate_get_write,
+};
+
+static ssize_t scmi_test_clk_enable_write(struct file *filp,
+					  const char __user *buf,
+					  size_t count, loff_t *ppos)
+{
+	bool enabled, irqs_off;
+	int ret;
+	unsigned long flags;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_clk_proto_ops *clock_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	irqs_off = !strncmp(filp->f_path.dentry->d_name.name,
+			    "enable_atomic_irqs_off",
+			    strlen("enable_atomic_irqs_off"));
+	if (irqs_off)
+		local_irq_save(flags);
+
+	if (enabled)
+		ret = clock_ops->enable_atomic(tsp->ph, data->id);
+	else
+		ret = clock_ops->disable_atomic(tsp->ph, data->id);
+
+	if (irqs_off)
+		local_irq_restore(flags);
+
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_clk_enable_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.write = scmi_test_clk_enable_write,
+};
+
+static ssize_t scmi_test_clk_prepare_enable_write(struct file *filp,
+						  const char __user *buf,
+						  size_t count, loff_t *ppos)
+{
+	bool enabled;
+	int ret;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_clk_proto_ops *clock_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	if (enabled)
+		ret = clock_ops->enable(tsp->ph, data->id);
+	else
+		ret = clock_ops->disable(tsp->ph, data->id);
+
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_clk_prepare_enable_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.write = scmi_test_clk_prepare_enable_write,
+};
+
 static ssize_t scmi_test_clock_rates_read(struct file *filp, char __user *buf,
 					  size_t count, loff_t *ppos)
 {
@@ -130,9 +263,24 @@ int scmi_test_clock_init(struct scmi_test_setup *tsp)
 
 		snprintf(clock_dir, 16, "%03d", i);
 		clock_dentry = debugfs_create_dir(clock_dir, tsp->parent);
-		if (!IS_ERR(clock_dentry))
+		if (!IS_ERR(clock_dentry)) {
 			scmi_test_debugfs_clock_info_create(cdata->clk_info[i],
 							    clock_dentry);
+			debugfs_create_file("rate_get_set", 0600,
+					    clock_dentry, tsp,
+					    &test_clk_rate_get_set_fops);
+			if (tsp->sdev->handle->transport->is_atomic) {
+				debugfs_create_file("enable_atomic_irqs_off",
+						    0200, clock_dentry, tsp,
+						    &test_clk_enable_fops);
+				debugfs_create_file("enable_atomic_irqs_on",
+						    0200, clock_dentry, tsp,
+						    &test_clk_enable_fops);
+			}
+			debugfs_create_file("enable", 0200,
+					    clock_dentry, tsp,
+					    &test_clk_prepare_enable_fops);
+		}
 	}
 
 	return 0;
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
index 1a4b6aa35095..cbe2eec4f2ac 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
@@ -15,6 +15,54 @@
 #include "test_common.h"
 
 /* Common File operations */
+
+/**
+ * scmi_test_setup_open  - A common open helper
+ * @ino: Related inode reference
+ * @filp: Related file pointer reference
+ *
+ * Expects to receive a struct scmi_test_setup via inode i_private reference and
+ * then allocate a properly sized buffer; it also tries to parse the parent
+ * directory name in search for a base10 integer and, if found, stores it into
+ * the buffer descriptor @id field: this comes handy since most of the SCMI
+ * protocol operations and data are bound to some specific SCMI resource id and
+ * the SCMI debugfs directory tree is structured to mirror this layout, so that,
+ * as an example, protocol <NN> would expose <operation_AAA> about its resource
+ * with id <XXX> as:
+ *
+ *	/sys/kernel/debug/scmi/protocol_0x<NN>/<XXX>/<operation_AAA>
+ *
+ * As as result this open would allocate a data buffer, parse the dentry and
+ * set data->id = <XXX>
+ *
+ * Return: 0 on Success
+ */
+int scmi_test_setup_open(struct inode *ino, struct file *filp)
+{
+	unsigned int id;
+	size_t blen;
+	struct scmi_test_buffer *data;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const char *id_str = filp->f_path.dentry->d_parent->d_name.name;
+
+	if (!tsp)
+		return -EINVAL;
+
+	blen = tsp->blen ?: SCMI_TEST_DEFAULT_BUF_SZ;
+	data = kzalloc(sizeof(*data) + blen, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->len = blen;
+	/* Grab clk ID from debugfs entry naming if any */
+	if (!kstrtouint(id_str, 10, &id))
+		data->id = id;
+
+	filp->private_data = data;
+
+	return 0;
+}
+
 int scmi_test_release(struct inode *ino, struct file *filp)
 {
 	kfree(filp->private_data);
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index 1ff5bbc32ae3..3c64cae9fae9 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -68,6 +68,7 @@ struct scmi_test_buffer {
 
 extern const struct file_operations scmi_test_string_file_fops;
 
+int scmi_test_setup_open(struct inode *ino, struct file *filp);
 int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp);
 int scmi_test_release(struct inode *ino, struct file *filp);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 09/16] firmware: arm_scmi: testing: Add Clock protocol full support
@ 2022-02-27 20:56   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add SCMI Clock protocol testing support exposing SCMI Clock protocol
operations under debugfs /sys/kernel/debug/scmi/protocol_0x14/<XXX>/, where
the subdirectories <XXX> represents each a distinct clock resource with
ID equal <XXX>.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 Documentation/ABI/testing/debugfs-scmi        |  56 +++++++
 .../arm_scmi/scmi_test_driver/test_clocks.c   | 150 +++++++++++++++++-
 .../arm_scmi/scmi_test_driver/test_common.c   |  48 ++++++
 .../arm_scmi/scmi_test_driver/test_common.h   |   1 +
 4 files changed, 254 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/testing/debugfs-scmi
index 85177f3723c8..e91c19e7a323 100644
--- a/Documentation/ABI/testing/debugfs-scmi
+++ b/Documentation/ABI/testing/debugfs-scmi
@@ -99,3 +99,59 @@ Description:	SCMI Clock Protocol informational RO data for clock resource
 		named field of struct scmi_clock_info as documented in
 		include/scmi/protocol.h
 Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/rate_get_set
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol rate get/set operation for clock resource
+		with id <XXX>; a read returns the currently set clock rate value
+		as a base-10 integer while the write of a base-10 integer sets a
+		new clock rate value.
+		Each R/W access invokes the corresponding SCMI Clock protocol
+		operations and issuing of needed SCMI commands.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/enable
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol enable operation for clock resource with id
+		<XXX>; writing a boolean value causes that specific clock to be
+		enabled or disabled.
+		No reference counting is kept: each write access invokes the
+		corresponding SCMI Clock protocol operations and issuing of
+		needed SCMI commands.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/enable_atomic_irqs_on
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol enable atomic operation for clock resource
+		with id <XXX>; writing a boolean value causes that specific
+		clock to be enabled or disabled using SCMI transport in polling
+		mode, if allowed by the underlying SCMI transport.
+		No reference counting is kept: each write access invokes the
+		corresponding SCMI Clock protocol operations and issuing of
+		needed SCMI commands.
+		Available only if the underlying SCMI transport is atomic
+		capable (/sys/kernel/debug/scmi/transport/is_atomic is True).
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x14/<XXX>/enable_atomic_irqs_off
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Clock Protocol enable atomic operation for clock resource
+		with id <XXX>; writing a boolean value causes that specific
+		clock to be enabled or disabled using SCMI transport in polling
+		mode, if allowed by the underlying SCMI transport.
+		Local IRQs are disabled while the SCMI command transaction is
+		executed.
+		No reference counting is kept: each write access invokes the
+		corresponding SCMI Clock protocol operations and issuing of
+		needed SCMI commands.
+		Available only if the underlying SCMI transport is atomic
+		capable (/sys/kernel/debug/scmi/transport/is_atomic is True).
+Users:		KSelftest, Debugging
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
index 3b9e92baa509..ae5b1af88f60 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_clocks.c
@@ -24,6 +24,139 @@ struct scmi_clock_data {
 	const struct scmi_clock_info **clk_info;
 };
 
+static ssize_t scmi_test_clk_rate_get_read(struct file *filp, char __user *buf,
+					   size_t count, loff_t *ppos)
+{
+	int ret;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		u64 rate;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_clk_proto_ops *clock_ops = tsp->ops;
+
+		ret = clock_ops->rate_get(tsp->ph, data->id, &rate);
+		if (ret)
+			return ret;
+
+		data->used = scnprintf(data->buf, data->len, "%lld\n", rate);
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static ssize_t scmi_test_clk_rate_get_write(struct file *filp,
+					    const char __user *buf,
+					    size_t count, loff_t *ppos)
+{
+	int ret;
+	u64 rate;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_clk_proto_ops *clock_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtou64_from_user(buf, count, 10, &rate);
+	if (ret < 0)
+		return ret;
+
+	ret = clock_ops->rate_set(tsp->ph, data->id, rate);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_clk_rate_get_set_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_clk_rate_get_read,
+	.write = scmi_test_clk_rate_get_write,
+};
+
+static ssize_t scmi_test_clk_enable_write(struct file *filp,
+					  const char __user *buf,
+					  size_t count, loff_t *ppos)
+{
+	bool enabled, irqs_off;
+	int ret;
+	unsigned long flags;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_clk_proto_ops *clock_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	irqs_off = !strncmp(filp->f_path.dentry->d_name.name,
+			    "enable_atomic_irqs_off",
+			    strlen("enable_atomic_irqs_off"));
+	if (irqs_off)
+		local_irq_save(flags);
+
+	if (enabled)
+		ret = clock_ops->enable_atomic(tsp->ph, data->id);
+	else
+		ret = clock_ops->disable_atomic(tsp->ph, data->id);
+
+	if (irqs_off)
+		local_irq_restore(flags);
+
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_clk_enable_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.write = scmi_test_clk_enable_write,
+};
+
+static ssize_t scmi_test_clk_prepare_enable_write(struct file *filp,
+						  const char __user *buf,
+						  size_t count, loff_t *ppos)
+{
+	bool enabled;
+	int ret;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_clk_proto_ops *clock_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	if (enabled)
+		ret = clock_ops->enable(tsp->ph, data->id);
+	else
+		ret = clock_ops->disable(tsp->ph, data->id);
+
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_clk_prepare_enable_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.write = scmi_test_clk_prepare_enable_write,
+};
+
 static ssize_t scmi_test_clock_rates_read(struct file *filp, char __user *buf,
 					  size_t count, loff_t *ppos)
 {
@@ -130,9 +263,24 @@ int scmi_test_clock_init(struct scmi_test_setup *tsp)
 
 		snprintf(clock_dir, 16, "%03d", i);
 		clock_dentry = debugfs_create_dir(clock_dir, tsp->parent);
-		if (!IS_ERR(clock_dentry))
+		if (!IS_ERR(clock_dentry)) {
 			scmi_test_debugfs_clock_info_create(cdata->clk_info[i],
 							    clock_dentry);
+			debugfs_create_file("rate_get_set", 0600,
+					    clock_dentry, tsp,
+					    &test_clk_rate_get_set_fops);
+			if (tsp->sdev->handle->transport->is_atomic) {
+				debugfs_create_file("enable_atomic_irqs_off",
+						    0200, clock_dentry, tsp,
+						    &test_clk_enable_fops);
+				debugfs_create_file("enable_atomic_irqs_on",
+						    0200, clock_dentry, tsp,
+						    &test_clk_enable_fops);
+			}
+			debugfs_create_file("enable", 0200,
+					    clock_dentry, tsp,
+					    &test_clk_prepare_enable_fops);
+		}
 	}
 
 	return 0;
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
index 1a4b6aa35095..cbe2eec4f2ac 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
@@ -15,6 +15,54 @@
 #include "test_common.h"
 
 /* Common File operations */
+
+/**
+ * scmi_test_setup_open  - A common open helper
+ * @ino: Related inode reference
+ * @filp: Related file pointer reference
+ *
+ * Expects to receive a struct scmi_test_setup via inode i_private reference and
+ * then allocate a properly sized buffer; it also tries to parse the parent
+ * directory name in search for a base10 integer and, if found, stores it into
+ * the buffer descriptor @id field: this comes handy since most of the SCMI
+ * protocol operations and data are bound to some specific SCMI resource id and
+ * the SCMI debugfs directory tree is structured to mirror this layout, so that,
+ * as an example, protocol <NN> would expose <operation_AAA> about its resource
+ * with id <XXX> as:
+ *
+ *	/sys/kernel/debug/scmi/protocol_0x<NN>/<XXX>/<operation_AAA>
+ *
+ * As as result this open would allocate a data buffer, parse the dentry and
+ * set data->id = <XXX>
+ *
+ * Return: 0 on Success
+ */
+int scmi_test_setup_open(struct inode *ino, struct file *filp)
+{
+	unsigned int id;
+	size_t blen;
+	struct scmi_test_buffer *data;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const char *id_str = filp->f_path.dentry->d_parent->d_name.name;
+
+	if (!tsp)
+		return -EINVAL;
+
+	blen = tsp->blen ?: SCMI_TEST_DEFAULT_BUF_SZ;
+	data = kzalloc(sizeof(*data) + blen, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->len = blen;
+	/* Grab clk ID from debugfs entry naming if any */
+	if (!kstrtouint(id_str, 10, &id))
+		data->id = id;
+
+	filp->private_data = data;
+
+	return 0;
+}
+
 int scmi_test_release(struct inode *ino, struct file *filp)
 {
 	kfree(filp->private_data);
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index 1ff5bbc32ae3..3c64cae9fae9 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -68,6 +68,7 @@ struct scmi_test_buffer {
 
 extern const struct file_operations scmi_test_string_file_fops;
 
+int scmi_test_setup_open(struct inode *ino, struct file *filp);
 int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp);
 int scmi_test_release(struct inode *ino, struct file *filp);
 
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 10/16] firmware: arm_scmi: testing: Add Sensor protocol basic support
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:56   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add SCMI Sensor protocol testing support exposing SCMI Sensor protocol
operations under debugfs /sys/kernel/debug/scmi/protocol_0x15/<XXX>/,
where the subdirectories <XXX> represents each a distinct sensor resource
with ID equal <XXX>.

Still without any support for testing SCMI Sensor notifications.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 Documentation/ABI/testing/debugfs-scmi        |  62 +++
 .../arm_scmi/scmi_test_driver/Makefile        |   2 +-
 .../arm_scmi/scmi_test_driver/scmi_test.c     |   2 +
 .../arm_scmi/scmi_test_driver/test_common.h   |   1 +
 .../arm_scmi/scmi_test_driver/test_sensors.c  | 525 ++++++++++++++++++
 5 files changed, 591 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c

diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/testing/debugfs-scmi
index e91c19e7a323..72835516dee8 100644
--- a/Documentation/ABI/testing/debugfs-scmi
+++ b/Documentation/ABI/testing/debugfs-scmi
@@ -155,3 +155,65 @@ Description:	SCMI Clock Protocol enable atomic operation for clock resource
 		Available only if the underlying SCMI transport is atomic
 		capable (/sys/kernel/debug/scmi/transport/is_atomic is True).
 Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/info/*
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol informational RO data for sensor resource
+		with id <XXX>: each entry under info/ subdir maps to an equally
+		named field of struct scmi_sensor_info as documented in
+		include/scmi/protocol.h
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/reading_get
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol reading_get operation for sensor resource
+		with id <XXX>; a read returns an u64 integer value representing
+		the current sensor reading.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/reading_get_timestamped
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol reading_get_timestamped operation for sensor
+		resource with id <XXX>; a read returns a list of pair of values
+		in the form <TSTAMP_u64>:<READING_S64>, where the TSTAMP_u64
+		represents a timestamp taken by the platform when the sensor
+		reading <READING_s64> was sampled.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/enable
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol enable operation for sensor resource with
+		id <XXX>; a read returns a boolen value representing the current
+		enable state of the sensor, while writing a boolean value causes
+		that specific sensor to be enabled or disabled.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/sensor_config
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol config operation for sensor resource with
+		id <XXX>; a read returns a base-16 integer representing the
+		current sensor configuration as described in the relevant SCMI
+	        specification (SENSOR_CONFIG_GET), while writing a base-16
+		integer value sets the sensor configuration as per the relevant
+		SCMI specification (SENSOR_CONFIG_SET).
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/trips/<YYY>/set
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol trip points configuration operation for
+		sensor resource with id <XXX> and trip point number <YYY>;
+		writing a base-10 integer value configure and enable trip point
+		<YYY> for sensor <XXX>.
+Users:		KSelftest, Debugging
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
index 6e3ddd177827..458883193f31 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
-scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o
+scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o
 obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
 
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
index f99aa621684c..04e01dd114c9 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
@@ -24,6 +24,7 @@ DEFINE_MUTEX(scmi_test_mtx);
 static
 int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
 	[SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
+	[SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
 };
 
 static void
@@ -124,6 +125,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
 
 static const struct scmi_device_id scmi_id_table[] = {
 	{ SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
+	{ SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
 	{ },
 };
 MODULE_DEVICE_TABLE(scmi, scmi_id_table);
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index 3c64cae9fae9..e02c2521f090 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -73,5 +73,6 @@ int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp);
 int scmi_test_release(struct inode *ino, struct file *filp);
 
 int scmi_test_clock_init(struct scmi_test_setup *tsp);
+int scmi_test_sensor_init(struct scmi_test_setup *tsp);
 
 #endif /* __SCMI_TEST_COMMON_H */
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
new file mode 100644
index 000000000000..23206c2bac98
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver - Clock Protocol
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/kstrtox.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+
+#include "test_common.h"
+
+struct scmi_sensor_data {
+	unsigned int version;
+	int count;
+	const struct scmi_sensor_info **sinfo;
+};
+
+static int scmi_test_sensor_reading_open(struct inode *ino, struct file *filp)
+{
+	unsigned int id;
+	size_t blen;
+	struct scmi_test_buffer *data;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	struct scmi_sensor_data *sdata = tsp->priv;
+	const char *id_str = filp->f_path.dentry->d_parent->d_name.name;
+
+	/* Grab clk ID from debugfs entry naming if any */
+	if (kstrtouint(id_str, 10, &id))
+		return -EINVAL;
+
+	if (!sdata->sinfo[id]->num_axis)
+		blen = SCMI_TEST_DEFAULT_BUF_SZ;
+	else
+		blen = 48 * sdata->sinfo[id]->num_axis;
+
+	data = kzalloc(sizeof(*data) + blen, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->id = id;
+	data->len = blen;
+	filp->private_data = data;
+
+	return 0;
+}
+
+static ssize_t scmi_test_sensor_reading_get(struct file *filp, char __user *buf,
+					    size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		int ret;
+		bool tstamp_req;
+		u64 value;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+
+		tstamp_req = !strncmp(filp->f_path.dentry->d_name.name,
+				      "reading_get_timestamped",
+				      strlen("reading_get_timestamped"));
+
+		if (!tstamp_req) {
+			ret = sensor_ops->reading_get(tsp->ph, data->id,
+						      &value);
+			if (ret)
+				return ret;
+
+			data->used = scnprintf(data->buf, data->len, "%llu\n",
+					       value);
+		} else {
+			u8 count;
+			int i;
+			struct scmi_sensor_reading *readings;
+			const struct scmi_sensor_info *sinfo;
+			struct scmi_sensor_data *sdata = tsp->priv;
+
+			sinfo = sdata->sinfo[data->id];
+			if (!sinfo)
+				return -EINVAL;
+
+			count = sinfo->num_axis ?: 1;
+			readings = kcalloc(count, sizeof(*readings),
+					   GFP_KERNEL);
+			if (!readings)
+				return -ENOMEM;
+
+			ret = sensor_ops->reading_get_timestamped(tsp->ph,
+								  data->id,
+								  count,
+								  readings);
+			if (ret) {
+				kfree(readings);
+				return ret;
+			}
+
+			for (i = 0; i < count; i++)
+				data->used += scnprintf(data->buf + data->used,
+							data->len - data->used,
+							"%llu:%lld ",
+							readings[i].timestamp,
+							readings[i].value);
+
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used, "\n");
+
+			kfree(readings);
+		}
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static const struct file_operations test_sensor_reading_get_fops_ro = {
+	.open = scmi_test_sensor_reading_open,
+	.release = scmi_test_release,
+	.read = scmi_test_sensor_reading_get,
+};
+
+static ssize_t scmi_test_sensor_enable_read(struct file *filp, char __user *buf,
+					    size_t count, loff_t *ppos)
+{
+	int ret;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		u32 sensor_config;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+
+		ret = sensor_ops->config_get(tsp->ph, data->id, &sensor_config);
+		if (ret)
+			return ret;
+
+		data->used = scnprintf(data->buf, data->len, "%lu\n",
+				       SCMI_SENS_CFG_IS_ENABLED(sensor_config));
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static ssize_t scmi_test_sensor_enable_write(struct file *filp,
+					     const char __user *buf,
+					     size_t count, loff_t *ppos)
+{
+	bool enabled;
+	int ret;
+	u32 sensor_config;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	ret = sensor_ops->config_get(tsp->ph, data->id, &sensor_config);
+	if (ret)
+		return ret;
+
+	sensor_config &= ~SCMI_SENS_CFG_SENSOR_ENABLED_MASK;
+	sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK, enabled);
+
+	ret = sensor_ops->config_set(tsp->ph, data->id, sensor_config);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_enable_fops_rw = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_sensor_enable_read,
+	.write = scmi_test_sensor_enable_write,
+};
+
+static ssize_t scmi_test_sensor_config_read(struct file *filp, char __user *buf,
+					    size_t count, loff_t *ppos)
+{
+	int ret;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		u32 sensor_config;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+
+		ret = sensor_ops->config_get(tsp->ph, data->id, &sensor_config);
+		if (ret)
+			return ret;
+
+		data->used = scnprintf(data->buf, data->len, "0x%X\n",
+				       sensor_config);
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static ssize_t scmi_test_sensor_config_write(struct file *filp,
+					     const char __user *buf,
+					     size_t count, loff_t *ppos)
+{
+	int ret;
+	u32 sensor_config;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtou32_from_user(buf, count, 16, &sensor_config);
+	if (ret)
+		return ret;
+
+	ret = sensor_ops->config_set(tsp->ph, data->id, sensor_config);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_config_fops_rw = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_sensor_config_read,
+	.write = scmi_test_sensor_config_write,
+};
+
+static ssize_t scmi_test_sensor_trip_config_write(struct file *filp,
+						  const char __user *buf,
+						  size_t count, loff_t *ppos)
+{
+	int ret;
+	unsigned int sid;
+	u64 trip_config;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+	/* protocol_0x15/008/trips/001/set */
+	const char *sid_str =
+		filp->f_path.dentry->d_parent->d_parent->d_parent->d_name.name;
+
+	if (!data || kstrtouint(sid_str, 10, &sid))
+		return 0;
+
+	/* Cannot clear !!! Not supported by .trip_point_config */
+	ret = kstrtou64_from_user(buf, count, 10, &trip_config);
+	if (ret)
+		return ret;
+
+	ret = sensor_ops->trip_point_config(tsp->ph, sid,
+					    data->id, trip_config);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_trip_config_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.write = scmi_test_sensor_trip_config_write,
+};
+
+static void scmi_test_sensor_trips_debugfs(struct dentry *pdentry,
+					   struct scmi_test_setup *tsp,
+					   unsigned int num_points)
+{
+	struct dentry *trips_dentry;
+
+	trips_dentry = debugfs_create_dir("trips", pdentry);
+
+	if (!IS_ERR(trips_dentry)) {
+		int i;
+
+		for (i = 0; i < num_points; i++) {
+			char point_dir[16];
+			struct dentry *point_dentry;
+
+			snprintf(point_dir, 16, "%03d", i);
+			point_dentry =
+				debugfs_create_dir(point_dir, trips_dentry);
+			if (!IS_ERR(point_dentry))
+				debugfs_create_file("set", 0200,
+						    point_dentry, tsp,
+						&test_sensor_trip_config_fops);
+		}
+	}
+}
+
+static int scmi_test_sensor_intervals_open(struct inode *ino, struct file *filp)
+{
+	size_t ilen;
+	struct scmi_test_buffer *data;
+	struct scmi_sensor_intervals_info *i = filp->f_inode->i_private;
+
+	/* 65536^-16\n */
+	ilen = i->count * 16;
+	data = kzalloc(sizeof(*data) + ilen, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->len = ilen;
+	filp->private_data = data;
+
+	return 0;
+}
+
+static ssize_t scmi_test_sensor_intervals_read(struct file *filp,
+					       char __user *buf,
+					       size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		int c;
+		struct scmi_sensor_intervals_info *i = filp->f_inode->i_private;
+
+		for (c = 0; c < i->count; c++)
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used,
+						"%lu^%d ",
+					SCMI_SENS_INTVL_GET_SECS(i->desc[c]),
+					SCMI_SENS_INTVL_GET_EXP(i->desc[c]));
+
+		data->used += scnprintf(data->buf + data->used,
+					data->len - data->used, "\n");
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static const struct file_operations test_sensor_intervals_fops = {
+	.open = scmi_test_sensor_intervals_open,
+	.release = scmi_test_release,
+	.read = scmi_test_sensor_intervals_read,
+};
+
+static void
+scmi_test_debugfs_sensor_info_create(const struct scmi_sensor_info *si,
+				     struct dentry *top_dentry)
+{
+	struct dentry *parent;
+	struct scmi_sensor_info *sinfo = (struct scmi_sensor_info *)si;
+
+	parent = debugfs_create_dir("info", top_dentry);
+	if (IS_ERR(parent))
+		return;
+
+	debugfs_create_u32("type", 0400, parent, &sinfo->type);
+	debugfs_create_s32("scale", 0400, parent, &sinfo->scale);
+	debugfs_create_u32("num_trip_points", 0400, parent,
+			   &sinfo->num_trip_points);
+	debugfs_create_bool("async", 0400, parent, &sinfo->async);
+	debugfs_create_bool("continuos_updates", 0400, parent,
+			    &sinfo->update);
+	debugfs_create_bool("timestamped", 0400, parent,
+			    &sinfo->timestamped);
+	debugfs_create_s32("tstamp_scale", 0400, parent,
+			   &sinfo->tstamp_scale);
+
+	debugfs_create_u32("num_axis", 0400, parent, &sinfo->num_axis);
+	if (sinfo->num_axis) {
+		int i;
+		struct dentry *axes;
+
+		axes = debugfs_create_dir("axes", parent);
+		if (IS_ERR(axes))
+			return;
+
+		for (i = 0; i < sinfo->num_axis; i++) {
+			char axis_dir[16];
+			struct dentry *axis;
+
+			snprintf(axis_dir, 16, "%03d", i);
+			axis = debugfs_create_dir(axis_dir, axes);
+			if (IS_ERR(axis))
+				return;
+
+			debugfs_create_u32("type", 0400, axis,
+					   &sinfo->axis[i].type);
+			debugfs_create_s32("scale", 0400, axis,
+					   &sinfo->axis[i].scale);
+			debugfs_create_file("name", 0400, axis,
+					    sinfo->axis[i].name,
+					    &scmi_test_string_file_fops);
+			if (sinfo->axis[i].extended_attrs) {
+				debugfs_create_u32("resolution", 0400, axis,
+						   &sinfo->axis[i].resolution);
+				debugfs_create_s32("exponent", 0400, axis,
+						   &sinfo->axis[i].exponent);
+				debugfs_create_s64("min_range", 0400, axis,
+						   &sinfo->axis[i].attrs.min_range);
+				debugfs_create_s64("max_range", 0400, axis,
+						   &sinfo->axis[i].attrs.max_range);
+			}
+		}
+	}
+
+	if (sinfo->intervals.segmented && sinfo->intervals.count == 3) {
+		debugfs_create_u32("interval_low", 0400, parent,
+				   &sinfo->intervals.desc[SCMI_SENS_INTVL_SEGMENT_LOW]);
+		debugfs_create_u32("interval_high", 0400, parent,
+				   &sinfo->intervals.desc[SCMI_SENS_INTVL_SEGMENT_HIGH]);
+		debugfs_create_u32("interval_step", 0400, parent,
+				   &sinfo->intervals.desc[SCMI_SENS_INTVL_SEGMENT_STEP]);
+	} else {
+		debugfs_create_file("intervals", 0400, parent,
+				    &sinfo->intervals,
+				    &test_sensor_intervals_fops);
+	}
+
+	debugfs_create_u32("sensor_config", 0400, parent,
+			   &sinfo->sensor_config);
+
+	debugfs_create_file("name", 0400, parent, sinfo->name,
+			    &scmi_test_string_file_fops);
+
+	if (sinfo->extended_scalar_attrs) {
+		debugfs_create_u32("sensor_power", 0400, parent,
+				   &sinfo->sensor_power);
+		debugfs_create_u32("resolution", 0400, parent,
+				   &sinfo->resolution);
+		debugfs_create_s32("exponent", 0400, parent,
+				   &sinfo->exponent);
+		debugfs_create_s64("min_range", 0400, parent,
+				   &sinfo->scalar_attrs.min_range);
+		debugfs_create_s64("max_range", 0400, parent,
+				   &sinfo->scalar_attrs.max_range);
+	}
+}
+
+int scmi_test_sensor_init(struct scmi_test_setup *tsp)
+{
+	int i;
+	struct scmi_sensor_data *sdata;
+	const struct scmi_sensor_proto_ops *sensor_ops;
+	struct device *dev = &tsp->sdev->dev;
+
+	sdata = devm_kzalloc(dev, sizeof(*sdata), GFP_KERNEL);
+	if (!sdata)
+		return -ENOMEM;
+
+	sensor_ops = tsp->ops;
+	sdata->version = sensor_ops->version_get(tsp->ph);
+	sdata->count = sensor_ops->count_get(tsp->ph);
+
+	if (sdata->count <= 0) {
+		dev_err(dev, "number of domains invalid: %d\n",
+			sdata->count);
+		return sdata->count ?: -EINVAL;
+	}
+
+	sdata->sinfo = devm_kcalloc(dev, sdata->count,
+				    sizeof(sdata->sinfo), GFP_KERNEL);
+	if (!sdata->sinfo)
+		return -ENOMEM;
+
+	for (i = 0; i < sdata->count; i++)
+		sdata->sinfo[i] = sensor_ops->info_get(tsp->ph, i);
+
+	tsp->priv = sdata;
+	debugfs_create_x32("version", 0400, tsp->parent, &sdata->version);
+
+	dev_info(dev, "Found %d sensor resources.\n", sdata->count);
+
+	for (i = 0; i < sdata->count; i++) {
+		char sensor_dir[16];
+		struct dentry *sensor_dentry;
+
+		if (!sdata->sinfo[i])
+			continue;
+
+		snprintf(sensor_dir, 16, "%03d", i);
+		sensor_dentry = debugfs_create_dir(sensor_dir, tsp->parent);
+		if (!IS_ERR(sensor_dentry)) {
+			scmi_test_debugfs_sensor_info_create(sdata->sinfo[i],
+							     sensor_dentry);
+			debugfs_create_file("reading_get", 0400,
+					    sensor_dentry, tsp,
+					    &test_sensor_reading_get_fops_ro);
+			debugfs_create_file("reading_get_timestamped", 0400,
+					    sensor_dentry, tsp,
+					    &test_sensor_reading_get_fops_ro);
+			debugfs_create_file("enable", 0600,
+					    sensor_dentry, tsp,
+					    &test_sensor_enable_fops_rw);
+			debugfs_create_file("sensor_config", 0600,
+					    sensor_dentry, tsp,
+					    &test_sensor_config_fops_rw);
+
+			if (sdata->sinfo[i]->num_trip_points)
+				scmi_test_sensor_trips_debugfs(sensor_dentry,
+							       tsp,
+					      sdata->sinfo[i]->num_trip_points);
+		}
+	}
+
+	return 0;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 10/16] firmware: arm_scmi: testing: Add Sensor protocol basic support
@ 2022-02-27 20:56   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add SCMI Sensor protocol testing support exposing SCMI Sensor protocol
operations under debugfs /sys/kernel/debug/scmi/protocol_0x15/<XXX>/,
where the subdirectories <XXX> represents each a distinct sensor resource
with ID equal <XXX>.

Still without any support for testing SCMI Sensor notifications.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 Documentation/ABI/testing/debugfs-scmi        |  62 +++
 .../arm_scmi/scmi_test_driver/Makefile        |   2 +-
 .../arm_scmi/scmi_test_driver/scmi_test.c     |   2 +
 .../arm_scmi/scmi_test_driver/test_common.h   |   1 +
 .../arm_scmi/scmi_test_driver/test_sensors.c  | 525 ++++++++++++++++++
 5 files changed, 591 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c

diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/testing/debugfs-scmi
index e91c19e7a323..72835516dee8 100644
--- a/Documentation/ABI/testing/debugfs-scmi
+++ b/Documentation/ABI/testing/debugfs-scmi
@@ -155,3 +155,65 @@ Description:	SCMI Clock Protocol enable atomic operation for clock resource
 		Available only if the underlying SCMI transport is atomic
 		capable (/sys/kernel/debug/scmi/transport/is_atomic is True).
 Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/info/*
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol informational RO data for sensor resource
+		with id <XXX>: each entry under info/ subdir maps to an equally
+		named field of struct scmi_sensor_info as documented in
+		include/scmi/protocol.h
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/reading_get
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol reading_get operation for sensor resource
+		with id <XXX>; a read returns an u64 integer value representing
+		the current sensor reading.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/reading_get_timestamped
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol reading_get_timestamped operation for sensor
+		resource with id <XXX>; a read returns a list of pair of values
+		in the form <TSTAMP_u64>:<READING_S64>, where the TSTAMP_u64
+		represents a timestamp taken by the platform when the sensor
+		reading <READING_s64> was sampled.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/enable
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol enable operation for sensor resource with
+		id <XXX>; a read returns a boolen value representing the current
+		enable state of the sensor, while writing a boolean value causes
+		that specific sensor to be enabled or disabled.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/sensor_config
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol config operation for sensor resource with
+		id <XXX>; a read returns a base-16 integer representing the
+		current sensor configuration as described in the relevant SCMI
+	        specification (SENSOR_CONFIG_GET), while writing a base-16
+		integer value sets the sensor configuration as per the relevant
+		SCMI specification (SENSOR_CONFIG_SET).
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/trips/<YYY>/set
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	SCMI Sensor Protocol trip points configuration operation for
+		sensor resource with id <XXX> and trip point number <YYY>;
+		writing a base-10 integer value configure and enable trip point
+		<YYY> for sensor <XXX>.
+Users:		KSelftest, Debugging
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
index 6e3ddd177827..458883193f31 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
-scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o
+scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o
 obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
 
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
index f99aa621684c..04e01dd114c9 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
@@ -24,6 +24,7 @@ DEFINE_MUTEX(scmi_test_mtx);
 static
 int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
 	[SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
+	[SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
 };
 
 static void
@@ -124,6 +125,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
 
 static const struct scmi_device_id scmi_id_table[] = {
 	{ SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
+	{ SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
 	{ },
 };
 MODULE_DEVICE_TABLE(scmi, scmi_id_table);
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index 3c64cae9fae9..e02c2521f090 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -73,5 +73,6 @@ int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp);
 int scmi_test_release(struct inode *ino, struct file *filp);
 
 int scmi_test_clock_init(struct scmi_test_setup *tsp);
+int scmi_test_sensor_init(struct scmi_test_setup *tsp);
 
 #endif /* __SCMI_TEST_COMMON_H */
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
new file mode 100644
index 000000000000..23206c2bac98
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver - Clock Protocol
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/kstrtox.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+
+#include "test_common.h"
+
+struct scmi_sensor_data {
+	unsigned int version;
+	int count;
+	const struct scmi_sensor_info **sinfo;
+};
+
+static int scmi_test_sensor_reading_open(struct inode *ino, struct file *filp)
+{
+	unsigned int id;
+	size_t blen;
+	struct scmi_test_buffer *data;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	struct scmi_sensor_data *sdata = tsp->priv;
+	const char *id_str = filp->f_path.dentry->d_parent->d_name.name;
+
+	/* Grab clk ID from debugfs entry naming if any */
+	if (kstrtouint(id_str, 10, &id))
+		return -EINVAL;
+
+	if (!sdata->sinfo[id]->num_axis)
+		blen = SCMI_TEST_DEFAULT_BUF_SZ;
+	else
+		blen = 48 * sdata->sinfo[id]->num_axis;
+
+	data = kzalloc(sizeof(*data) + blen, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->id = id;
+	data->len = blen;
+	filp->private_data = data;
+
+	return 0;
+}
+
+static ssize_t scmi_test_sensor_reading_get(struct file *filp, char __user *buf,
+					    size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		int ret;
+		bool tstamp_req;
+		u64 value;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+
+		tstamp_req = !strncmp(filp->f_path.dentry->d_name.name,
+				      "reading_get_timestamped",
+				      strlen("reading_get_timestamped"));
+
+		if (!tstamp_req) {
+			ret = sensor_ops->reading_get(tsp->ph, data->id,
+						      &value);
+			if (ret)
+				return ret;
+
+			data->used = scnprintf(data->buf, data->len, "%llu\n",
+					       value);
+		} else {
+			u8 count;
+			int i;
+			struct scmi_sensor_reading *readings;
+			const struct scmi_sensor_info *sinfo;
+			struct scmi_sensor_data *sdata = tsp->priv;
+
+			sinfo = sdata->sinfo[data->id];
+			if (!sinfo)
+				return -EINVAL;
+
+			count = sinfo->num_axis ?: 1;
+			readings = kcalloc(count, sizeof(*readings),
+					   GFP_KERNEL);
+			if (!readings)
+				return -ENOMEM;
+
+			ret = sensor_ops->reading_get_timestamped(tsp->ph,
+								  data->id,
+								  count,
+								  readings);
+			if (ret) {
+				kfree(readings);
+				return ret;
+			}
+
+			for (i = 0; i < count; i++)
+				data->used += scnprintf(data->buf + data->used,
+							data->len - data->used,
+							"%llu:%lld ",
+							readings[i].timestamp,
+							readings[i].value);
+
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used, "\n");
+
+			kfree(readings);
+		}
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static const struct file_operations test_sensor_reading_get_fops_ro = {
+	.open = scmi_test_sensor_reading_open,
+	.release = scmi_test_release,
+	.read = scmi_test_sensor_reading_get,
+};
+
+static ssize_t scmi_test_sensor_enable_read(struct file *filp, char __user *buf,
+					    size_t count, loff_t *ppos)
+{
+	int ret;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		u32 sensor_config;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+
+		ret = sensor_ops->config_get(tsp->ph, data->id, &sensor_config);
+		if (ret)
+			return ret;
+
+		data->used = scnprintf(data->buf, data->len, "%lu\n",
+				       SCMI_SENS_CFG_IS_ENABLED(sensor_config));
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static ssize_t scmi_test_sensor_enable_write(struct file *filp,
+					     const char __user *buf,
+					     size_t count, loff_t *ppos)
+{
+	bool enabled;
+	int ret;
+	u32 sensor_config;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	ret = sensor_ops->config_get(tsp->ph, data->id, &sensor_config);
+	if (ret)
+		return ret;
+
+	sensor_config &= ~SCMI_SENS_CFG_SENSOR_ENABLED_MASK;
+	sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK, enabled);
+
+	ret = sensor_ops->config_set(tsp->ph, data->id, sensor_config);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_enable_fops_rw = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_sensor_enable_read,
+	.write = scmi_test_sensor_enable_write,
+};
+
+static ssize_t scmi_test_sensor_config_read(struct file *filp, char __user *buf,
+					    size_t count, loff_t *ppos)
+{
+	int ret;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		u32 sensor_config;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+
+		ret = sensor_ops->config_get(tsp->ph, data->id, &sensor_config);
+		if (ret)
+			return ret;
+
+		data->used = scnprintf(data->buf, data->len, "0x%X\n",
+				       sensor_config);
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static ssize_t scmi_test_sensor_config_write(struct file *filp,
+					     const char __user *buf,
+					     size_t count, loff_t *ppos)
+{
+	int ret;
+	u32 sensor_config;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	ret = kstrtou32_from_user(buf, count, 16, &sensor_config);
+	if (ret)
+		return ret;
+
+	ret = sensor_ops->config_set(tsp->ph, data->id, sensor_config);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_config_fops_rw = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_sensor_config_read,
+	.write = scmi_test_sensor_config_write,
+};
+
+static ssize_t scmi_test_sensor_trip_config_write(struct file *filp,
+						  const char __user *buf,
+						  size_t count, loff_t *ppos)
+{
+	int ret;
+	unsigned int sid;
+	u64 trip_config;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	const struct scmi_sensor_proto_ops *sensor_ops = tsp->ops;
+	struct scmi_test_buffer *data = filp->private_data;
+	/* protocol_0x15/008/trips/001/set */
+	const char *sid_str =
+		filp->f_path.dentry->d_parent->d_parent->d_parent->d_name.name;
+
+	if (!data || kstrtouint(sid_str, 10, &sid))
+		return 0;
+
+	/* Cannot clear !!! Not supported by .trip_point_config */
+	ret = kstrtou64_from_user(buf, count, 10, &trip_config);
+	if (ret)
+		return ret;
+
+	ret = sensor_ops->trip_point_config(tsp->ph, sid,
+					    data->id, trip_config);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_trip_config_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.write = scmi_test_sensor_trip_config_write,
+};
+
+static void scmi_test_sensor_trips_debugfs(struct dentry *pdentry,
+					   struct scmi_test_setup *tsp,
+					   unsigned int num_points)
+{
+	struct dentry *trips_dentry;
+
+	trips_dentry = debugfs_create_dir("trips", pdentry);
+
+	if (!IS_ERR(trips_dentry)) {
+		int i;
+
+		for (i = 0; i < num_points; i++) {
+			char point_dir[16];
+			struct dentry *point_dentry;
+
+			snprintf(point_dir, 16, "%03d", i);
+			point_dentry =
+				debugfs_create_dir(point_dir, trips_dentry);
+			if (!IS_ERR(point_dentry))
+				debugfs_create_file("set", 0200,
+						    point_dentry, tsp,
+						&test_sensor_trip_config_fops);
+		}
+	}
+}
+
+static int scmi_test_sensor_intervals_open(struct inode *ino, struct file *filp)
+{
+	size_t ilen;
+	struct scmi_test_buffer *data;
+	struct scmi_sensor_intervals_info *i = filp->f_inode->i_private;
+
+	/* 65536^-16\n */
+	ilen = i->count * 16;
+	data = kzalloc(sizeof(*data) + ilen, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->len = ilen;
+	filp->private_data = data;
+
+	return 0;
+}
+
+static ssize_t scmi_test_sensor_intervals_read(struct file *filp,
+					       char __user *buf,
+					       size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		int c;
+		struct scmi_sensor_intervals_info *i = filp->f_inode->i_private;
+
+		for (c = 0; c < i->count; c++)
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used,
+						"%lu^%d ",
+					SCMI_SENS_INTVL_GET_SECS(i->desc[c]),
+					SCMI_SENS_INTVL_GET_EXP(i->desc[c]));
+
+		data->used += scnprintf(data->buf + data->used,
+					data->len - data->used, "\n");
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
+static const struct file_operations test_sensor_intervals_fops = {
+	.open = scmi_test_sensor_intervals_open,
+	.release = scmi_test_release,
+	.read = scmi_test_sensor_intervals_read,
+};
+
+static void
+scmi_test_debugfs_sensor_info_create(const struct scmi_sensor_info *si,
+				     struct dentry *top_dentry)
+{
+	struct dentry *parent;
+	struct scmi_sensor_info *sinfo = (struct scmi_sensor_info *)si;
+
+	parent = debugfs_create_dir("info", top_dentry);
+	if (IS_ERR(parent))
+		return;
+
+	debugfs_create_u32("type", 0400, parent, &sinfo->type);
+	debugfs_create_s32("scale", 0400, parent, &sinfo->scale);
+	debugfs_create_u32("num_trip_points", 0400, parent,
+			   &sinfo->num_trip_points);
+	debugfs_create_bool("async", 0400, parent, &sinfo->async);
+	debugfs_create_bool("continuos_updates", 0400, parent,
+			    &sinfo->update);
+	debugfs_create_bool("timestamped", 0400, parent,
+			    &sinfo->timestamped);
+	debugfs_create_s32("tstamp_scale", 0400, parent,
+			   &sinfo->tstamp_scale);
+
+	debugfs_create_u32("num_axis", 0400, parent, &sinfo->num_axis);
+	if (sinfo->num_axis) {
+		int i;
+		struct dentry *axes;
+
+		axes = debugfs_create_dir("axes", parent);
+		if (IS_ERR(axes))
+			return;
+
+		for (i = 0; i < sinfo->num_axis; i++) {
+			char axis_dir[16];
+			struct dentry *axis;
+
+			snprintf(axis_dir, 16, "%03d", i);
+			axis = debugfs_create_dir(axis_dir, axes);
+			if (IS_ERR(axis))
+				return;
+
+			debugfs_create_u32("type", 0400, axis,
+					   &sinfo->axis[i].type);
+			debugfs_create_s32("scale", 0400, axis,
+					   &sinfo->axis[i].scale);
+			debugfs_create_file("name", 0400, axis,
+					    sinfo->axis[i].name,
+					    &scmi_test_string_file_fops);
+			if (sinfo->axis[i].extended_attrs) {
+				debugfs_create_u32("resolution", 0400, axis,
+						   &sinfo->axis[i].resolution);
+				debugfs_create_s32("exponent", 0400, axis,
+						   &sinfo->axis[i].exponent);
+				debugfs_create_s64("min_range", 0400, axis,
+						   &sinfo->axis[i].attrs.min_range);
+				debugfs_create_s64("max_range", 0400, axis,
+						   &sinfo->axis[i].attrs.max_range);
+			}
+		}
+	}
+
+	if (sinfo->intervals.segmented && sinfo->intervals.count == 3) {
+		debugfs_create_u32("interval_low", 0400, parent,
+				   &sinfo->intervals.desc[SCMI_SENS_INTVL_SEGMENT_LOW]);
+		debugfs_create_u32("interval_high", 0400, parent,
+				   &sinfo->intervals.desc[SCMI_SENS_INTVL_SEGMENT_HIGH]);
+		debugfs_create_u32("interval_step", 0400, parent,
+				   &sinfo->intervals.desc[SCMI_SENS_INTVL_SEGMENT_STEP]);
+	} else {
+		debugfs_create_file("intervals", 0400, parent,
+				    &sinfo->intervals,
+				    &test_sensor_intervals_fops);
+	}
+
+	debugfs_create_u32("sensor_config", 0400, parent,
+			   &sinfo->sensor_config);
+
+	debugfs_create_file("name", 0400, parent, sinfo->name,
+			    &scmi_test_string_file_fops);
+
+	if (sinfo->extended_scalar_attrs) {
+		debugfs_create_u32("sensor_power", 0400, parent,
+				   &sinfo->sensor_power);
+		debugfs_create_u32("resolution", 0400, parent,
+				   &sinfo->resolution);
+		debugfs_create_s32("exponent", 0400, parent,
+				   &sinfo->exponent);
+		debugfs_create_s64("min_range", 0400, parent,
+				   &sinfo->scalar_attrs.min_range);
+		debugfs_create_s64("max_range", 0400, parent,
+				   &sinfo->scalar_attrs.max_range);
+	}
+}
+
+int scmi_test_sensor_init(struct scmi_test_setup *tsp)
+{
+	int i;
+	struct scmi_sensor_data *sdata;
+	const struct scmi_sensor_proto_ops *sensor_ops;
+	struct device *dev = &tsp->sdev->dev;
+
+	sdata = devm_kzalloc(dev, sizeof(*sdata), GFP_KERNEL);
+	if (!sdata)
+		return -ENOMEM;
+
+	sensor_ops = tsp->ops;
+	sdata->version = sensor_ops->version_get(tsp->ph);
+	sdata->count = sensor_ops->count_get(tsp->ph);
+
+	if (sdata->count <= 0) {
+		dev_err(dev, "number of domains invalid: %d\n",
+			sdata->count);
+		return sdata->count ?: -EINVAL;
+	}
+
+	sdata->sinfo = devm_kcalloc(dev, sdata->count,
+				    sizeof(sdata->sinfo), GFP_KERNEL);
+	if (!sdata->sinfo)
+		return -ENOMEM;
+
+	for (i = 0; i < sdata->count; i++)
+		sdata->sinfo[i] = sensor_ops->info_get(tsp->ph, i);
+
+	tsp->priv = sdata;
+	debugfs_create_x32("version", 0400, tsp->parent, &sdata->version);
+
+	dev_info(dev, "Found %d sensor resources.\n", sdata->count);
+
+	for (i = 0; i < sdata->count; i++) {
+		char sensor_dir[16];
+		struct dentry *sensor_dentry;
+
+		if (!sdata->sinfo[i])
+			continue;
+
+		snprintf(sensor_dir, 16, "%03d", i);
+		sensor_dentry = debugfs_create_dir(sensor_dir, tsp->parent);
+		if (!IS_ERR(sensor_dentry)) {
+			scmi_test_debugfs_sensor_info_create(sdata->sinfo[i],
+							     sensor_dentry);
+			debugfs_create_file("reading_get", 0400,
+					    sensor_dentry, tsp,
+					    &test_sensor_reading_get_fops_ro);
+			debugfs_create_file("reading_get_timestamped", 0400,
+					    sensor_dentry, tsp,
+					    &test_sensor_reading_get_fops_ro);
+			debugfs_create_file("enable", 0600,
+					    sensor_dentry, tsp,
+					    &test_sensor_enable_fops_rw);
+			debugfs_create_file("sensor_config", 0600,
+					    sensor_dentry, tsp,
+					    &test_sensor_config_fops_rw);
+
+			if (sdata->sinfo[i]->num_trip_points)
+				scmi_test_sensor_trips_debugfs(sensor_dentry,
+							       tsp,
+					      sdata->sinfo[i]->num_trip_points);
+		}
+	}
+
+	return 0;
+}
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 11/16] firmware: arm_scmi: Add test driver generic notification helpers
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:56   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add a few generic helpers to allow the test driver to register a common
notifier block and related read routines in order to test notifications
when supported by the specific SCMI protocol.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 .../arm_scmi/scmi_test_driver/test_common.c   | 177 ++++++++++++++++++
 .../arm_scmi/scmi_test_driver/test_common.h   |  28 +++
 2 files changed, 205 insertions(+)

diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
index cbe2eec4f2ac..c44fe702196e 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
@@ -14,6 +14,22 @@
 
 #include "test_common.h"
 
+struct scmi_test_setup *
+scmi_test_tsp_shallow_copy(struct device *dev,
+			   struct scmi_test_setup *tsp)
+{
+	struct scmi_test_setup *tsp_copy;
+
+	tsp_copy = devm_kzalloc(dev, sizeof(*tsp_copy), GFP_KERNEL);
+	if (!tsp_copy)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(tsp_copy, tsp, sizeof(*tsp_copy));
+	tsp_copy->n_priv = NULL;
+
+	return tsp_copy;
+}
+
 /* Common File operations */
 
 /**
@@ -70,6 +86,167 @@ int scmi_test_release(struct inode *ino, struct file *filp)
 	return 0;
 }
 
+int scmi_test_generic_notif_cb(struct notifier_block *nb, unsigned long event,
+			       void *data)
+{
+	struct scmi_test_notif_reports *nrep;
+	void *d_report;
+
+	nrep = container_of(nb, struct scmi_test_notif_reports, notif_nb);
+
+	mutex_lock(&nrep->mtx);
+	d_report = ((u8 *)nrep->reports) +
+		    ((nrep->count % nrep->max_reports) * nrep->report_sz);
+	memcpy(d_report, data, nrep->report_sz);
+	nrep->count++;
+	mutex_unlock(&nrep->mtx);
+
+	return NOTIFY_OK;
+}
+
+static struct scmi_test_notif_reports *
+scmi_test_notif_reports_alloc(struct scmi_device *sdev,
+			      size_t report_sz, unsigned int max_reports,
+			      u8 proto_id, u8 evt_id, const u32 *src_id,
+			      notifier_fn_t notif_cb)
+{
+	int ret;
+	struct scmi_test_notif_reports *nrep;
+	struct device *dev = &sdev->dev;
+	const struct scmi_notify_ops *n_ops = sdev->handle->notify_ops;
+
+	nrep = devm_kzalloc(dev, sizeof(*nrep), GFP_KERNEL);
+	if (!nrep)
+		return ERR_PTR(-ENOMEM);
+
+	nrep->reports = devm_kcalloc(dev, max_reports, report_sz, GFP_KERNEL);
+	if (!nrep->reports) {
+		devm_kfree(dev, nrep);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	nrep->proto_id = proto_id;
+	nrep->evt_id = evt_id;
+	if (src_id)
+		nrep->src_id = *src_id;
+	else
+		nrep->src_id = 0xffffffff;
+	nrep->report_sz = report_sz;
+	nrep->max_reports = max_reports;
+	mutex_init(&nrep->mtx);
+
+	if (notif_cb)
+		nrep->notif_nb.notifier_call = notif_cb;
+	else
+		nrep->notif_nb.notifier_call = scmi_test_generic_notif_cb;
+
+	ret = n_ops->devm_event_notifier_register(sdev,
+						  proto_id, evt_id, src_id,
+						  &nrep->notif_nb);
+	if (ret) {
+		devm_kfree(dev, nrep->reports);
+		devm_kfree(dev, nrep);
+		return ERR_PTR(ret);
+	}
+
+	return nrep;
+}
+
+static int scmi_test_notif_reports_free(struct scmi_device *sdev,
+					struct scmi_test_notif_reports *nrep)
+{
+	int ret;
+	struct device *dev = &sdev->dev;
+	const struct scmi_notify_ops *n_ops = sdev->handle->notify_ops;
+
+	if (!nrep)
+		return -EINVAL;
+
+	ret = n_ops->devm_event_notifier_unregister(sdev, &nrep->notif_nb);
+	if (ret)
+		return ret;
+
+	devm_kfree(dev, nrep->reports);
+	devm_kfree(dev, nrep);
+
+	return 0;
+}
+
+int scmi_test_notif_manage(struct scmi_test_setup *tsp, bool enabled,
+			   u8 proto_id, u8 evt_id, const u32 *src_id,
+			   size_t rep_sz, notifier_fn_t notif_cb)
+{
+	int ret;
+
+	/* For testing allow enable only for one notifier at time */
+	if ((enabled && tsp->n_priv) || (!enabled && !tsp->n_priv))
+		return -EINVAL;
+
+	if (enabled) {
+		tsp->n_priv =
+			scmi_test_notif_reports_alloc(tsp->sdev, rep_sz,
+						      SCMI_TEST_MAX_REPORTS,
+						      proto_id, evt_id,
+						      src_id, notif_cb);
+		if (IS_ERR(tsp->n_priv)) {
+			ret = PTR_ERR(tsp->n_priv);
+			tsp->n_priv = NULL;
+			return ret;
+		}
+	} else {
+		ret = scmi_test_notif_reports_free(tsp->sdev, tsp->n_priv);
+		if (ret)
+			return ret;
+
+		tsp->n_priv = NULL;
+	}
+
+	return 0;
+}
+
+ssize_t scmi_test_notif_reports_read(struct file *filp, char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	struct scmi_test_notif_reports *nrep = tsp->n_priv;
+
+	if (!data || !nrep)
+		return 0;
+
+	if (!data->used) {
+		int i, cnt;
+
+		mutex_lock(&nrep->mtx);
+		cnt = nrep->count >= nrep->max_reports ?
+			nrep->max_reports : nrep->count;
+		for (i = 0; i < cnt; i++) {
+			u8 *rep;
+			int j;
+
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used,
+				       "[%02u/%02u|%u] - |%02X|%u|%u| = Report: ",
+						i,
+						nrep->max_reports, nrep->count,
+						nrep->proto_id, nrep->evt_id,
+						nrep->src_id);
+
+			rep = ((u8 *)nrep->reports) + i * nrep->report_sz;
+			for (j = 0; j < nrep->report_sz; j++)
+				data->used += scnprintf(data->buf + data->used,
+							data->len - data->used,
+							"%02X ", rep[j]);
+
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used, "\n");
+		}
+		mutex_unlock(&nrep->mtx);
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
 int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp)
 {
 	struct scmi_test_buffer *data;
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index e02c2521f090..93c05db0ebff 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -66,8 +66,36 @@ struct scmi_test_buffer {
 	unsigned char buf[];
 };
 
+#define SCMI_TEST_MAX_REPORTS	20
+struct scmi_test_notif_reports {
+	u8 proto_id;
+	u8 evt_id;
+	u32 src_id;
+	unsigned int max_reports;
+	size_t report_sz;
+	void *reports;
+	unsigned int count;
+	struct notifier_block notif_nb;
+	/* Protect access to notification reports */
+	struct mutex mtx;
+};
+
 extern const struct file_operations scmi_test_string_file_fops;
 
+int scmi_test_generic_notif_cb(struct notifier_block *nb, unsigned long event,
+			       void *data);
+
+int scmi_test_notif_manage(struct scmi_test_setup *tsp, bool enabled,
+			   u8 proto_id, u8 evt_id, const u32 *src_id,
+			   size_t rep_sz, notifier_fn_t notif_cb);
+
+ssize_t scmi_test_notif_reports_read(struct file *filp, char __user *buf,
+				     size_t count, loff_t *ppos);
+
+struct scmi_test_setup *
+scmi_test_tsp_shallow_copy(struct device *dev,
+			   struct scmi_test_setup *tsp);
+
 int scmi_test_setup_open(struct inode *ino, struct file *filp);
 int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp);
 int scmi_test_release(struct inode *ino, struct file *filp);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 11/16] firmware: arm_scmi: Add test driver generic notification helpers
@ 2022-02-27 20:56   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add a few generic helpers to allow the test driver to register a common
notifier block and related read routines in order to test notifications
when supported by the specific SCMI protocol.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 .../arm_scmi/scmi_test_driver/test_common.c   | 177 ++++++++++++++++++
 .../arm_scmi/scmi_test_driver/test_common.h   |  28 +++
 2 files changed, 205 insertions(+)

diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
index cbe2eec4f2ac..c44fe702196e 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.c
@@ -14,6 +14,22 @@
 
 #include "test_common.h"
 
+struct scmi_test_setup *
+scmi_test_tsp_shallow_copy(struct device *dev,
+			   struct scmi_test_setup *tsp)
+{
+	struct scmi_test_setup *tsp_copy;
+
+	tsp_copy = devm_kzalloc(dev, sizeof(*tsp_copy), GFP_KERNEL);
+	if (!tsp_copy)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(tsp_copy, tsp, sizeof(*tsp_copy));
+	tsp_copy->n_priv = NULL;
+
+	return tsp_copy;
+}
+
 /* Common File operations */
 
 /**
@@ -70,6 +86,167 @@ int scmi_test_release(struct inode *ino, struct file *filp)
 	return 0;
 }
 
+int scmi_test_generic_notif_cb(struct notifier_block *nb, unsigned long event,
+			       void *data)
+{
+	struct scmi_test_notif_reports *nrep;
+	void *d_report;
+
+	nrep = container_of(nb, struct scmi_test_notif_reports, notif_nb);
+
+	mutex_lock(&nrep->mtx);
+	d_report = ((u8 *)nrep->reports) +
+		    ((nrep->count % nrep->max_reports) * nrep->report_sz);
+	memcpy(d_report, data, nrep->report_sz);
+	nrep->count++;
+	mutex_unlock(&nrep->mtx);
+
+	return NOTIFY_OK;
+}
+
+static struct scmi_test_notif_reports *
+scmi_test_notif_reports_alloc(struct scmi_device *sdev,
+			      size_t report_sz, unsigned int max_reports,
+			      u8 proto_id, u8 evt_id, const u32 *src_id,
+			      notifier_fn_t notif_cb)
+{
+	int ret;
+	struct scmi_test_notif_reports *nrep;
+	struct device *dev = &sdev->dev;
+	const struct scmi_notify_ops *n_ops = sdev->handle->notify_ops;
+
+	nrep = devm_kzalloc(dev, sizeof(*nrep), GFP_KERNEL);
+	if (!nrep)
+		return ERR_PTR(-ENOMEM);
+
+	nrep->reports = devm_kcalloc(dev, max_reports, report_sz, GFP_KERNEL);
+	if (!nrep->reports) {
+		devm_kfree(dev, nrep);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	nrep->proto_id = proto_id;
+	nrep->evt_id = evt_id;
+	if (src_id)
+		nrep->src_id = *src_id;
+	else
+		nrep->src_id = 0xffffffff;
+	nrep->report_sz = report_sz;
+	nrep->max_reports = max_reports;
+	mutex_init(&nrep->mtx);
+
+	if (notif_cb)
+		nrep->notif_nb.notifier_call = notif_cb;
+	else
+		nrep->notif_nb.notifier_call = scmi_test_generic_notif_cb;
+
+	ret = n_ops->devm_event_notifier_register(sdev,
+						  proto_id, evt_id, src_id,
+						  &nrep->notif_nb);
+	if (ret) {
+		devm_kfree(dev, nrep->reports);
+		devm_kfree(dev, nrep);
+		return ERR_PTR(ret);
+	}
+
+	return nrep;
+}
+
+static int scmi_test_notif_reports_free(struct scmi_device *sdev,
+					struct scmi_test_notif_reports *nrep)
+{
+	int ret;
+	struct device *dev = &sdev->dev;
+	const struct scmi_notify_ops *n_ops = sdev->handle->notify_ops;
+
+	if (!nrep)
+		return -EINVAL;
+
+	ret = n_ops->devm_event_notifier_unregister(sdev, &nrep->notif_nb);
+	if (ret)
+		return ret;
+
+	devm_kfree(dev, nrep->reports);
+	devm_kfree(dev, nrep);
+
+	return 0;
+}
+
+int scmi_test_notif_manage(struct scmi_test_setup *tsp, bool enabled,
+			   u8 proto_id, u8 evt_id, const u32 *src_id,
+			   size_t rep_sz, notifier_fn_t notif_cb)
+{
+	int ret;
+
+	/* For testing allow enable only for one notifier at time */
+	if ((enabled && tsp->n_priv) || (!enabled && !tsp->n_priv))
+		return -EINVAL;
+
+	if (enabled) {
+		tsp->n_priv =
+			scmi_test_notif_reports_alloc(tsp->sdev, rep_sz,
+						      SCMI_TEST_MAX_REPORTS,
+						      proto_id, evt_id,
+						      src_id, notif_cb);
+		if (IS_ERR(tsp->n_priv)) {
+			ret = PTR_ERR(tsp->n_priv);
+			tsp->n_priv = NULL;
+			return ret;
+		}
+	} else {
+		ret = scmi_test_notif_reports_free(tsp->sdev, tsp->n_priv);
+		if (ret)
+			return ret;
+
+		tsp->n_priv = NULL;
+	}
+
+	return 0;
+}
+
+ssize_t scmi_test_notif_reports_read(struct file *filp, char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	struct scmi_test_notif_reports *nrep = tsp->n_priv;
+
+	if (!data || !nrep)
+		return 0;
+
+	if (!data->used) {
+		int i, cnt;
+
+		mutex_lock(&nrep->mtx);
+		cnt = nrep->count >= nrep->max_reports ?
+			nrep->max_reports : nrep->count;
+		for (i = 0; i < cnt; i++) {
+			u8 *rep;
+			int j;
+
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used,
+				       "[%02u/%02u|%u] - |%02X|%u|%u| = Report: ",
+						i,
+						nrep->max_reports, nrep->count,
+						nrep->proto_id, nrep->evt_id,
+						nrep->src_id);
+
+			rep = ((u8 *)nrep->reports) + i * nrep->report_sz;
+			for (j = 0; j < nrep->report_sz; j++)
+				data->used += scnprintf(data->buf + data->used,
+							data->len - data->used,
+							"%02X ", rep[j]);
+
+			data->used += scnprintf(data->buf + data->used,
+						data->len - data->used, "\n");
+		}
+		mutex_unlock(&nrep->mtx);
+	}
+
+	return simple_read_from_buffer(buf, count, ppos, data->buf, data->used);
+}
+
 int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp)
 {
 	struct scmi_test_buffer *data;
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index e02c2521f090..93c05db0ebff 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -66,8 +66,36 @@ struct scmi_test_buffer {
 	unsigned char buf[];
 };
 
+#define SCMI_TEST_MAX_REPORTS	20
+struct scmi_test_notif_reports {
+	u8 proto_id;
+	u8 evt_id;
+	u32 src_id;
+	unsigned int max_reports;
+	size_t report_sz;
+	void *reports;
+	unsigned int count;
+	struct notifier_block notif_nb;
+	/* Protect access to notification reports */
+	struct mutex mtx;
+};
+
 extern const struct file_operations scmi_test_string_file_fops;
 
+int scmi_test_generic_notif_cb(struct notifier_block *nb, unsigned long event,
+			       void *data);
+
+int scmi_test_notif_manage(struct scmi_test_setup *tsp, bool enabled,
+			   u8 proto_id, u8 evt_id, const u32 *src_id,
+			   size_t rep_sz, notifier_fn_t notif_cb);
+
+ssize_t scmi_test_notif_reports_read(struct file *filp, char __user *buf,
+				     size_t count, loff_t *ppos);
+
+struct scmi_test_setup *
+scmi_test_tsp_shallow_copy(struct device *dev,
+			   struct scmi_test_setup *tsp);
+
 int scmi_test_setup_open(struct inode *ino, struct file *filp);
 int scmi_test_fixed_buffer_open(struct inode *ino, struct file *filp);
 int scmi_test_release(struct inode *ino, struct file *filp);
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 12/16] firmware: arm_scmi: Add Sensor notifications testing support
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:56   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add a few debugfs entry to enable Sensor notifications support, namely
continuos sensor updates notifications and sensor trip point events
notifications.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 Documentation/ABI/testing/debugfs-scmi        |  50 +++++++++
 .../arm_scmi/scmi_test_driver/test_sensors.c  | 104 +++++++++++++++++-
 2 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/testing/debugfs-scmi
index 72835516dee8..8b3f9a12053d 100644
--- a/Documentation/ABI/testing/debugfs-scmi
+++ b/Documentation/ABI/testing/debugfs-scmi
@@ -217,3 +217,53 @@ Description:	SCMI Sensor Protocol trip points configuration operation for
 		writing a base-10 integer value configure and enable trip point
 		<YYY> for sensor <XXX>.
 Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/sensor_update_notifs
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	A RW entry to support SENSOR_UPDATE notifications testing.
+		Writing a true value (Y/y/1) to this entry will trigger the
+		registration of a common notifier block for the SENSOR_UPDATE
+		notification as defined in SCMI Sensor Protocol: this common
+		notifier block starts collecting all the received notification
+		payload in a circular buffer.
+		The rate at which such notifications are emitted depends on the
+		specific update interval currently selected by the resource
+		at hand using the SENSOR_CONFIG command.
+		Note that, as per SCMI specification, the related sensor
+		resource <XXX> has also to be in an enabled state for the
+		notifications to be emitted by the platform.
+		Reading from this entry will return the latest content of the
+		above mentioned circular buffer.
+		Writing a false value (N/n/0) to this entry will cause the above
+		mentioned common notifier block to be unregistered and so
+		effectively the notification emission to be stopped.
+		When the notifier is unregistered the notification circular
+		buffer is cleared empty.
+		This entry is present only if the related resource <XXX> has
+		been advertised as supporting continuos updated notifications.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/sensor_trip_notifs
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	A RW entry to support SENSOR_TRIP_POINT_EVENT notifications
+		testing. Writing a true value (Y/y/1) to this entry will trigger
+		the registration of a common notifier block for
+		SENSOR_TRIP_POINT_EVENT notification as defined in SCMI Sensor
+		Protocol: this common notifier block starts collecting all the
+		received notification payload in a circular buffer.
+		Such notifications will be emitted once the related sensor
+		resource crosses one of the configured trip point: such trip
+		point can be cofigured using SENSOR_TRIP_POINT_CONFIG command
+		and related entries in the SCMI debugfs filesystem.
+		Reading from this entry will return the latest content of the
+		above mentioned circular buffer.
+		Writing a false value (N/n/0) to this entry will cause the above
+		mentioned common notifier block to be unregistered and so
+		effectively the notification emission to be stopped.
+		When the notifier is unregistered the notification circular
+		buffer is cleared empty.
+Users:		KSelftest, Debugging
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
index 23206c2bac98..2d610d84390f 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
@@ -284,6 +284,79 @@ static const struct file_operations test_sensor_trip_config_fops = {
 	.write = scmi_test_sensor_trip_config_write,
 };
 
+static ssize_t scmi_test_sensor_updates_write(struct file *filp,
+					      const char __user *buf,
+					      size_t count, loff_t *ppos)
+{
+	bool enabled;
+	int ret;
+	u32 src_id;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!tsp || !data)
+		return count;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	src_id = data->id;
+	ret = scmi_test_notif_manage(tsp, enabled,
+				     SCMI_PROTOCOL_SENSOR,
+				     SCMI_EVENT_SENSOR_UPDATE, &src_id,
+				     sizeof(struct scmi_sensor_update_report),
+				     scmi_test_generic_notif_cb);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_updates_fops_rw = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_notif_reports_read,
+	.write = scmi_test_sensor_updates_write,
+};
+
+static ssize_t scmi_test_sensor_trip_point_write(struct file *filp,
+						 const char __user *buf,
+						 size_t count, loff_t *ppos)
+{
+	bool enabled;
+	int ret;
+	u32 src_id;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!tsp || !data)
+		return count;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	src_id = data->id;
+	ret = scmi_test_notif_manage(tsp, enabled,
+				     SCMI_PROTOCOL_SENSOR,
+				     SCMI_EVENT_SENSOR_TRIP_POINT_EVENT,
+				     &src_id,
+				   sizeof(struct scmi_sensor_trip_point_report),
+				     scmi_test_generic_notif_cb);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_trips_fops_rw = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_notif_reports_read,
+	.write = scmi_test_sensor_trip_point_write,
+};
+
 static void scmi_test_sensor_trips_debugfs(struct dentry *pdentry,
 					   struct scmi_test_setup *tsp,
 					   unsigned int num_points)
@@ -514,10 +587,39 @@ int scmi_test_sensor_init(struct scmi_test_setup *tsp)
 					    sensor_dentry, tsp,
 					    &test_sensor_config_fops_rw);
 
-			if (sdata->sinfo[i]->num_trip_points)
+			if (sdata->sinfo[i]->update) {
+				struct scmi_test_setup *tsp_copy;
+
+				tsp_copy = scmi_test_tsp_shallow_copy(dev, tsp);
+				if (IS_ERR(tsp_copy))
+					return PTR_ERR(tsp_copy);
+
+				/* Bigger dedicated buffer for notifs */
+				tsp_copy->blen = 4096;
+				debugfs_create_file("sensor_update_notifs",
+						    0600, sensor_dentry,
+						    tsp_copy,
+						  &test_sensor_updates_fops_rw);
+			}
+
+			if (sdata->sinfo[i]->num_trip_points) {
+				struct scmi_test_setup *tsp_copy;
+
 				scmi_test_sensor_trips_debugfs(sensor_dentry,
 							       tsp,
 					      sdata->sinfo[i]->num_trip_points);
+
+				tsp_copy = scmi_test_tsp_shallow_copy(dev, tsp);
+				if (IS_ERR(tsp_copy))
+					return PTR_ERR(tsp_copy);
+
+				/* Bigger dedicated buffer for notifs */
+				tsp_copy->blen = 4096;
+				debugfs_create_file("sensor_trip_notifs",
+						    0600, sensor_dentry,
+						    tsp_copy,
+						    &test_sensor_trips_fops_rw);
+			}
 		}
 	}
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 12/16] firmware: arm_scmi: Add Sensor notifications testing support
@ 2022-02-27 20:56   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

Add a few debugfs entry to enable Sensor notifications support, namely
continuos sensor updates notifications and sensor trip point events
notifications.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 Documentation/ABI/testing/debugfs-scmi        |  50 +++++++++
 .../arm_scmi/scmi_test_driver/test_sensors.c  | 104 +++++++++++++++++-
 2 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/debugfs-scmi b/Documentation/ABI/testing/debugfs-scmi
index 72835516dee8..8b3f9a12053d 100644
--- a/Documentation/ABI/testing/debugfs-scmi
+++ b/Documentation/ABI/testing/debugfs-scmi
@@ -217,3 +217,53 @@ Description:	SCMI Sensor Protocol trip points configuration operation for
 		writing a base-10 integer value configure and enable trip point
 		<YYY> for sensor <XXX>.
 Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/sensor_update_notifs
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	A RW entry to support SENSOR_UPDATE notifications testing.
+		Writing a true value (Y/y/1) to this entry will trigger the
+		registration of a common notifier block for the SENSOR_UPDATE
+		notification as defined in SCMI Sensor Protocol: this common
+		notifier block starts collecting all the received notification
+		payload in a circular buffer.
+		The rate at which such notifications are emitted depends on the
+		specific update interval currently selected by the resource
+		at hand using the SENSOR_CONFIG command.
+		Note that, as per SCMI specification, the related sensor
+		resource <XXX> has also to be in an enabled state for the
+		notifications to be emitted by the platform.
+		Reading from this entry will return the latest content of the
+		above mentioned circular buffer.
+		Writing a false value (N/n/0) to this entry will cause the above
+		mentioned common notifier block to be unregistered and so
+		effectively the notification emission to be stopped.
+		When the notifier is unregistered the notification circular
+		buffer is cleared empty.
+		This entry is present only if the related resource <XXX> has
+		been advertised as supporting continuos updated notifications.
+Users:		KSelftest, Debugging
+
+What:		/sys/kernel/debug/scmi/protocol_0x15/<XXX>/sensor_trip_notifs
+Date:		Feb 2022
+KernelVersion:	5.19
+Contact:	cristian.marussi@arm.com
+Description:	A RW entry to support SENSOR_TRIP_POINT_EVENT notifications
+		testing. Writing a true value (Y/y/1) to this entry will trigger
+		the registration of a common notifier block for
+		SENSOR_TRIP_POINT_EVENT notification as defined in SCMI Sensor
+		Protocol: this common notifier block starts collecting all the
+		received notification payload in a circular buffer.
+		Such notifications will be emitted once the related sensor
+		resource crosses one of the configured trip point: such trip
+		point can be cofigured using SENSOR_TRIP_POINT_CONFIG command
+		and related entries in the SCMI debugfs filesystem.
+		Reading from this entry will return the latest content of the
+		above mentioned circular buffer.
+		Writing a false value (N/n/0) to this entry will cause the above
+		mentioned common notifier block to be unregistered and so
+		effectively the notification emission to be stopped.
+		When the notifier is unregistered the notification circular
+		buffer is cleared empty.
+Users:		KSelftest, Debugging
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
index 23206c2bac98..2d610d84390f 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_sensors.c
@@ -284,6 +284,79 @@ static const struct file_operations test_sensor_trip_config_fops = {
 	.write = scmi_test_sensor_trip_config_write,
 };
 
+static ssize_t scmi_test_sensor_updates_write(struct file *filp,
+					      const char __user *buf,
+					      size_t count, loff_t *ppos)
+{
+	bool enabled;
+	int ret;
+	u32 src_id;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!tsp || !data)
+		return count;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	src_id = data->id;
+	ret = scmi_test_notif_manage(tsp, enabled,
+				     SCMI_PROTOCOL_SENSOR,
+				     SCMI_EVENT_SENSOR_UPDATE, &src_id,
+				     sizeof(struct scmi_sensor_update_report),
+				     scmi_test_generic_notif_cb);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_updates_fops_rw = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_notif_reports_read,
+	.write = scmi_test_sensor_updates_write,
+};
+
+static ssize_t scmi_test_sensor_trip_point_write(struct file *filp,
+						 const char __user *buf,
+						 size_t count, loff_t *ppos)
+{
+	bool enabled;
+	int ret;
+	u32 src_id;
+	struct scmi_test_setup *tsp = filp->f_inode->i_private;
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!tsp || !data)
+		return count;
+
+	ret = kstrtobool_from_user(buf, count, &enabled);
+	if (ret)
+		return ret;
+
+	src_id = data->id;
+	ret = scmi_test_notif_manage(tsp, enabled,
+				     SCMI_PROTOCOL_SENSOR,
+				     SCMI_EVENT_SENSOR_TRIP_POINT_EVENT,
+				     &src_id,
+				   sizeof(struct scmi_sensor_trip_point_report),
+				     scmi_test_generic_notif_cb);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations test_sensor_trips_fops_rw = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_notif_reports_read,
+	.write = scmi_test_sensor_trip_point_write,
+};
+
 static void scmi_test_sensor_trips_debugfs(struct dentry *pdentry,
 					   struct scmi_test_setup *tsp,
 					   unsigned int num_points)
@@ -514,10 +587,39 @@ int scmi_test_sensor_init(struct scmi_test_setup *tsp)
 					    sensor_dentry, tsp,
 					    &test_sensor_config_fops_rw);
 
-			if (sdata->sinfo[i]->num_trip_points)
+			if (sdata->sinfo[i]->update) {
+				struct scmi_test_setup *tsp_copy;
+
+				tsp_copy = scmi_test_tsp_shallow_copy(dev, tsp);
+				if (IS_ERR(tsp_copy))
+					return PTR_ERR(tsp_copy);
+
+				/* Bigger dedicated buffer for notifs */
+				tsp_copy->blen = 4096;
+				debugfs_create_file("sensor_update_notifs",
+						    0600, sensor_dentry,
+						    tsp_copy,
+						  &test_sensor_updates_fops_rw);
+			}
+
+			if (sdata->sinfo[i]->num_trip_points) {
+				struct scmi_test_setup *tsp_copy;
+
 				scmi_test_sensor_trips_debugfs(sensor_dentry,
 							       tsp,
 					      sdata->sinfo[i]->num_trip_points);
+
+				tsp_copy = scmi_test_tsp_shallow_copy(dev, tsp);
+				if (IS_ERR(tsp_copy))
+					return PTR_ERR(tsp_copy);
+
+				/* Bigger dedicated buffer for notifs */
+				tsp_copy->blen = 4096;
+				debugfs_create_file("sensor_trip_notifs",
+						    0600, sensor_dentry,
+						    tsp_copy,
+						    &test_sensor_trips_fops_rw);
+			}
 		}
 	}
 
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 13/16] firmware: arm_scmi: Add testing Power protocol support
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:56   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

firmware: arm_scmi: Add testing Power protocol support

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 .../arm_scmi/scmi_test_driver/Makefile        |   3 +-
 .../arm_scmi/scmi_test_driver/scmi_test.c     |   2 +
 .../arm_scmi/scmi_test_driver/test_common.h   |   1 +
 .../arm_scmi/scmi_test_driver/test_powers.c   | 105 ++++++++++++++++++
 4 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c

diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
index 458883193f31..68a3d94a6a88 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o
+scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o \
+	test_powers.o
 obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
 
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
index 04e01dd114c9..df0d3e572010 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
@@ -23,6 +23,7 @@ DEFINE_MUTEX(scmi_test_mtx);
 
 static
 int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
+	[SCMI_PROTOCOL_POWER] = scmi_test_power_init,
 	[SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
 	[SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
 };
@@ -126,6 +127,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
 static const struct scmi_device_id scmi_id_table[] = {
 	{ SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
 	{ SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
+	{ SCMI_PROTOCOL_POWER, "__scmi_test-power" },
 	{ },
 };
 MODULE_DEVICE_TABLE(scmi, scmi_id_table);
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index 93c05db0ebff..9f3d35ba4477 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -102,5 +102,6 @@ int scmi_test_release(struct inode *ino, struct file *filp);
 
 int scmi_test_clock_init(struct scmi_test_setup *tsp);
 int scmi_test_sensor_init(struct scmi_test_setup *tsp);
+int scmi_test_power_init(struct scmi_test_setup *tsp);
 
 #endif /* __SCMI_TEST_COMMON_H */
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c
new file mode 100644
index 000000000000..5db1662f2dc7
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver - Power Protocol
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+
+#include "test_common.h"
+
+struct scmi_power_data {
+	unsigned int version;
+	int count;
+};
+
+static ssize_t scmi_test_power_info_read(struct file *filp, char __user *buf,
+					 size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		u32 pstate;
+		char *pname;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_power_proto_ops *power_ops = tsp->ops;
+
+		pname = power_ops->name_get(tsp->ph, data->id);
+		power_ops->state_get(tsp->ph, data->id, &pstate);
+
+		data->used = scnprintf(data->buf, data->len,
+				       "%s -> state:%d\n",
+				       pname, pstate);
+	}
+
+	if (*ppos >= data->used)
+		return 0;
+
+	if (count > data->used)
+		count = data->used;
+
+	count -= copy_to_user(buf, data->buf + *ppos, count);
+	*ppos += count;
+
+	return count;
+}
+
+static const struct file_operations test_power_info_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_power_info_read,
+};
+
+int scmi_test_power_init(struct scmi_test_setup *tsp)
+{
+	int i;
+	struct scmi_power_data *pdata;
+	const struct scmi_power_proto_ops *power_ops;
+	struct device *dev = &tsp->sdev->dev;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	power_ops = tsp->ops;
+	pdata->version = power_ops->version_get(tsp->ph);
+	pdata->count = power_ops->num_domains_get(tsp->ph);
+
+	if (pdata->count <= 0) {
+		dev_err(dev, "number of domains invalid: %d\n",
+			pdata->count);
+		return pdata->count ?: -EINVAL;
+	}
+
+	tsp->priv = pdata;
+	debugfs_create_x32("version", 0400, tsp->parent, &pdata->version);
+
+	dev_info(dev, "Found %d power-domain resources.\n", pdata->count);
+
+	for (i = 0; i < pdata->count; i++) {
+		char power_dir[16];
+		struct dentry *power_dentry;
+
+		snprintf(power_dir, 16, "%03d", i);
+		power_dentry = debugfs_create_dir(power_dir, tsp->parent);
+		if (!IS_ERR(power_dentry)) {
+			debugfs_create_file("info", 0400,
+					    power_dentry, tsp,
+					    &test_power_info_fops);
+		}
+	}
+
+	return 0;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 13/16] firmware: arm_scmi: Add testing Power protocol support
@ 2022-02-27 20:56   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

firmware: arm_scmi: Add testing Power protocol support

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 .../arm_scmi/scmi_test_driver/Makefile        |   3 +-
 .../arm_scmi/scmi_test_driver/scmi_test.c     |   2 +
 .../arm_scmi/scmi_test_driver/test_common.h   |   1 +
 .../arm_scmi/scmi_test_driver/test_powers.c   | 105 ++++++++++++++++++
 4 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c

diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
index 458883193f31..68a3d94a6a88 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o
+scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o \
+	test_powers.o
 obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
 
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
index 04e01dd114c9..df0d3e572010 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
@@ -23,6 +23,7 @@ DEFINE_MUTEX(scmi_test_mtx);
 
 static
 int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
+	[SCMI_PROTOCOL_POWER] = scmi_test_power_init,
 	[SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
 	[SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
 };
@@ -126,6 +127,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
 static const struct scmi_device_id scmi_id_table[] = {
 	{ SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
 	{ SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
+	{ SCMI_PROTOCOL_POWER, "__scmi_test-power" },
 	{ },
 };
 MODULE_DEVICE_TABLE(scmi, scmi_id_table);
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index 93c05db0ebff..9f3d35ba4477 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -102,5 +102,6 @@ int scmi_test_release(struct inode *ino, struct file *filp);
 
 int scmi_test_clock_init(struct scmi_test_setup *tsp);
 int scmi_test_sensor_init(struct scmi_test_setup *tsp);
+int scmi_test_power_init(struct scmi_test_setup *tsp);
 
 #endif /* __SCMI_TEST_COMMON_H */
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c
new file mode 100644
index 000000000000..5db1662f2dc7
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_powers.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver - Power Protocol
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+
+#include "test_common.h"
+
+struct scmi_power_data {
+	unsigned int version;
+	int count;
+};
+
+static ssize_t scmi_test_power_info_read(struct file *filp, char __user *buf,
+					 size_t count, loff_t *ppos)
+{
+	struct scmi_test_buffer *data = filp->private_data;
+
+	if (!data)
+		return 0;
+
+	if (!data->used) {
+		u32 pstate;
+		char *pname;
+		struct scmi_test_setup *tsp = filp->f_inode->i_private;
+		const struct scmi_power_proto_ops *power_ops = tsp->ops;
+
+		pname = power_ops->name_get(tsp->ph, data->id);
+		power_ops->state_get(tsp->ph, data->id, &pstate);
+
+		data->used = scnprintf(data->buf, data->len,
+				       "%s -> state:%d\n",
+				       pname, pstate);
+	}
+
+	if (*ppos >= data->used)
+		return 0;
+
+	if (count > data->used)
+		count = data->used;
+
+	count -= copy_to_user(buf, data->buf + *ppos, count);
+	*ppos += count;
+
+	return count;
+}
+
+static const struct file_operations test_power_info_fops = {
+	.open = scmi_test_setup_open,
+	.release = scmi_test_release,
+	.read = scmi_test_power_info_read,
+};
+
+int scmi_test_power_init(struct scmi_test_setup *tsp)
+{
+	int i;
+	struct scmi_power_data *pdata;
+	const struct scmi_power_proto_ops *power_ops;
+	struct device *dev = &tsp->sdev->dev;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	power_ops = tsp->ops;
+	pdata->version = power_ops->version_get(tsp->ph);
+	pdata->count = power_ops->num_domains_get(tsp->ph);
+
+	if (pdata->count <= 0) {
+		dev_err(dev, "number of domains invalid: %d\n",
+			pdata->count);
+		return pdata->count ?: -EINVAL;
+	}
+
+	tsp->priv = pdata;
+	debugfs_create_x32("version", 0400, tsp->parent, &pdata->version);
+
+	dev_info(dev, "Found %d power-domain resources.\n", pdata->count);
+
+	for (i = 0; i < pdata->count; i++) {
+		char power_dir[16];
+		struct dentry *power_dentry;
+
+		snprintf(power_dir, 16, "%03d", i);
+		power_dentry = debugfs_create_dir(power_dir, tsp->parent);
+		if (!IS_ERR(power_dentry)) {
+			debugfs_create_file("info", 0400,
+					    power_dentry, tsp,
+					    &test_power_info_fops);
+		}
+	}
+
+	return 0;
+}
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 14/16] firmware: arm_scmi: Add testing Voltage protocol support
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:56   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

firmware: arm_scmi: Add testing Voltage protocol support

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 .../arm_scmi/scmi_test_driver/Makefile        |  2 +-
 .../arm_scmi/scmi_test_driver/scmi_test.c     |  2 +
 .../arm_scmi/scmi_test_driver/test_common.h   |  1 +
 .../arm_scmi/scmi_test_driver/test_voltages.c | 51 +++++++++++++++++++
 4 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c

diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
index 68a3d94a6a88..3b7df18de250 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o \
-	test_powers.o
+	test_powers.o test_voltages.o
 obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
 
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
index df0d3e572010..2ca9f82c5bf3 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
@@ -26,6 +26,7 @@ int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
 	[SCMI_PROTOCOL_POWER] = scmi_test_power_init,
 	[SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
 	[SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
+	[SCMI_PROTOCOL_VOLTAGE] = scmi_test_voltage_init,
 };
 
 static void
@@ -125,6 +126,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
 }
 
 static const struct scmi_device_id scmi_id_table[] = {
+	{ SCMI_PROTOCOL_VOLTAGE, "__scmi_test-voltage" },
 	{ SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
 	{ SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
 	{ SCMI_PROTOCOL_POWER, "__scmi_test-power" },
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index 9f3d35ba4477..338b65da593f 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -102,6 +102,7 @@ int scmi_test_release(struct inode *ino, struct file *filp);
 
 int scmi_test_clock_init(struct scmi_test_setup *tsp);
 int scmi_test_sensor_init(struct scmi_test_setup *tsp);
+int scmi_test_voltage_init(struct scmi_test_setup *tsp);
 int scmi_test_power_init(struct scmi_test_setup *tsp);
 
 #endif /* __SCMI_TEST_COMMON_H */
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
new file mode 100644
index 000000000000..ab91080e3a0f
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver - Voltage Protocol
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+
+#include "test_common.h"
+
+struct scmi_voltage_data {
+	unsigned int version;
+	int count;
+};
+
+int scmi_test_voltage_init(struct scmi_test_setup *tsp)
+{
+	struct scmi_voltage_data *vdata;
+	struct device *dev = &tsp->sdev->dev;
+	const struct scmi_voltage_proto_ops *voltage_ops;
+
+	vdata = devm_kzalloc(dev, sizeof(*vdata), GFP_KERNEL);
+	if (!vdata)
+		return -ENOMEM;
+
+	voltage_ops = tsp->ops;
+	vdata->version = voltage_ops->version_get(tsp->ph);
+	vdata->count = voltage_ops->num_domains_get(tsp->ph);
+
+	if (vdata->count <= 0) {
+		dev_err(dev, "number of voltage doms invalid: %d\n",
+			vdata->count);
+		return vdata->count ?: -EINVAL;
+	}
+
+	dev_info(dev, "Found %d voltage resources.\n", vdata->count);
+
+	tsp->priv = vdata;
+	debugfs_create_x32("version", 0400, tsp->parent, &vdata->version);
+
+	return 0;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 14/16] firmware: arm_scmi: Add testing Voltage protocol support
@ 2022-02-27 20:56   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

firmware: arm_scmi: Add testing Voltage protocol support

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 .../arm_scmi/scmi_test_driver/Makefile        |  2 +-
 .../arm_scmi/scmi_test_driver/scmi_test.c     |  2 +
 .../arm_scmi/scmi_test_driver/test_common.h   |  1 +
 .../arm_scmi/scmi_test_driver/test_voltages.c | 51 +++++++++++++++++++
 4 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c

diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
index 68a3d94a6a88..3b7df18de250 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o \
-	test_powers.o
+	test_powers.o test_voltages.o
 obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
 
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
index df0d3e572010..2ca9f82c5bf3 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
@@ -26,6 +26,7 @@ int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
 	[SCMI_PROTOCOL_POWER] = scmi_test_power_init,
 	[SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
 	[SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
+	[SCMI_PROTOCOL_VOLTAGE] = scmi_test_voltage_init,
 };
 
 static void
@@ -125,6 +126,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
 }
 
 static const struct scmi_device_id scmi_id_table[] = {
+	{ SCMI_PROTOCOL_VOLTAGE, "__scmi_test-voltage" },
 	{ SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
 	{ SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
 	{ SCMI_PROTOCOL_POWER, "__scmi_test-power" },
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
index 9f3d35ba4477..338b65da593f 100644
--- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
@@ -102,6 +102,7 @@ int scmi_test_release(struct inode *ino, struct file *filp);
 
 int scmi_test_clock_init(struct scmi_test_setup *tsp);
 int scmi_test_sensor_init(struct scmi_test_setup *tsp);
+int scmi_test_voltage_init(struct scmi_test_setup *tsp);
 int scmi_test_power_init(struct scmi_test_setup *tsp);
 
 #endif /* __SCMI_TEST_COMMON_H */
diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
new file mode 100644
index 000000000000..ab91080e3a0f
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Testing Driver - Voltage Protocol
+ *
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+
+#include "test_common.h"
+
+struct scmi_voltage_data {
+	unsigned int version;
+	int count;
+};
+
+int scmi_test_voltage_init(struct scmi_test_setup *tsp)
+{
+	struct scmi_voltage_data *vdata;
+	struct device *dev = &tsp->sdev->dev;
+	const struct scmi_voltage_proto_ops *voltage_ops;
+
+	vdata = devm_kzalloc(dev, sizeof(*vdata), GFP_KERNEL);
+	if (!vdata)
+		return -ENOMEM;
+
+	voltage_ops = tsp->ops;
+	vdata->version = voltage_ops->version_get(tsp->ph);
+	vdata->count = voltage_ops->num_domains_get(tsp->ph);
+
+	if (vdata->count <= 0) {
+		dev_err(dev, "number of voltage doms invalid: %d\n",
+			vdata->count);
+		return vdata->count ?: -EINVAL;
+	}
+
+	dev_info(dev, "Found %d voltage resources.\n", vdata->count);
+
+	tsp->priv = vdata;
+	debugfs_create_x32("version", 0400, tsp->parent, &vdata->version);
+
+	return 0;
+}
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:56   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

A few initial testcases for Clock and Sensot protocol plus all the test
infrastructure, including the test runeer.

All of this just an experimental demonstrator.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 tools/testing/selftests/arm64/Makefile        |   2 +-
 tools/testing/selftests/arm64/scmi/Makefile   |   6 +
 tools/testing/selftests/arm64/scmi/config     |   1 +
 .../arm64/scmi/kselftest_scmi_lib.sh          | 118 ++++++++++++++++++
 .../selftests/arm64/scmi/run_scmi_tests.sh    |  69 ++++++++++
 .../testcases/protocol_0x14/clock_enable.sh   |  33 +++++
 .../protocol_0x14/clock_rate_read.sh          |  18 +++
 .../protocol_0x14/clock_rate_write.sh         |  29 +++++
 .../testcases/protocol_0x15/sensor_reading.sh |  17 +++
 9 files changed, 292 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/arm64/scmi/Makefile
 create mode 100644 tools/testing/selftests/arm64/scmi/config
 create mode 100644 tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh

diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile
index 1e8d9a8f59df..6648dd8e2173 100644
--- a/tools/testing/selftests/arm64/Makefile
+++ b/tools/testing/selftests/arm64/Makefile
@@ -4,7 +4,7 @@
 ARCH ?= $(shell uname -m 2>/dev/null || echo not)
 
 ifneq (,$(filter $(ARCH),aarch64 arm64))
-ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi
+ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi scmi
 else
 ARM64_SUBTARGETS :=
 endif
diff --git a/tools/testing/selftests/arm64/scmi/Makefile b/tools/testing/selftests/arm64/scmi/Makefile
new file mode 100644
index 000000000000..8786d8d4c332
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+TEST_PROGS := run_scmi_tests.sh
+TEST_FILES := kselftest_scmi_lib.sh testcases/*
+
+include ../../lib.mk
diff --git a/tools/testing/selftests/arm64/scmi/config b/tools/testing/selftests/arm64/scmi/config
new file mode 100644
index 000000000000..161387084a3f
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/config
@@ -0,0 +1 @@
+CONFIG_ARM_SCMI_TEST_DRIVER=y
diff --git a/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
new file mode 100644
index 000000000000..54d27b5f3e1a
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
@@ -0,0 +1,118 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+SCMI_TEST_DRV="scmi_test_driver"
+TRES=(0 0 0)
+
+ksft_log()
+{
+	echo -e "[SCMI]: $1"
+}
+
+ksft_skip()
+{
+	echo -e "[SKIP]: $1"
+	exit 4
+}
+
+ksft_pass()
+{
+	echo -e "[PASS]: $1"
+}
+
+ksft_fail()
+{
+	echo -e "[FAIL]: $1"
+	exit 1
+}
+
+ksft_results()
+{
+	if [ $# -gt 0 ]; then
+		local val
+		local idx
+		local ret=$1
+
+		case "$ret" in
+			0)
+				idx=0
+				;;
+			4)
+				idx=1
+				;;
+			*)
+				idx=2
+				;;
+		esac
+		val=${TRES[${idx}]}
+		TRES[$idx]=$((val + 1))
+	else
+		ksft_log "Summary - PASS[${TRES[0]}]  SKIP[${TRES[1]}]  FAIL[${TRES[2]}]"
+		[ "x${TRES[2]}" != "x0" ] && exit 1
+		[ "x${TRES[1]}" != "x0" -a "x${TRES[0]}" == "x0" ] && exit 4
+		exit 0
+	fi
+}
+
+ksft_scmi_run_one()
+{
+	tcase=$1
+
+	echo "-> Running testcase: $tcase"
+
+	./$tcase
+       ret=$?
+
+       ksft_results $ret
+}
+
+ksft_scmi_check_fw_version()
+{
+	local supported=$1
+	local current="${SCMI_VENDOR}:${SCMI_SUB_VENDOR}"
+
+	if [ "x${current}" != "x${supported}" ]; then
+		ksft_skip "Current FW('$current') is UNSUPPORTED. Should be '$supported'"
+	fi
+}
+
+ksft_scmi_transport_is_atomic ()
+{
+	[ "x$SCMI_TRANSPORT_IS_ATOMIC" == "xY" ] && return 0 || return 1
+}
+
+ksft_scmi_protocol_resources_get()
+{
+	local proto_dir=$1
+	local resources=""
+
+	for d in ${proto_dir}/*; do
+		rd="$(basename $d)"
+		[[ $rd =~ [0-9] ]] && resources="$resources $rd"
+	done
+
+	echo "$resources"
+}
+
+ksft_scmi_value_get()
+{
+	local syspath=$1
+	local __retval=$2
+	local value
+
+	value=$(cat $syspath)
+	[ "x$?" != "x0" ] && ksft_fail "Fail to read $syspath"
+
+	eval $__retval="'$value'"
+}
+
+ksft_scmi_value_set()
+{
+	local syspath=$1
+	local value=$2
+
+	echo $value > $syspath
+	[ "x$?" != "x0" ] && ksft_fail "Fail to write $syspath - err:$?"
+}
+
+
diff --git a/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
new file mode 100755
index 000000000000..f372744a4579
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. ./kselftest_scmi_lib.sh
+
+check_root_privs()
+{
+	[ x"$(id -u)" != "x0" ] && ksft_skip "You need to be root"
+}
+
+check_scmi_testing_stack()
+{
+	local debugfs_root=$(findmnt -o TARGET -t debugfs | grep -v TARGET)
+	export SCMI_DEBUGFS_TOPDIR="$debugfs_root/scmi"
+
+	# Try to load module if not builtin
+	if [ ! -d $SCMI_DEBUGFS_TOPDIR ]; then
+		modprobe $SCMI_TEST_DRV || ksft_skip "Failed to load $SCMI_TEST_DRV"
+		[ ! -d $SCMI_DEBUGFS_TOPDIR ] && ksft_skip "SCMI Test stack not found; is CONFIG_ARM_SCMI_TEST_DRIVER enabled ?"
+	fi
+}
+
+setup_scmi_test_env()
+{
+	local scmi_info_dir="${SCMI_DEBUGFS_TOPDIR}/info/"
+
+	export SCMI_VENDOR="$(cat ${scmi_info_dir}/vendor_id)"
+	export SCMI_SUB_VENDOR="$(cat ${scmi_info_dir}/sub_vendor_id)"
+	export SCMI_VERS_MAJ="$(cat ${scmi_info_dir}/major_ver)"
+	export SCMI_VERS_MIN="$(cat ${scmi_info_dir}/minor_ver)"
+	export SCMI_VERS_IMPL="$(cat ${scmi_info_dir}/impl_ver)"
+
+	ksft_log "Found stack: $SCMI_VENDOR/$SCMI_SUB_VENDOR ${SCMI_VERS_MAJ}.${SCMI_VERS_MAJ} - $SCMI_VERS_IMPL"
+
+	SCMI_TEST_PROTOS=""
+	for p in ${SCMI_DEBUGFS_TOPDIR}/protocol_*; do
+		SCMI_TEST_PROTOS="${SCMI_TEST_PROTOS} $(basename $p)"
+	done
+
+	ksft_log "Found testing protocols: $SCMI_TEST_PROTOS"
+
+	export SCMI_TEST_PROTOS
+	SCMI_TRANSPORT_IS_ATOMIC="N"
+	[ -d "${SCMI_DEBUGFS_TOPDIR}/transport" ] &&
+		SCMI_TRANSPORT_IS_ATOMIC=$(cat "${SCMI_DEBUGFS_TOPDIR}/transport/is_atomic")
+	export SCMI_TRANSPORT_IS_ATOMIC
+}
+
+# Setup
+check_root_privs
+
+check_scmi_testing_stack
+
+setup_scmi_test_env
+
+# Main
+# Run all available tests for the found protocols
+#
+for proto_dir in $SCMI_TEST_PROTOS; do
+	[ ! -d $proto_dir ] && ksft_log "$proto_dir tests NOT supported." && continue
+	export TST_PROTO_DIR="${SCMI_DEBUGFS_TOPDIR}/${proto_dir}"
+	TST_PROTO_VERSION=$(cat ${TST_PROTO_DIR}/version)
+	ksft_log "Running tests for SCMI $proto_dir ver:$TST_PROTO_VERSION"
+	for tst in $proto_dir/*; do
+		ksft_scmi_run_one $tst
+	done
+done
+
+ksft_results
diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
new file mode 100755
index 000000000000..4cdf3a097ba7
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. ./kselftest_scmi_lib.sh
+
+supported_fw="EMU-SCMI-VM:userland"
+ksft_scmi_check_fw_version $supported_fw
+
+clock_enable_disable() {
+	rname=$1
+	rdir=$2
+	clk_op=$3
+
+	ksft_scmi_value_set $rdir/$clk_op Y
+	ksft_scmi_value_set $rdir/$clk_op N
+	ksft_log "Clock $rname: $clk_op - ON/OFF ... OK"
+}
+
+resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
+ksft_log "Found Clock resources: $resources"
+
+for res in $resources;do
+	resd="$TST_PROTO_DIR/$res"
+	name="$(cat $resd/info/name)"
+
+	clock_enable_disable $name $resd "enable"
+	if [ ksft_transport_is_atomic ]; then
+		clock_enable_disable $name $resd "enable_atomic_irqs_off"
+		clock_enable_disable $name $resd "enable_atomic_irqs_on"
+	fi
+done
+
+ksft_pass "$0"
diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
new file mode 100755
index 000000000000..88c444fd317d
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. ./kselftest_scmi_lib.sh
+
+resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
+ksft_log "Found Clock resources: $resources"
+
+for res in $resources;do
+	resd="$TST_PROTO_DIR/$res"
+	name="$(cat $resd/info/name)"
+	val=0
+
+	ksft_scmi_value_get $resd/rate_get_set val
+	ksft_log "$name READ => $val"
+done
+
+ksft_pass "$0"
diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
new file mode 100755
index 000000000000..346084ec3812
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. ./kselftest_scmi_lib.sh
+
+supported_fw="EMU-SCMI-VM:userland"
+ksft_scmi_check_fw_version $supported_fw
+
+resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
+ksft_log "Found Clock resources: $resources"
+
+for res in $resources;do
+	resd="$TST_PROTO_DIR/$res"
+	name="$(cat $resd/info/name)"
+	val=0
+	oldval=0
+	setval=0
+
+	ksft_scmi_value_get $resd/rate_get_set oldval
+	setval=$((oldval + 666))
+
+	ksft_scmi_value_set $resd/rate_get_set $setval
+
+	ksft_scmi_value_get $resd/rate_get_set val
+	[ "x$val" != "x$setval" ] && ksft_fail "Set:$setval readback:$val"
+	ksft_log "$name OK -> read:$oldval  set:$setval  readback:$val"
+done
+
+ksft_pass "$0"
diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
new file mode 100755
index 000000000000..b0f5f6361379
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+. ./kselftest_scmi_lib.sh
+
+resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
+ksft_log "Found Sensor resources: $resources"
+
+for res in $resources;do
+	resd="$TST_PROTO_DIR/$res"
+	name="$(cat $resd/info/name)"
+	val=0
+
+	ksft_scmi_value_get $resd/reading_get val
+	ksft_log "$name READ => $val"
+done
+
+ksft_pass $0
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases
@ 2022-02-27 20:56   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

A few initial testcases for Clock and Sensot protocol plus all the test
infrastructure, including the test runeer.

All of this just an experimental demonstrator.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 tools/testing/selftests/arm64/Makefile        |   2 +-
 tools/testing/selftests/arm64/scmi/Makefile   |   6 +
 tools/testing/selftests/arm64/scmi/config     |   1 +
 .../arm64/scmi/kselftest_scmi_lib.sh          | 118 ++++++++++++++++++
 .../selftests/arm64/scmi/run_scmi_tests.sh    |  69 ++++++++++
 .../testcases/protocol_0x14/clock_enable.sh   |  33 +++++
 .../protocol_0x14/clock_rate_read.sh          |  18 +++
 .../protocol_0x14/clock_rate_write.sh         |  29 +++++
 .../testcases/protocol_0x15/sensor_reading.sh |  17 +++
 9 files changed, 292 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/arm64/scmi/Makefile
 create mode 100644 tools/testing/selftests/arm64/scmi/config
 create mode 100644 tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
 create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh

diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile
index 1e8d9a8f59df..6648dd8e2173 100644
--- a/tools/testing/selftests/arm64/Makefile
+++ b/tools/testing/selftests/arm64/Makefile
@@ -4,7 +4,7 @@
 ARCH ?= $(shell uname -m 2>/dev/null || echo not)
 
 ifneq (,$(filter $(ARCH),aarch64 arm64))
-ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi
+ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi scmi
 else
 ARM64_SUBTARGETS :=
 endif
diff --git a/tools/testing/selftests/arm64/scmi/Makefile b/tools/testing/selftests/arm64/scmi/Makefile
new file mode 100644
index 000000000000..8786d8d4c332
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+TEST_PROGS := run_scmi_tests.sh
+TEST_FILES := kselftest_scmi_lib.sh testcases/*
+
+include ../../lib.mk
diff --git a/tools/testing/selftests/arm64/scmi/config b/tools/testing/selftests/arm64/scmi/config
new file mode 100644
index 000000000000..161387084a3f
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/config
@@ -0,0 +1 @@
+CONFIG_ARM_SCMI_TEST_DRIVER=y
diff --git a/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
new file mode 100644
index 000000000000..54d27b5f3e1a
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
@@ -0,0 +1,118 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+SCMI_TEST_DRV="scmi_test_driver"
+TRES=(0 0 0)
+
+ksft_log()
+{
+	echo -e "[SCMI]: $1"
+}
+
+ksft_skip()
+{
+	echo -e "[SKIP]: $1"
+	exit 4
+}
+
+ksft_pass()
+{
+	echo -e "[PASS]: $1"
+}
+
+ksft_fail()
+{
+	echo -e "[FAIL]: $1"
+	exit 1
+}
+
+ksft_results()
+{
+	if [ $# -gt 0 ]; then
+		local val
+		local idx
+		local ret=$1
+
+		case "$ret" in
+			0)
+				idx=0
+				;;
+			4)
+				idx=1
+				;;
+			*)
+				idx=2
+				;;
+		esac
+		val=${TRES[${idx}]}
+		TRES[$idx]=$((val + 1))
+	else
+		ksft_log "Summary - PASS[${TRES[0]}]  SKIP[${TRES[1]}]  FAIL[${TRES[2]}]"
+		[ "x${TRES[2]}" != "x0" ] && exit 1
+		[ "x${TRES[1]}" != "x0" -a "x${TRES[0]}" == "x0" ] && exit 4
+		exit 0
+	fi
+}
+
+ksft_scmi_run_one()
+{
+	tcase=$1
+
+	echo "-> Running testcase: $tcase"
+
+	./$tcase
+       ret=$?
+
+       ksft_results $ret
+}
+
+ksft_scmi_check_fw_version()
+{
+	local supported=$1
+	local current="${SCMI_VENDOR}:${SCMI_SUB_VENDOR}"
+
+	if [ "x${current}" != "x${supported}" ]; then
+		ksft_skip "Current FW('$current') is UNSUPPORTED. Should be '$supported'"
+	fi
+}
+
+ksft_scmi_transport_is_atomic ()
+{
+	[ "x$SCMI_TRANSPORT_IS_ATOMIC" == "xY" ] && return 0 || return 1
+}
+
+ksft_scmi_protocol_resources_get()
+{
+	local proto_dir=$1
+	local resources=""
+
+	for d in ${proto_dir}/*; do
+		rd="$(basename $d)"
+		[[ $rd =~ [0-9] ]] && resources="$resources $rd"
+	done
+
+	echo "$resources"
+}
+
+ksft_scmi_value_get()
+{
+	local syspath=$1
+	local __retval=$2
+	local value
+
+	value=$(cat $syspath)
+	[ "x$?" != "x0" ] && ksft_fail "Fail to read $syspath"
+
+	eval $__retval="'$value'"
+}
+
+ksft_scmi_value_set()
+{
+	local syspath=$1
+	local value=$2
+
+	echo $value > $syspath
+	[ "x$?" != "x0" ] && ksft_fail "Fail to write $syspath - err:$?"
+}
+
+
diff --git a/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
new file mode 100755
index 000000000000..f372744a4579
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. ./kselftest_scmi_lib.sh
+
+check_root_privs()
+{
+	[ x"$(id -u)" != "x0" ] && ksft_skip "You need to be root"
+}
+
+check_scmi_testing_stack()
+{
+	local debugfs_root=$(findmnt -o TARGET -t debugfs | grep -v TARGET)
+	export SCMI_DEBUGFS_TOPDIR="$debugfs_root/scmi"
+
+	# Try to load module if not builtin
+	if [ ! -d $SCMI_DEBUGFS_TOPDIR ]; then
+		modprobe $SCMI_TEST_DRV || ksft_skip "Failed to load $SCMI_TEST_DRV"
+		[ ! -d $SCMI_DEBUGFS_TOPDIR ] && ksft_skip "SCMI Test stack not found; is CONFIG_ARM_SCMI_TEST_DRIVER enabled ?"
+	fi
+}
+
+setup_scmi_test_env()
+{
+	local scmi_info_dir="${SCMI_DEBUGFS_TOPDIR}/info/"
+
+	export SCMI_VENDOR="$(cat ${scmi_info_dir}/vendor_id)"
+	export SCMI_SUB_VENDOR="$(cat ${scmi_info_dir}/sub_vendor_id)"
+	export SCMI_VERS_MAJ="$(cat ${scmi_info_dir}/major_ver)"
+	export SCMI_VERS_MIN="$(cat ${scmi_info_dir}/minor_ver)"
+	export SCMI_VERS_IMPL="$(cat ${scmi_info_dir}/impl_ver)"
+
+	ksft_log "Found stack: $SCMI_VENDOR/$SCMI_SUB_VENDOR ${SCMI_VERS_MAJ}.${SCMI_VERS_MAJ} - $SCMI_VERS_IMPL"
+
+	SCMI_TEST_PROTOS=""
+	for p in ${SCMI_DEBUGFS_TOPDIR}/protocol_*; do
+		SCMI_TEST_PROTOS="${SCMI_TEST_PROTOS} $(basename $p)"
+	done
+
+	ksft_log "Found testing protocols: $SCMI_TEST_PROTOS"
+
+	export SCMI_TEST_PROTOS
+	SCMI_TRANSPORT_IS_ATOMIC="N"
+	[ -d "${SCMI_DEBUGFS_TOPDIR}/transport" ] &&
+		SCMI_TRANSPORT_IS_ATOMIC=$(cat "${SCMI_DEBUGFS_TOPDIR}/transport/is_atomic")
+	export SCMI_TRANSPORT_IS_ATOMIC
+}
+
+# Setup
+check_root_privs
+
+check_scmi_testing_stack
+
+setup_scmi_test_env
+
+# Main
+# Run all available tests for the found protocols
+#
+for proto_dir in $SCMI_TEST_PROTOS; do
+	[ ! -d $proto_dir ] && ksft_log "$proto_dir tests NOT supported." && continue
+	export TST_PROTO_DIR="${SCMI_DEBUGFS_TOPDIR}/${proto_dir}"
+	TST_PROTO_VERSION=$(cat ${TST_PROTO_DIR}/version)
+	ksft_log "Running tests for SCMI $proto_dir ver:$TST_PROTO_VERSION"
+	for tst in $proto_dir/*; do
+		ksft_scmi_run_one $tst
+	done
+done
+
+ksft_results
diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
new file mode 100755
index 000000000000..4cdf3a097ba7
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. ./kselftest_scmi_lib.sh
+
+supported_fw="EMU-SCMI-VM:userland"
+ksft_scmi_check_fw_version $supported_fw
+
+clock_enable_disable() {
+	rname=$1
+	rdir=$2
+	clk_op=$3
+
+	ksft_scmi_value_set $rdir/$clk_op Y
+	ksft_scmi_value_set $rdir/$clk_op N
+	ksft_log "Clock $rname: $clk_op - ON/OFF ... OK"
+}
+
+resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
+ksft_log "Found Clock resources: $resources"
+
+for res in $resources;do
+	resd="$TST_PROTO_DIR/$res"
+	name="$(cat $resd/info/name)"
+
+	clock_enable_disable $name $resd "enable"
+	if [ ksft_transport_is_atomic ]; then
+		clock_enable_disable $name $resd "enable_atomic_irqs_off"
+		clock_enable_disable $name $resd "enable_atomic_irqs_on"
+	fi
+done
+
+ksft_pass "$0"
diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
new file mode 100755
index 000000000000..88c444fd317d
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. ./kselftest_scmi_lib.sh
+
+resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
+ksft_log "Found Clock resources: $resources"
+
+for res in $resources;do
+	resd="$TST_PROTO_DIR/$res"
+	name="$(cat $resd/info/name)"
+	val=0
+
+	ksft_scmi_value_get $resd/rate_get_set val
+	ksft_log "$name READ => $val"
+done
+
+ksft_pass "$0"
diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
new file mode 100755
index 000000000000..346084ec3812
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. ./kselftest_scmi_lib.sh
+
+supported_fw="EMU-SCMI-VM:userland"
+ksft_scmi_check_fw_version $supported_fw
+
+resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
+ksft_log "Found Clock resources: $resources"
+
+for res in $resources;do
+	resd="$TST_PROTO_DIR/$res"
+	name="$(cat $resd/info/name)"
+	val=0
+	oldval=0
+	setval=0
+
+	ksft_scmi_value_get $resd/rate_get_set oldval
+	setval=$((oldval + 666))
+
+	ksft_scmi_value_set $resd/rate_get_set $setval
+
+	ksft_scmi_value_get $resd/rate_get_set val
+	[ "x$val" != "x$setval" ] && ksft_fail "Set:$setval readback:$val"
+	ksft_log "$name OK -> read:$oldval  set:$setval  readback:$val"
+done
+
+ksft_pass "$0"
diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
new file mode 100755
index 000000000000..b0f5f6361379
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+. ./kselftest_scmi_lib.sh
+
+resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
+ksft_log "Found Sensor resources: $resources"
+
+for res in $resources;do
+	resd="$TST_PROTO_DIR/$res"
+	name="$(cat $resd/info/name)"
+	val=0
+
+	ksft_scmi_value_get $resd/reading_get val
+	ksft_log "$name READ => $val"
+done
+
+ksft_pass $0
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 16/16] [DEBUG]: firmware: arm_scmi: Add Kconfig to allow SCMI Testing driver coexistence
  2022-02-27 20:55 ` Cristian Marussi
@ 2022-02-27 20:56   ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

firmware: arm_scmi: Add Kconfig to allow SCMI Testing driver coexistence

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/Kconfig  |  6 ++++++
 drivers/firmware/arm_scmi/driver.c | 15 ++++++++-------
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
index a3726074c89e..c3fc608d5373 100644
--- a/drivers/firmware/arm_scmi/Kconfig
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -160,4 +160,10 @@ config ARM_SCMI_TEST_DRIVER
 	  This driver can also be built as a module.  If so, the module
 	  will be called scmi_test_driver.
 
+config ARM_SCMI_TEST_DRIVER_COEXISTENCE
+	bool "Allow Coexistence of SCMI standard drivers and test driver"
+	depends on ARM_SCMI_TEST_DRIVER
+	help
+	  This enables coexistence for concurrent SCMI drievrs and testing driver.
+
 endmenu
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 8c4706b24368..ff692c458a0b 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1782,14 +1782,15 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 	pr_debug("Requesting SCMI device (%s) for protocol %x\n",
 		 id_table->name, id_table->protocol_id);
 
-#if IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER)
-	/* Reject non-testing SCMI drivers */
-	if (strncmp(id_table->name, "__scmi_test", strlen("__scmi_test"))) {
-		pr_warn("SCMI Test driver loaded. Rejecting '%s'/0x%X\n",
-			id_table->name, id_table->protocol_id);
-		return -EINVAL;
+	if (IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER) &&
+	    !IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER_COEXISTENCE)) {
+		/* Reject non-testing SCMI drivers */
+		if (strncmp(id_table->name, "__scmi_test", strlen("__scmi_test"))) {
+			pr_warn("SCMI Test driver loaded. Rejecting driver: '%s'/0x%X\n",
+				id_table->name, id_table->protocol_id);
+			return -EBUSY;
+		}
 	}
-#endif
 
 	/*
 	 * Search for the matching protocol rdev list and then search
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [RFC PATCH 16/16] [DEBUG]: firmware: arm_scmi: Add Kconfig to allow SCMI Testing driver coexistence
@ 2022-02-27 20:56   ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-02-27 20:56 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, james.quinlan, Jonathan.Cameron, f.fainelli,
	vincent.guittot, souvik.chakravarty, peter.hilber,
	cristian.marussi

firmware: arm_scmi: Add Kconfig to allow SCMI Testing driver coexistence

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/Kconfig  |  6 ++++++
 drivers/firmware/arm_scmi/driver.c | 15 ++++++++-------
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
index a3726074c89e..c3fc608d5373 100644
--- a/drivers/firmware/arm_scmi/Kconfig
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -160,4 +160,10 @@ config ARM_SCMI_TEST_DRIVER
 	  This driver can also be built as a module.  If so, the module
 	  will be called scmi_test_driver.
 
+config ARM_SCMI_TEST_DRIVER_COEXISTENCE
+	bool "Allow Coexistence of SCMI standard drivers and test driver"
+	depends on ARM_SCMI_TEST_DRIVER
+	help
+	  This enables coexistence for concurrent SCMI drievrs and testing driver.
+
 endmenu
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 8c4706b24368..ff692c458a0b 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1782,14 +1782,15 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 	pr_debug("Requesting SCMI device (%s) for protocol %x\n",
 		 id_table->name, id_table->protocol_id);
 
-#if IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER)
-	/* Reject non-testing SCMI drivers */
-	if (strncmp(id_table->name, "__scmi_test", strlen("__scmi_test"))) {
-		pr_warn("SCMI Test driver loaded. Rejecting '%s'/0x%X\n",
-			id_table->name, id_table->protocol_id);
-		return -EINVAL;
+	if (IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER) &&
+	    !IS_ENABLED(CONFIG_ARM_SCMI_TEST_DRIVER_COEXISTENCE)) {
+		/* Reject non-testing SCMI drivers */
+		if (strncmp(id_table->name, "__scmi_test", strlen("__scmi_test"))) {
+			pr_warn("SCMI Test driver loaded. Rejecting driver: '%s'/0x%X\n",
+				id_table->name, id_table->protocol_id);
+			return -EBUSY;
+		}
 	}
-#endif
 
 	/*
 	 * Search for the matching protocol rdev list and then search
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers
  2022-02-27 20:55   ` Cristian Marussi
@ 2022-03-18 13:21     ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 50+ messages in thread
From: Greg Kroah-Hartman @ 2022-03-18 13:21 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Rafael J. Wysocki,
	Alexander Viro

On Sun, Feb 27, 2022 at 08:55:59PM +0000, Cristian Marussi wrote:
> Add a few helpers to deal with signed values integers; built on existing
> debugfs internal helpers as the existing unsigned functions already do.
> 
> Make the simple_attr_write() internal helper detect the sign of the
> requested set operation from the related format string: this is needed
> to be able to properly parse negatively signed input strings.
> 
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> ---
> Note that in the rest of the series I do NOT need the s64 WRITE/SET
> operations, that required the more invasive simple_attr_write() change,
> but it seemed odd to implement a get only debug_create_s32/64 API.

Let's wait to add them when we have a need for them with a in-kernel
user.  Otherwise I'll just end up removing them eventually when I sweep
for "is this used" cleanups.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers
@ 2022-03-18 13:21     ` Greg Kroah-Hartman
  0 siblings, 0 replies; 50+ messages in thread
From: Greg Kroah-Hartman @ 2022-03-18 13:21 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Rafael J. Wysocki,
	Alexander Viro

On Sun, Feb 27, 2022 at 08:55:59PM +0000, Cristian Marussi wrote:
> Add a few helpers to deal with signed values integers; built on existing
> debugfs internal helpers as the existing unsigned functions already do.
> 
> Make the simple_attr_write() internal helper detect the sign of the
> requested set operation from the related format string: this is needed
> to be able to properly parse negatively signed input strings.
> 
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> ---
> Note that in the rest of the series I do NOT need the s64 WRITE/SET
> operations, that required the more invasive simple_attr_write() change,
> but it seemed odd to implement a get only debug_create_s32/64 API.

Let's wait to add them when we have a need for them with a in-kernel
user.  Otherwise I'll just end up removing them eventually when I sweep
for "is this used" cleanups.

thanks,

greg k-h

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers
  2022-03-18 13:21     ` Greg Kroah-Hartman
@ 2022-03-18 15:39       ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-03-18 15:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Rafael J. Wysocki,
	Alexander Viro

On Fri, Mar 18, 2022 at 02:21:32PM +0100, Greg Kroah-Hartman wrote:
> On Sun, Feb 27, 2022 at 08:55:59PM +0000, Cristian Marussi wrote:
> > Add a few helpers to deal with signed values integers; built on existing
> > debugfs internal helpers as the existing unsigned functions already do.
> > 
> > Make the simple_attr_write() internal helper detect the sign of the
> > requested set operation from the related format string: this is needed
> > to be able to properly parse negatively signed input strings.
> > 
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> > Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> > Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> > ---

Hi Greg,

thanks for the feedback.

> > Note that in the rest of the series I do NOT need the s64 WRITE/SET
> > operations, that required the more invasive simple_attr_write() change,
> > but it seemed odd to implement a get only debug_create_s32/64 API.
> 
> Let's wait to add them when we have a need for them with a in-kernel
> user.  Otherwise I'll just end up removing them eventually when I sweep
> for "is this used" cleanups.
> 

Ok, so just to double check what I understood(or not), I'll leave out the
setters ops and implement instead the debufs_create_s32/s64 with only RO
fops support, right ?

Thanks,
Cristian

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers
@ 2022-03-18 15:39       ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-03-18 15:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Rafael J. Wysocki,
	Alexander Viro

On Fri, Mar 18, 2022 at 02:21:32PM +0100, Greg Kroah-Hartman wrote:
> On Sun, Feb 27, 2022 at 08:55:59PM +0000, Cristian Marussi wrote:
> > Add a few helpers to deal with signed values integers; built on existing
> > debugfs internal helpers as the existing unsigned functions already do.
> > 
> > Make the simple_attr_write() internal helper detect the sign of the
> > requested set operation from the related format string: this is needed
> > to be able to properly parse negatively signed input strings.
> > 
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> > Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> > Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> > ---

Hi Greg,

thanks for the feedback.

> > Note that in the rest of the series I do NOT need the s64 WRITE/SET
> > operations, that required the more invasive simple_attr_write() change,
> > but it seemed odd to implement a get only debug_create_s32/64 API.
> 
> Let's wait to add them when we have a need for them with a in-kernel
> user.  Otherwise I'll just end up removing them eventually when I sweep
> for "is this used" cleanups.
> 

Ok, so just to double check what I understood(or not), I'll leave out the
setters ops and implement instead the debufs_create_s32/s64 with only RO
fops support, right ?

Thanks,
Cristian

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers
  2022-03-18 15:39       ` Cristian Marussi
@ 2022-03-18 15:49         ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 50+ messages in thread
From: Greg Kroah-Hartman @ 2022-03-18 15:49 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Rafael J. Wysocki,
	Alexander Viro

On Fri, Mar 18, 2022 at 03:39:40PM +0000, Cristian Marussi wrote:
> On Fri, Mar 18, 2022 at 02:21:32PM +0100, Greg Kroah-Hartman wrote:
> > On Sun, Feb 27, 2022 at 08:55:59PM +0000, Cristian Marussi wrote:
> > > Add a few helpers to deal with signed values integers; built on existing
> > > debugfs internal helpers as the existing unsigned functions already do.
> > > 
> > > Make the simple_attr_write() internal helper detect the sign of the
> > > requested set operation from the related format string: this is needed
> > > to be able to properly parse negatively signed input strings.
> > > 
> > > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> > > Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> > > Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> > > ---
> 
> Hi Greg,
> 
> thanks for the feedback.
> 
> > > Note that in the rest of the series I do NOT need the s64 WRITE/SET
> > > operations, that required the more invasive simple_attr_write() change,
> > > but it seemed odd to implement a get only debug_create_s32/64 API.
> > 
> > Let's wait to add them when we have a need for them with a in-kernel
> > user.  Otherwise I'll just end up removing them eventually when I sweep
> > for "is this used" cleanups.
> > 
> 
> Ok, so just to double check what I understood(or not), I'll leave out the
> setters ops and implement instead the debufs_create_s32/s64 with only RO
> fops support, right ?

Only create what you actually need.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers
@ 2022-03-18 15:49         ` Greg Kroah-Hartman
  0 siblings, 0 replies; 50+ messages in thread
From: Greg Kroah-Hartman @ 2022-03-18 15:49 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Rafael J. Wysocki,
	Alexander Viro

On Fri, Mar 18, 2022 at 03:39:40PM +0000, Cristian Marussi wrote:
> On Fri, Mar 18, 2022 at 02:21:32PM +0100, Greg Kroah-Hartman wrote:
> > On Sun, Feb 27, 2022 at 08:55:59PM +0000, Cristian Marussi wrote:
> > > Add a few helpers to deal with signed values integers; built on existing
> > > debugfs internal helpers as the existing unsigned functions already do.
> > > 
> > > Make the simple_attr_write() internal helper detect the sign of the
> > > requested set operation from the related format string: this is needed
> > > to be able to properly parse negatively signed input strings.
> > > 
> > > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> > > Cc: Alexander Viro <viro@zeniv.linux.org.uk>
> > > Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> > > ---
> 
> Hi Greg,
> 
> thanks for the feedback.
> 
> > > Note that in the rest of the series I do NOT need the s64 WRITE/SET
> > > operations, that required the more invasive simple_attr_write() change,
> > > but it seemed odd to implement a get only debug_create_s32/64 API.
> > 
> > Let's wait to add them when we have a need for them with a in-kernel
> > user.  Otherwise I'll just end up removing them eventually when I sweep
> > for "is this used" cleanups.
> > 
> 
> Ok, so just to double check what I understood(or not), I'll leave out the
> setters ops and implement instead the debufs_create_s32/s64 with only RO
> fops support, right ?

Only create what you actually need.

thanks,

greg k-h

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 14/16] firmware: arm_scmi: Add testing Voltage protocol support
  2022-02-27 20:56   ` Cristian Marussi
@ 2022-08-01  4:47     ` Arun KS
  -1 siblings, 0 replies; 50+ messages in thread
From: Arun KS @ 2022-08-01  4:47 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber

Hi Cristian,

On Mon, Feb 28, 2022 at 4:23 AM Cristian Marussi
<cristian.marussi@arm.com> wrote:
>
> firmware: arm_scmi: Add testing Voltage protocol support
>
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> ---
>  .../arm_scmi/scmi_test_driver/Makefile        |  2 +-
>  .../arm_scmi/scmi_test_driver/scmi_test.c     |  2 +
>  .../arm_scmi/scmi_test_driver/test_common.h   |  1 +
>  .../arm_scmi/scmi_test_driver/test_voltages.c | 51 +++++++++++++++++++
>  4 files changed, 55 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
>
> diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> index 68a3d94a6a88..3b7df18de250 100644
> --- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> +++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> @@ -1,5 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o \
> -       test_powers.o
> +       test_powers.o test_voltages.o
>  obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
>
> diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> index df0d3e572010..2ca9f82c5bf3 100644
> --- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> +++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> @@ -26,6 +26,7 @@ int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
>         [SCMI_PROTOCOL_POWER] = scmi_test_power_init,
>         [SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
>         [SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
> +       [SCMI_PROTOCOL_VOLTAGE] = scmi_test_voltage_init,
>  };
>
>  static void
> @@ -125,6 +126,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
>  }
>
>  static const struct scmi_device_id scmi_id_table[] = {
> +       { SCMI_PROTOCOL_VOLTAGE, "__scmi_test-voltage" },
>         { SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
>         { SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
>         { SCMI_PROTOCOL_POWER, "__scmi_test-power" },
> diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> index 9f3d35ba4477..338b65da593f 100644
> --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> @@ -102,6 +102,7 @@ int scmi_test_release(struct inode *ino, struct file *filp);
>
>  int scmi_test_clock_init(struct scmi_test_setup *tsp);
>  int scmi_test_sensor_init(struct scmi_test_setup *tsp);
> +int scmi_test_voltage_init(struct scmi_test_setup *tsp);
>  int scmi_test_power_init(struct scmi_test_setup *tsp);
>
>  #endif /* __SCMI_TEST_COMMON_H */
> diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> new file mode 100644
> index 000000000000..ab91080e3a0f
> --- /dev/null
> +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> @@ -0,0 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * SCMI Testing Driver - Voltage Protocol
> + *
> + * Copyright (C) 2022 ARM Ltd.
> + */
> +
> +#include <linux/dcache.h>
> +#include <linux/debugfs.h>
> +#include <linux/err.h>
> +#include <linux/fs.h>
> +#include <linux/io.h>
> +#include <linux/kstrtox.h>
> +#include <linux/module.h>
> +#include <linux/scmi_protocol.h>
> +#include <linux/slab.h>
> +
> +#include "test_common.h"
> +
> +struct scmi_voltage_data {
> +       unsigned int version;
> +       int count;
> +};
> +
> +int scmi_test_voltage_init(struct scmi_test_setup *tsp)
> +{
> +       struct scmi_voltage_data *vdata;
> +       struct device *dev = &tsp->sdev->dev;
> +       const struct scmi_voltage_proto_ops *voltage_ops;
> +
> +       vdata = devm_kzalloc(dev, sizeof(*vdata), GFP_KERNEL);
> +       if (!vdata)
> +               return -ENOMEM;
> +
> +       voltage_ops = tsp->ops;
> +       vdata->version = voltage_ops->version_get(tsp->ph);
> +       vdata->count = voltage_ops->num_domains_get(tsp->ph);
> +
> +       if (vdata->count <= 0) {
> +               dev_err(dev, "number of voltage doms invalid: %d\n",
> +                       vdata->count);
> +               return vdata->count ?: -EINVAL;
> +       }
> +
> +       dev_info(dev, "Found %d voltage resources.\n", vdata->count);
> +
> +       tsp->priv = vdata;
> +       debugfs_create_x32("version", 0400, tsp->parent, &vdata->version);
Any particular reason, why we are not creating debugfs entires for
regulator level_get/level_set like it was done for
clocks(rate_get_set)?
> +
> +       return 0;
> +}
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 14/16] firmware: arm_scmi: Add testing Voltage protocol support
@ 2022-08-01  4:47     ` Arun KS
  0 siblings, 0 replies; 50+ messages in thread
From: Arun KS @ 2022-08-01  4:47 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber

Hi Cristian,

On Mon, Feb 28, 2022 at 4:23 AM Cristian Marussi
<cristian.marussi@arm.com> wrote:
>
> firmware: arm_scmi: Add testing Voltage protocol support
>
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> ---
>  .../arm_scmi/scmi_test_driver/Makefile        |  2 +-
>  .../arm_scmi/scmi_test_driver/scmi_test.c     |  2 +
>  .../arm_scmi/scmi_test_driver/test_common.h   |  1 +
>  .../arm_scmi/scmi_test_driver/test_voltages.c | 51 +++++++++++++++++++
>  4 files changed, 55 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
>
> diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> index 68a3d94a6a88..3b7df18de250 100644
> --- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> +++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> @@ -1,5 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o \
> -       test_powers.o
> +       test_powers.o test_voltages.o
>  obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
>
> diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> index df0d3e572010..2ca9f82c5bf3 100644
> --- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> +++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> @@ -26,6 +26,7 @@ int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
>         [SCMI_PROTOCOL_POWER] = scmi_test_power_init,
>         [SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
>         [SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
> +       [SCMI_PROTOCOL_VOLTAGE] = scmi_test_voltage_init,
>  };
>
>  static void
> @@ -125,6 +126,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
>  }
>
>  static const struct scmi_device_id scmi_id_table[] = {
> +       { SCMI_PROTOCOL_VOLTAGE, "__scmi_test-voltage" },
>         { SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
>         { SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
>         { SCMI_PROTOCOL_POWER, "__scmi_test-power" },
> diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> index 9f3d35ba4477..338b65da593f 100644
> --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> @@ -102,6 +102,7 @@ int scmi_test_release(struct inode *ino, struct file *filp);
>
>  int scmi_test_clock_init(struct scmi_test_setup *tsp);
>  int scmi_test_sensor_init(struct scmi_test_setup *tsp);
> +int scmi_test_voltage_init(struct scmi_test_setup *tsp);
>  int scmi_test_power_init(struct scmi_test_setup *tsp);
>
>  #endif /* __SCMI_TEST_COMMON_H */
> diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> new file mode 100644
> index 000000000000..ab91080e3a0f
> --- /dev/null
> +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> @@ -0,0 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * SCMI Testing Driver - Voltage Protocol
> + *
> + * Copyright (C) 2022 ARM Ltd.
> + */
> +
> +#include <linux/dcache.h>
> +#include <linux/debugfs.h>
> +#include <linux/err.h>
> +#include <linux/fs.h>
> +#include <linux/io.h>
> +#include <linux/kstrtox.h>
> +#include <linux/module.h>
> +#include <linux/scmi_protocol.h>
> +#include <linux/slab.h>
> +
> +#include "test_common.h"
> +
> +struct scmi_voltage_data {
> +       unsigned int version;
> +       int count;
> +};
> +
> +int scmi_test_voltage_init(struct scmi_test_setup *tsp)
> +{
> +       struct scmi_voltage_data *vdata;
> +       struct device *dev = &tsp->sdev->dev;
> +       const struct scmi_voltage_proto_ops *voltage_ops;
> +
> +       vdata = devm_kzalloc(dev, sizeof(*vdata), GFP_KERNEL);
> +       if (!vdata)
> +               return -ENOMEM;
> +
> +       voltage_ops = tsp->ops;
> +       vdata->version = voltage_ops->version_get(tsp->ph);
> +       vdata->count = voltage_ops->num_domains_get(tsp->ph);
> +
> +       if (vdata->count <= 0) {
> +               dev_err(dev, "number of voltage doms invalid: %d\n",
> +                       vdata->count);
> +               return vdata->count ?: -EINVAL;
> +       }
> +
> +       dev_info(dev, "Found %d voltage resources.\n", vdata->count);
> +
> +       tsp->priv = vdata;
> +       debugfs_create_x32("version", 0400, tsp->parent, &vdata->version);
Any particular reason, why we are not creating debugfs entires for
regulator level_get/level_set like it was done for
clocks(rate_get_set)?
> +
> +       return 0;
> +}
> --
> 2.17.1
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases
  2022-02-27 20:56   ` Cristian Marussi
@ 2022-08-01  4:52     ` Arun KS
  -1 siblings, 0 replies; 50+ messages in thread
From: Arun KS @ 2022-08-01  4:52 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Arun KS

Hi Cristian,

On Mon, Feb 28, 2022 at 12:16 PM Cristian Marussi
<cristian.marussi@arm.com> wrote:
>
> A few initial testcases for Clock and Sensot protocol plus all the test
> infrastructure, including the test runeer.
>
> All of this just an experimental demonstrator.
>
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> ---
>  tools/testing/selftests/arm64/Makefile        |   2 +-
>  tools/testing/selftests/arm64/scmi/Makefile   |   6 +
>  tools/testing/selftests/arm64/scmi/config     |   1 +
>  .../arm64/scmi/kselftest_scmi_lib.sh          | 118 ++++++++++++++++++
>  .../selftests/arm64/scmi/run_scmi_tests.sh    |  69 ++++++++++
>  .../testcases/protocol_0x14/clock_enable.sh   |  33 +++++
>  .../protocol_0x14/clock_rate_read.sh          |  18 +++
>  .../protocol_0x14/clock_rate_write.sh         |  29 +++++
>  .../testcases/protocol_0x15/sensor_reading.sh |  17 +++
>  9 files changed, 292 insertions(+), 1 deletion(-)
>  create mode 100644 tools/testing/selftests/arm64/scmi/Makefile
>  create mode 100644 tools/testing/selftests/arm64/scmi/config
>  create mode 100644 tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
>
> diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile
> index 1e8d9a8f59df..6648dd8e2173 100644
> --- a/tools/testing/selftests/arm64/Makefile
> +++ b/tools/testing/selftests/arm64/Makefile
> @@ -4,7 +4,7 @@
>  ARCH ?= $(shell uname -m 2>/dev/null || echo not)
>
>  ifneq (,$(filter $(ARCH),aarch64 arm64))
> -ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi
> +ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi scmi
>  else
>  ARM64_SUBTARGETS :=
>  endif
> diff --git a/tools/testing/selftests/arm64/scmi/Makefile b/tools/testing/selftests/arm64/scmi/Makefile
> new file mode 100644
> index 000000000000..8786d8d4c332
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +TEST_PROGS := run_scmi_tests.sh
> +TEST_FILES := kselftest_scmi_lib.sh testcases/*
> +
> +include ../../lib.mk
> diff --git a/tools/testing/selftests/arm64/scmi/config b/tools/testing/selftests/arm64/scmi/config
> new file mode 100644
> index 000000000000..161387084a3f
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/config
> @@ -0,0 +1 @@
> +CONFIG_ARM_SCMI_TEST_DRIVER=y
> diff --git a/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
> new file mode 100644
> index 000000000000..54d27b5f3e1a
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
> @@ -0,0 +1,118 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +SCMI_TEST_DRV="scmi_test_driver"
> +TRES=(0 0 0)
> +
> +ksft_log()
> +{
> +       echo -e "[SCMI]: $1"
> +}
> +
> +ksft_skip()
> +{
> +       echo -e "[SKIP]: $1"
> +       exit 4
> +}
> +
> +ksft_pass()
> +{
> +       echo -e "[PASS]: $1"
> +}
> +
> +ksft_fail()
> +{
> +       echo -e "[FAIL]: $1"
> +       exit 1
> +}
> +
> +ksft_results()
> +{
> +       if [ $# -gt 0 ]; then
> +               local val
> +               local idx
> +               local ret=$1
> +
> +               case "$ret" in
> +                       0)
> +                               idx=0
> +                               ;;
> +                       4)
> +                               idx=1
> +                               ;;
> +                       *)
> +                               idx=2
> +                               ;;
> +               esac
> +               val=${TRES[${idx}]}
> +               TRES[$idx]=$((val + 1))
> +       else
> +               ksft_log "Summary - PASS[${TRES[0]}]  SKIP[${TRES[1]}]  FAIL[${TRES[2]}]"
> +               [ "x${TRES[2]}" != "x0" ] && exit 1
> +               [ "x${TRES[1]}" != "x0" -a "x${TRES[0]}" == "x0" ] && exit 4
> +               exit 0
> +       fi
> +}
> +
> +ksft_scmi_run_one()
> +{
> +       tcase=$1
> +
> +       echo "-> Running testcase: $tcase"
> +
> +       ./$tcase
> +       ret=$?
> +
> +       ksft_results $ret
> +}
> +
> +ksft_scmi_check_fw_version()
> +{
> +       local supported=$1
> +       local current="${SCMI_VENDOR}:${SCMI_SUB_VENDOR}"
> +
> +       if [ "x${current}" != "x${supported}" ]; then
> +               ksft_skip "Current FW('$current') is UNSUPPORTED. Should be '$supported'"
> +       fi
> +}
> +
> +ksft_scmi_transport_is_atomic ()
> +{
> +       [ "x$SCMI_TRANSPORT_IS_ATOMIC" == "xY" ] && return 0 || return 1
> +}
> +
> +ksft_scmi_protocol_resources_get()
> +{
> +       local proto_dir=$1
> +       local resources=""
> +
> +       for d in ${proto_dir}/*; do
> +               rd="$(basename $d)"
> +               [[ $rd =~ [0-9] ]] && resources="$resources $rd"
> +       done
> +
> +       echo "$resources"
> +}
> +
> +ksft_scmi_value_get()
> +{
> +       local syspath=$1
> +       local __retval=$2
> +       local value
> +
> +       value=$(cat $syspath)
> +       [ "x$?" != "x0" ] && ksft_fail "Fail to read $syspath"
> +
> +       eval $__retval="'$value'"
> +}
> +
> +ksft_scmi_value_set()
> +{
> +       local syspath=$1
> +       local value=$2
> +
> +       echo $value > $syspath
> +       [ "x$?" != "x0" ] && ksft_fail "Fail to write $syspath - err:$?"
> +}
> +
> +
> diff --git a/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
> new file mode 100755
> index 000000000000..f372744a4579
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
> @@ -0,0 +1,69 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +. ./kselftest_scmi_lib.sh
> +
> +check_root_privs()
> +{
> +       [ x"$(id -u)" != "x0" ] && ksft_skip "You need to be root"
> +}
> +
> +check_scmi_testing_stack()
> +{
> +       local debugfs_root=$(findmnt -o TARGET -t debugfs | grep -v TARGET)
> +       export SCMI_DEBUGFS_TOPDIR="$debugfs_root/scmi"
> +
> +       # Try to load module if not builtin
> +       if [ ! -d $SCMI_DEBUGFS_TOPDIR ]; then
> +               modprobe $SCMI_TEST_DRV || ksft_skip "Failed to load $SCMI_TEST_DRV"
> +               [ ! -d $SCMI_DEBUGFS_TOPDIR ] && ksft_skip "SCMI Test stack not found; is CONFIG_ARM_SCMI_TEST_DRIVER enabled ?"
> +       fi
> +}
> +
> +setup_scmi_test_env()
> +{
> +       local scmi_info_dir="${SCMI_DEBUGFS_TOPDIR}/info/"
> +
> +       export SCMI_VENDOR="$(cat ${scmi_info_dir}/vendor_id)"
> +       export SCMI_SUB_VENDOR="$(cat ${scmi_info_dir}/sub_vendor_id)"
> +       export SCMI_VERS_MAJ="$(cat ${scmi_info_dir}/major_ver)"
> +       export SCMI_VERS_MIN="$(cat ${scmi_info_dir}/minor_ver)"
> +       export SCMI_VERS_IMPL="$(cat ${scmi_info_dir}/impl_ver)"
> +
> +       ksft_log "Found stack: $SCMI_VENDOR/$SCMI_SUB_VENDOR ${SCMI_VERS_MAJ}.${SCMI_VERS_MAJ} - $SCMI_VERS_IMPL"
> +
> +       SCMI_TEST_PROTOS=""
> +       for p in ${SCMI_DEBUGFS_TOPDIR}/protocol_*; do
> +               SCMI_TEST_PROTOS="${SCMI_TEST_PROTOS} $(basename $p)"
> +       done
> +
> +       ksft_log "Found testing protocols: $SCMI_TEST_PROTOS"
> +
> +       export SCMI_TEST_PROTOS
> +       SCMI_TRANSPORT_IS_ATOMIC="N"
> +       [ -d "${SCMI_DEBUGFS_TOPDIR}/transport" ] &&
> +               SCMI_TRANSPORT_IS_ATOMIC=$(cat "${SCMI_DEBUGFS_TOPDIR}/transport/is_atomic")
> +       export SCMI_TRANSPORT_IS_ATOMIC
> +}
> +
> +# Setup
> +check_root_privs
> +
> +check_scmi_testing_stack
> +
> +setup_scmi_test_env
> +
> +# Main
> +# Run all available tests for the found protocols
> +#
> +for proto_dir in $SCMI_TEST_PROTOS; do
> +       [ ! -d $proto_dir ] && ksft_log "$proto_dir tests NOT supported." && continue
> +       export TST_PROTO_DIR="${SCMI_DEBUGFS_TOPDIR}/${proto_dir}"
> +       TST_PROTO_VERSION=$(cat ${TST_PROTO_DIR}/version)
> +       ksft_log "Running tests for SCMI $proto_dir ver:$TST_PROTO_VERSION"
> +       for tst in $proto_dir/*; do
> +               ksft_scmi_run_one $tst
> +       done
> +done
> +
> +ksft_results
> diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
> new file mode 100755
> index 000000000000..4cdf3a097ba7
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
> @@ -0,0 +1,33 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +. ./kselftest_scmi_lib.sh
> +
> +supported_fw="EMU-SCMI-VM:userland"
> +ksft_scmi_check_fw_version $supported_fw

what is the necessity of this check? Won't it limits the use of this
common test script across multiple platforms?

> +
> +clock_enable_disable() {
> +       rname=$1
> +       rdir=$2
> +       clk_op=$3
> +
> +       ksft_scmi_value_set $rdir/$clk_op Y
> +       ksft_scmi_value_set $rdir/$clk_op N
> +       ksft_log "Clock $rname: $clk_op - ON/OFF ... OK"
> +}
> +
> +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
> +ksft_log "Found Clock resources: $resources"
> +
> +for res in $resources;do
> +       resd="$TST_PROTO_DIR/$res"
> +       name="$(cat $resd/info/name)"
> +
> +       clock_enable_disable $name $resd "enable"
> +       if [ ksft_transport_is_atomic ]; then
> +               clock_enable_disable $name $resd "enable_atomic_irqs_off"
> +               clock_enable_disable $name $resd "enable_atomic_irqs_on"
> +       fi
> +done
> +
> +ksft_pass "$0"
> diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
> new file mode 100755
> index 000000000000..88c444fd317d
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
> @@ -0,0 +1,18 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +. ./kselftest_scmi_lib.sh
> +
> +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
> +ksft_log "Found Clock resources: $resources"
> +
> +for res in $resources;do
> +       resd="$TST_PROTO_DIR/$res"
> +       name="$(cat $resd/info/name)"
> +       val=0
> +
> +       ksft_scmi_value_get $resd/rate_get_set val
> +       ksft_log "$name READ => $val"
> +done
> +
> +ksft_pass "$0"
> diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
> new file mode 100755
> index 000000000000..346084ec3812
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
> @@ -0,0 +1,29 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +. ./kselftest_scmi_lib.sh
> +
> +supported_fw="EMU-SCMI-VM:userland"
> +ksft_scmi_check_fw_version $supported_fw
> +
> +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
> +ksft_log "Found Clock resources: $resources"
> +
> +for res in $resources;do
> +       resd="$TST_PROTO_DIR/$res"
> +       name="$(cat $resd/info/name)"
> +       val=0
> +       oldval=0
> +       setval=0
> +
> +       ksft_scmi_value_get $resd/rate_get_set oldval
> +       setval=$((oldval + 666))
> +
> +       ksft_scmi_value_set $resd/rate_get_set $setval
> +
> +       ksft_scmi_value_get $resd/rate_get_set val
> +       [ "x$val" != "x$setval" ] && ksft_fail "Set:$setval readback:$val"
> +       ksft_log "$name OK -> read:$oldval  set:$setval  readback:$val"
> +done
> +
> +ksft_pass "$0"
> diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
> new file mode 100755
> index 000000000000..b0f5f6361379
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
> @@ -0,0 +1,17 @@
> +#!/bin/bash
> +
> +. ./kselftest_scmi_lib.sh
> +
> +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
> +ksft_log "Found Sensor resources: $resources"
> +
> +for res in $resources;do
> +       resd="$TST_PROTO_DIR/$res"
> +       name="$(cat $resd/info/name)"
> +       val=0
> +
> +       ksft_scmi_value_get $resd/reading_get val
> +       ksft_log "$name READ => $val"
> +done
> +
> +ksft_pass $0
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases
@ 2022-08-01  4:52     ` Arun KS
  0 siblings, 0 replies; 50+ messages in thread
From: Arun KS @ 2022-08-01  4:52 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Arun KS

Hi Cristian,

On Mon, Feb 28, 2022 at 12:16 PM Cristian Marussi
<cristian.marussi@arm.com> wrote:
>
> A few initial testcases for Clock and Sensot protocol plus all the test
> infrastructure, including the test runeer.
>
> All of this just an experimental demonstrator.
>
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> ---
>  tools/testing/selftests/arm64/Makefile        |   2 +-
>  tools/testing/selftests/arm64/scmi/Makefile   |   6 +
>  tools/testing/selftests/arm64/scmi/config     |   1 +
>  .../arm64/scmi/kselftest_scmi_lib.sh          | 118 ++++++++++++++++++
>  .../selftests/arm64/scmi/run_scmi_tests.sh    |  69 ++++++++++
>  .../testcases/protocol_0x14/clock_enable.sh   |  33 +++++
>  .../protocol_0x14/clock_rate_read.sh          |  18 +++
>  .../protocol_0x14/clock_rate_write.sh         |  29 +++++
>  .../testcases/protocol_0x15/sensor_reading.sh |  17 +++
>  9 files changed, 292 insertions(+), 1 deletion(-)
>  create mode 100644 tools/testing/selftests/arm64/scmi/Makefile
>  create mode 100644 tools/testing/selftests/arm64/scmi/config
>  create mode 100644 tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
>  create mode 100755 tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
>
> diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile
> index 1e8d9a8f59df..6648dd8e2173 100644
> --- a/tools/testing/selftests/arm64/Makefile
> +++ b/tools/testing/selftests/arm64/Makefile
> @@ -4,7 +4,7 @@
>  ARCH ?= $(shell uname -m 2>/dev/null || echo not)
>
>  ifneq (,$(filter $(ARCH),aarch64 arm64))
> -ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi
> +ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi scmi
>  else
>  ARM64_SUBTARGETS :=
>  endif
> diff --git a/tools/testing/selftests/arm64/scmi/Makefile b/tools/testing/selftests/arm64/scmi/Makefile
> new file mode 100644
> index 000000000000..8786d8d4c332
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +TEST_PROGS := run_scmi_tests.sh
> +TEST_FILES := kselftest_scmi_lib.sh testcases/*
> +
> +include ../../lib.mk
> diff --git a/tools/testing/selftests/arm64/scmi/config b/tools/testing/selftests/arm64/scmi/config
> new file mode 100644
> index 000000000000..161387084a3f
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/config
> @@ -0,0 +1 @@
> +CONFIG_ARM_SCMI_TEST_DRIVER=y
> diff --git a/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
> new file mode 100644
> index 000000000000..54d27b5f3e1a
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
> @@ -0,0 +1,118 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +SCMI_TEST_DRV="scmi_test_driver"
> +TRES=(0 0 0)
> +
> +ksft_log()
> +{
> +       echo -e "[SCMI]: $1"
> +}
> +
> +ksft_skip()
> +{
> +       echo -e "[SKIP]: $1"
> +       exit 4
> +}
> +
> +ksft_pass()
> +{
> +       echo -e "[PASS]: $1"
> +}
> +
> +ksft_fail()
> +{
> +       echo -e "[FAIL]: $1"
> +       exit 1
> +}
> +
> +ksft_results()
> +{
> +       if [ $# -gt 0 ]; then
> +               local val
> +               local idx
> +               local ret=$1
> +
> +               case "$ret" in
> +                       0)
> +                               idx=0
> +                               ;;
> +                       4)
> +                               idx=1
> +                               ;;
> +                       *)
> +                               idx=2
> +                               ;;
> +               esac
> +               val=${TRES[${idx}]}
> +               TRES[$idx]=$((val + 1))
> +       else
> +               ksft_log "Summary - PASS[${TRES[0]}]  SKIP[${TRES[1]}]  FAIL[${TRES[2]}]"
> +               [ "x${TRES[2]}" != "x0" ] && exit 1
> +               [ "x${TRES[1]}" != "x0" -a "x${TRES[0]}" == "x0" ] && exit 4
> +               exit 0
> +       fi
> +}
> +
> +ksft_scmi_run_one()
> +{
> +       tcase=$1
> +
> +       echo "-> Running testcase: $tcase"
> +
> +       ./$tcase
> +       ret=$?
> +
> +       ksft_results $ret
> +}
> +
> +ksft_scmi_check_fw_version()
> +{
> +       local supported=$1
> +       local current="${SCMI_VENDOR}:${SCMI_SUB_VENDOR}"
> +
> +       if [ "x${current}" != "x${supported}" ]; then
> +               ksft_skip "Current FW('$current') is UNSUPPORTED. Should be '$supported'"
> +       fi
> +}
> +
> +ksft_scmi_transport_is_atomic ()
> +{
> +       [ "x$SCMI_TRANSPORT_IS_ATOMIC" == "xY" ] && return 0 || return 1
> +}
> +
> +ksft_scmi_protocol_resources_get()
> +{
> +       local proto_dir=$1
> +       local resources=""
> +
> +       for d in ${proto_dir}/*; do
> +               rd="$(basename $d)"
> +               [[ $rd =~ [0-9] ]] && resources="$resources $rd"
> +       done
> +
> +       echo "$resources"
> +}
> +
> +ksft_scmi_value_get()
> +{
> +       local syspath=$1
> +       local __retval=$2
> +       local value
> +
> +       value=$(cat $syspath)
> +       [ "x$?" != "x0" ] && ksft_fail "Fail to read $syspath"
> +
> +       eval $__retval="'$value'"
> +}
> +
> +ksft_scmi_value_set()
> +{
> +       local syspath=$1
> +       local value=$2
> +
> +       echo $value > $syspath
> +       [ "x$?" != "x0" ] && ksft_fail "Fail to write $syspath - err:$?"
> +}
> +
> +
> diff --git a/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
> new file mode 100755
> index 000000000000..f372744a4579
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
> @@ -0,0 +1,69 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +. ./kselftest_scmi_lib.sh
> +
> +check_root_privs()
> +{
> +       [ x"$(id -u)" != "x0" ] && ksft_skip "You need to be root"
> +}
> +
> +check_scmi_testing_stack()
> +{
> +       local debugfs_root=$(findmnt -o TARGET -t debugfs | grep -v TARGET)
> +       export SCMI_DEBUGFS_TOPDIR="$debugfs_root/scmi"
> +
> +       # Try to load module if not builtin
> +       if [ ! -d $SCMI_DEBUGFS_TOPDIR ]; then
> +               modprobe $SCMI_TEST_DRV || ksft_skip "Failed to load $SCMI_TEST_DRV"
> +               [ ! -d $SCMI_DEBUGFS_TOPDIR ] && ksft_skip "SCMI Test stack not found; is CONFIG_ARM_SCMI_TEST_DRIVER enabled ?"
> +       fi
> +}
> +
> +setup_scmi_test_env()
> +{
> +       local scmi_info_dir="${SCMI_DEBUGFS_TOPDIR}/info/"
> +
> +       export SCMI_VENDOR="$(cat ${scmi_info_dir}/vendor_id)"
> +       export SCMI_SUB_VENDOR="$(cat ${scmi_info_dir}/sub_vendor_id)"
> +       export SCMI_VERS_MAJ="$(cat ${scmi_info_dir}/major_ver)"
> +       export SCMI_VERS_MIN="$(cat ${scmi_info_dir}/minor_ver)"
> +       export SCMI_VERS_IMPL="$(cat ${scmi_info_dir}/impl_ver)"
> +
> +       ksft_log "Found stack: $SCMI_VENDOR/$SCMI_SUB_VENDOR ${SCMI_VERS_MAJ}.${SCMI_VERS_MAJ} - $SCMI_VERS_IMPL"
> +
> +       SCMI_TEST_PROTOS=""
> +       for p in ${SCMI_DEBUGFS_TOPDIR}/protocol_*; do
> +               SCMI_TEST_PROTOS="${SCMI_TEST_PROTOS} $(basename $p)"
> +       done
> +
> +       ksft_log "Found testing protocols: $SCMI_TEST_PROTOS"
> +
> +       export SCMI_TEST_PROTOS
> +       SCMI_TRANSPORT_IS_ATOMIC="N"
> +       [ -d "${SCMI_DEBUGFS_TOPDIR}/transport" ] &&
> +               SCMI_TRANSPORT_IS_ATOMIC=$(cat "${SCMI_DEBUGFS_TOPDIR}/transport/is_atomic")
> +       export SCMI_TRANSPORT_IS_ATOMIC
> +}
> +
> +# Setup
> +check_root_privs
> +
> +check_scmi_testing_stack
> +
> +setup_scmi_test_env
> +
> +# Main
> +# Run all available tests for the found protocols
> +#
> +for proto_dir in $SCMI_TEST_PROTOS; do
> +       [ ! -d $proto_dir ] && ksft_log "$proto_dir tests NOT supported." && continue
> +       export TST_PROTO_DIR="${SCMI_DEBUGFS_TOPDIR}/${proto_dir}"
> +       TST_PROTO_VERSION=$(cat ${TST_PROTO_DIR}/version)
> +       ksft_log "Running tests for SCMI $proto_dir ver:$TST_PROTO_VERSION"
> +       for tst in $proto_dir/*; do
> +               ksft_scmi_run_one $tst
> +       done
> +done
> +
> +ksft_results
> diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
> new file mode 100755
> index 000000000000..4cdf3a097ba7
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
> @@ -0,0 +1,33 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +. ./kselftest_scmi_lib.sh
> +
> +supported_fw="EMU-SCMI-VM:userland"
> +ksft_scmi_check_fw_version $supported_fw

what is the necessity of this check? Won't it limits the use of this
common test script across multiple platforms?

> +
> +clock_enable_disable() {
> +       rname=$1
> +       rdir=$2
> +       clk_op=$3
> +
> +       ksft_scmi_value_set $rdir/$clk_op Y
> +       ksft_scmi_value_set $rdir/$clk_op N
> +       ksft_log "Clock $rname: $clk_op - ON/OFF ... OK"
> +}
> +
> +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
> +ksft_log "Found Clock resources: $resources"
> +
> +for res in $resources;do
> +       resd="$TST_PROTO_DIR/$res"
> +       name="$(cat $resd/info/name)"
> +
> +       clock_enable_disable $name $resd "enable"
> +       if [ ksft_transport_is_atomic ]; then
> +               clock_enable_disable $name $resd "enable_atomic_irqs_off"
> +               clock_enable_disable $name $resd "enable_atomic_irqs_on"
> +       fi
> +done
> +
> +ksft_pass "$0"
> diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
> new file mode 100755
> index 000000000000..88c444fd317d
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_read.sh
> @@ -0,0 +1,18 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +. ./kselftest_scmi_lib.sh
> +
> +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
> +ksft_log "Found Clock resources: $resources"
> +
> +for res in $resources;do
> +       resd="$TST_PROTO_DIR/$res"
> +       name="$(cat $resd/info/name)"
> +       val=0
> +
> +       ksft_scmi_value_get $resd/rate_get_set val
> +       ksft_log "$name READ => $val"
> +done
> +
> +ksft_pass "$0"
> diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
> new file mode 100755
> index 000000000000..346084ec3812
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_write.sh
> @@ -0,0 +1,29 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +. ./kselftest_scmi_lib.sh
> +
> +supported_fw="EMU-SCMI-VM:userland"
> +ksft_scmi_check_fw_version $supported_fw
> +
> +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
> +ksft_log "Found Clock resources: $resources"
> +
> +for res in $resources;do
> +       resd="$TST_PROTO_DIR/$res"
> +       name="$(cat $resd/info/name)"
> +       val=0
> +       oldval=0
> +       setval=0
> +
> +       ksft_scmi_value_get $resd/rate_get_set oldval
> +       setval=$((oldval + 666))
> +
> +       ksft_scmi_value_set $resd/rate_get_set $setval
> +
> +       ksft_scmi_value_get $resd/rate_get_set val
> +       [ "x$val" != "x$setval" ] && ksft_fail "Set:$setval readback:$val"
> +       ksft_log "$name OK -> read:$oldval  set:$setval  readback:$val"
> +done
> +
> +ksft_pass "$0"
> diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
> new file mode 100755
> index 000000000000..b0f5f6361379
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_reading.sh
> @@ -0,0 +1,17 @@
> +#!/bin/bash
> +
> +. ./kselftest_scmi_lib.sh
> +
> +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
> +ksft_log "Found Sensor resources: $resources"
> +
> +for res in $resources;do
> +       resd="$TST_PROTO_DIR/$res"
> +       name="$(cat $resd/info/name)"
> +       val=0
> +
> +       ksft_scmi_value_get $resd/reading_get val
> +       ksft_log "$name READ => $val"
> +done
> +
> +ksft_pass $0
> --
> 2.17.1
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 14/16] firmware: arm_scmi: Add testing Voltage protocol support
  2022-08-01  4:47     ` Arun KS
@ 2022-08-01  6:44       ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-08-01  6:44 UTC (permalink / raw)
  To: Arun KS
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber

On Mon, Aug 01, 2022 at 10:17:00AM +0530, Arun KS wrote:
> Hi Cristian,
> 

Hi Arun,

first of all thanks for the feedback !

> On Mon, Feb 28, 2022 at 4:23 AM Cristian Marussi
> <cristian.marussi@arm.com> wrote:
> >
> > firmware: arm_scmi: Add testing Voltage protocol support
> >
> > Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> > ---
> >  .../arm_scmi/scmi_test_driver/Makefile        |  2 +-
> >  .../arm_scmi/scmi_test_driver/scmi_test.c     |  2 +
> >  .../arm_scmi/scmi_test_driver/test_common.h   |  1 +
> >  .../arm_scmi/scmi_test_driver/test_voltages.c | 51 +++++++++++++++++++
> >  4 files changed, 55 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> >
> > diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> > index 68a3d94a6a88..3b7df18de250 100644
> > --- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> > +++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> > @@ -1,5 +1,5 @@
> >  # SPDX-License-Identifier: GPL-2.0-only
> >  scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o \
> > -       test_powers.o
> > +       test_powers.o test_voltages.o
> >  obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
> >
> > diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> > index df0d3e572010..2ca9f82c5bf3 100644
> > --- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> > +++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> > @@ -26,6 +26,7 @@ int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
> >         [SCMI_PROTOCOL_POWER] = scmi_test_power_init,
> >         [SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
> >         [SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
> > +       [SCMI_PROTOCOL_VOLTAGE] = scmi_test_voltage_init,
> >  };
> >
> >  static void
> > @@ -125,6 +126,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
> >  }
> >
> >  static const struct scmi_device_id scmi_id_table[] = {
> > +       { SCMI_PROTOCOL_VOLTAGE, "__scmi_test-voltage" },
> >         { SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
> >         { SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
> >         { SCMI_PROTOCOL_POWER, "__scmi_test-power" },
> > diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> > index 9f3d35ba4477..338b65da593f 100644
> > --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> > +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> > @@ -102,6 +102,7 @@ int scmi_test_release(struct inode *ino, struct file *filp);
> >
> >  int scmi_test_clock_init(struct scmi_test_setup *tsp);
> >  int scmi_test_sensor_init(struct scmi_test_setup *tsp);
> > +int scmi_test_voltage_init(struct scmi_test_setup *tsp);
> >  int scmi_test_power_init(struct scmi_test_setup *tsp);
> >
> >  #endif /* __SCMI_TEST_COMMON_H */
> > diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> > new file mode 100644
> > index 000000000000..ab91080e3a0f
> > --- /dev/null
> > +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> > @@ -0,0 +1,51 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * SCMI Testing Driver - Voltage Protocol
> > + *
> > + * Copyright (C) 2022 ARM Ltd.
> > + */
> > +
> > +#include <linux/dcache.h>
> > +#include <linux/debugfs.h>
> > +#include <linux/err.h>
> > +#include <linux/fs.h>
> > +#include <linux/io.h>
> > +#include <linux/kstrtox.h>
> > +#include <linux/module.h>
> > +#include <linux/scmi_protocol.h>
> > +#include <linux/slab.h>
> > +
> > +#include "test_common.h"
> > +
> > +struct scmi_voltage_data {
> > +       unsigned int version;
> > +       int count;
> > +};
> > +
> > +int scmi_test_voltage_init(struct scmi_test_setup *tsp)
> > +{
> > +       struct scmi_voltage_data *vdata;
> > +       struct device *dev = &tsp->sdev->dev;
> > +       const struct scmi_voltage_proto_ops *voltage_ops;
> > +
> > +       vdata = devm_kzalloc(dev, sizeof(*vdata), GFP_KERNEL);
> > +       if (!vdata)
> > +               return -ENOMEM;
> > +
> > +       voltage_ops = tsp->ops;
> > +       vdata->version = voltage_ops->version_get(tsp->ph);
> > +       vdata->count = voltage_ops->num_domains_get(tsp->ph);
> > +
> > +       if (vdata->count <= 0) {
> > +               dev_err(dev, "number of voltage doms invalid: %d\n",
> > +                       vdata->count);
> > +               return vdata->count ?: -EINVAL;
> > +       }
> > +
> > +       dev_info(dev, "Found %d voltage resources.\n", vdata->count);
> > +
> > +       tsp->priv = vdata;
> > +       debugfs_create_x32("version", 0400, tsp->parent, &vdata->version);
> Any particular reason, why we are not creating debugfs entires for
> regulator level_get/level_set like it was done for
> clocks(rate_get_set)?

No, it is just that this RFC initial series was meant to gather feedback
on this approach at testing and to experiment with this solution itself
a bit, before committing more work to more extensive cover all SCMI protocols
and ops... so the series is 'incomplete' by design :P

... having said that, despite the series had not received so much
feedback at the end, I have worked in the background on extending its
SCMI coverage, so that now I can support all SCMI protocols (exposing all
ops on debugfs) ... I'll plan to post a new more extensive series in the
near(-ish) future once I'll have the time to clean it up and add more
example KSFT testcases (and fix the dummy ones ...)

Thanks,
Cristian


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 14/16] firmware: arm_scmi: Add testing Voltage protocol support
@ 2022-08-01  6:44       ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-08-01  6:44 UTC (permalink / raw)
  To: Arun KS
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber

On Mon, Aug 01, 2022 at 10:17:00AM +0530, Arun KS wrote:
> Hi Cristian,
> 

Hi Arun,

first of all thanks for the feedback !

> On Mon, Feb 28, 2022 at 4:23 AM Cristian Marussi
> <cristian.marussi@arm.com> wrote:
> >
> > firmware: arm_scmi: Add testing Voltage protocol support
> >
> > Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> > ---
> >  .../arm_scmi/scmi_test_driver/Makefile        |  2 +-
> >  .../arm_scmi/scmi_test_driver/scmi_test.c     |  2 +
> >  .../arm_scmi/scmi_test_driver/test_common.h   |  1 +
> >  .../arm_scmi/scmi_test_driver/test_voltages.c | 51 +++++++++++++++++++
> >  4 files changed, 55 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> >
> > diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> > index 68a3d94a6a88..3b7df18de250 100644
> > --- a/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> > +++ b/drivers/firmware/arm_scmi/scmi_test_driver/Makefile
> > @@ -1,5 +1,5 @@
> >  # SPDX-License-Identifier: GPL-2.0-only
> >  scmi_test_driver-objs := scmi_test.o test_common.o test_clocks.o test_sensors.o \
> > -       test_powers.o
> > +       test_powers.o test_voltages.o
> >  obj-$(CONFIG_ARM_SCMI_TEST_DRIVER) += scmi_test_driver.o
> >
> > diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> > index df0d3e572010..2ca9f82c5bf3 100644
> > --- a/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> > +++ b/drivers/firmware/arm_scmi/scmi_test_driver/scmi_test.c
> > @@ -26,6 +26,7 @@ int (*scmi_test_init[SCMI_MAX_PROTOCOLS])(struct scmi_test_setup *) = {
> >         [SCMI_PROTOCOL_POWER] = scmi_test_power_init,
> >         [SCMI_PROTOCOL_CLOCK] = scmi_test_clock_init,
> >         [SCMI_PROTOCOL_SENSOR] = scmi_test_sensor_init,
> > +       [SCMI_PROTOCOL_VOLTAGE] = scmi_test_voltage_init,
> >  };
> >
> >  static void
> > @@ -125,6 +126,7 @@ static int scmi_testing_probe(struct scmi_device *sdev)
> >  }
> >
> >  static const struct scmi_device_id scmi_id_table[] = {
> > +       { SCMI_PROTOCOL_VOLTAGE, "__scmi_test-voltage" },
> >         { SCMI_PROTOCOL_CLOCK, "__scmi_test-clock" },
> >         { SCMI_PROTOCOL_SENSOR, "__scmi_test-sensor" },
> >         { SCMI_PROTOCOL_POWER, "__scmi_test-power" },
> > diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> > index 9f3d35ba4477..338b65da593f 100644
> > --- a/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> > +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_common.h
> > @@ -102,6 +102,7 @@ int scmi_test_release(struct inode *ino, struct file *filp);
> >
> >  int scmi_test_clock_init(struct scmi_test_setup *tsp);
> >  int scmi_test_sensor_init(struct scmi_test_setup *tsp);
> > +int scmi_test_voltage_init(struct scmi_test_setup *tsp);
> >  int scmi_test_power_init(struct scmi_test_setup *tsp);
> >
> >  #endif /* __SCMI_TEST_COMMON_H */
> > diff --git a/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> > new file mode 100644
> > index 000000000000..ab91080e3a0f
> > --- /dev/null
> > +++ b/drivers/firmware/arm_scmi/scmi_test_driver/test_voltages.c
> > @@ -0,0 +1,51 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * SCMI Testing Driver - Voltage Protocol
> > + *
> > + * Copyright (C) 2022 ARM Ltd.
> > + */
> > +
> > +#include <linux/dcache.h>
> > +#include <linux/debugfs.h>
> > +#include <linux/err.h>
> > +#include <linux/fs.h>
> > +#include <linux/io.h>
> > +#include <linux/kstrtox.h>
> > +#include <linux/module.h>
> > +#include <linux/scmi_protocol.h>
> > +#include <linux/slab.h>
> > +
> > +#include "test_common.h"
> > +
> > +struct scmi_voltage_data {
> > +       unsigned int version;
> > +       int count;
> > +};
> > +
> > +int scmi_test_voltage_init(struct scmi_test_setup *tsp)
> > +{
> > +       struct scmi_voltage_data *vdata;
> > +       struct device *dev = &tsp->sdev->dev;
> > +       const struct scmi_voltage_proto_ops *voltage_ops;
> > +
> > +       vdata = devm_kzalloc(dev, sizeof(*vdata), GFP_KERNEL);
> > +       if (!vdata)
> > +               return -ENOMEM;
> > +
> > +       voltage_ops = tsp->ops;
> > +       vdata->version = voltage_ops->version_get(tsp->ph);
> > +       vdata->count = voltage_ops->num_domains_get(tsp->ph);
> > +
> > +       if (vdata->count <= 0) {
> > +               dev_err(dev, "number of voltage doms invalid: %d\n",
> > +                       vdata->count);
> > +               return vdata->count ?: -EINVAL;
> > +       }
> > +
> > +       dev_info(dev, "Found %d voltage resources.\n", vdata->count);
> > +
> > +       tsp->priv = vdata;
> > +       debugfs_create_x32("version", 0400, tsp->parent, &vdata->version);
> Any particular reason, why we are not creating debugfs entires for
> regulator level_get/level_set like it was done for
> clocks(rate_get_set)?

No, it is just that this RFC initial series was meant to gather feedback
on this approach at testing and to experiment with this solution itself
a bit, before committing more work to more extensive cover all SCMI protocols
and ops... so the series is 'incomplete' by design :P

... having said that, despite the series had not received so much
feedback at the end, I have worked in the background on extending its
SCMI coverage, so that now I can support all SCMI protocols (exposing all
ops on debugfs) ... I'll plan to post a new more extensive series in the
near(-ish) future once I'll have the time to clean it up and add more
example KSFT testcases (and fix the dummy ones ...)

Thanks,
Cristian


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases
  2022-08-01  4:52     ` Arun KS
@ 2022-08-01  6:54       ` Cristian Marussi
  -1 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-08-01  6:54 UTC (permalink / raw)
  To: Arun KS
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Arun KS

On Mon, Aug 01, 2022 at 10:22:19AM +0530, Arun KS wrote:
> Hi Cristian,
> 

Hi Arun,

[snip]
> > +setup_scmi_test_env()
> > +{
> > +       local scmi_info_dir="${SCMI_DEBUGFS_TOPDIR}/info/"
> > +
> > +       export SCMI_VENDOR="$(cat ${scmi_info_dir}/vendor_id)"
> > +       export SCMI_SUB_VENDOR="$(cat ${scmi_info_dir}/sub_vendor_id)"
> > +       export SCMI_VERS_MAJ="$(cat ${scmi_info_dir}/major_ver)"
> > +       export SCMI_VERS_MIN="$(cat ${scmi_info_dir}/minor_ver)"
> > +       export SCMI_VERS_IMPL="$(cat ${scmi_info_dir}/impl_ver)"
> > +
> > +       ksft_log "Found stack: $SCMI_VENDOR/$SCMI_SUB_VENDOR ${SCMI_VERS_MAJ}.${SCMI_VERS_MAJ} - $SCMI_VERS_IMPL"
> > +
> > +       SCMI_TEST_PROTOS=""
> > +       for p in ${SCMI_DEBUGFS_TOPDIR}/protocol_*; do
> > +               SCMI_TEST_PROTOS="${SCMI_TEST_PROTOS} $(basename $p)"
> > +       done
> > +
> > +       ksft_log "Found testing protocols: $SCMI_TEST_PROTOS"
> > +
> > +       export SCMI_TEST_PROTOS
> > +       SCMI_TRANSPORT_IS_ATOMIC="N"
> > +       [ -d "${SCMI_DEBUGFS_TOPDIR}/transport" ] &&
> > +               SCMI_TRANSPORT_IS_ATOMIC=$(cat "${SCMI_DEBUGFS_TOPDIR}/transport/is_atomic")
> > +       export SCMI_TRANSPORT_IS_ATOMIC
> > +}
> > +
> > +# Setup
> > +check_root_privs
> > +
> > +check_scmi_testing_stack
> > +
> > +setup_scmi_test_env
> > +
> > +# Main
> > +# Run all available tests for the found protocols
> > +#
> > +for proto_dir in $SCMI_TEST_PROTOS; do
> > +       [ ! -d $proto_dir ] && ksft_log "$proto_dir tests NOT supported." && continue
> > +       export TST_PROTO_DIR="${SCMI_DEBUGFS_TOPDIR}/${proto_dir}"
> > +       TST_PROTO_VERSION=$(cat ${TST_PROTO_DIR}/version)
> > +       ksft_log "Running tests for SCMI $proto_dir ver:$TST_PROTO_VERSION"
> > +       for tst in $proto_dir/*; do
> > +               ksft_scmi_run_one $tst
> > +       done
> > +done
> > +
> > +ksft_results
> > diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
> > new file mode 100755
> > index 000000000000..4cdf3a097ba7
> > --- /dev/null
> > +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
> > @@ -0,0 +1,33 @@
> > +#!/bin/bash
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +. ./kselftest_scmi_lib.sh
> > +
> > +supported_fw="EMU-SCMI-VM:userland"
> > +ksft_scmi_check_fw_version $supported_fw
> 
> what is the necessity of this check? Won't it limits the use of this
> common test script across multiple platforms?
> 

Yes, indeed the basic idea here was to showcase in this RFC series that
the testcases could be written so as to be run only on a restricted set
of platforms: the crux of the matter is that some of the SCMI tests by
their own nature can be very invasive and disruptive, but for the sake
of testing the Kernel stack some of those are worth to be run and, with
this 'version-bsed' approach, you could run it safely as long as you
deploy them against some sort of special emulated SCMI-server which is
is instead safe to be tested in any way (since no real clocks are in
fact involved...)

For this same reason, this kind of test tailored at a very special SCMI
server wouldn't be probably upstreamed unless you fw-emulation backend
is upstream in the open too, so I posted this test more to showcase the
version based mechanism than the test itself...

Thanks,
Cristian

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases
@ 2022-08-01  6:54       ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-08-01  6:54 UTC (permalink / raw)
  To: Arun KS
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber, Arun KS

On Mon, Aug 01, 2022 at 10:22:19AM +0530, Arun KS wrote:
> Hi Cristian,
> 

Hi Arun,

[snip]
> > +setup_scmi_test_env()
> > +{
> > +       local scmi_info_dir="${SCMI_DEBUGFS_TOPDIR}/info/"
> > +
> > +       export SCMI_VENDOR="$(cat ${scmi_info_dir}/vendor_id)"
> > +       export SCMI_SUB_VENDOR="$(cat ${scmi_info_dir}/sub_vendor_id)"
> > +       export SCMI_VERS_MAJ="$(cat ${scmi_info_dir}/major_ver)"
> > +       export SCMI_VERS_MIN="$(cat ${scmi_info_dir}/minor_ver)"
> > +       export SCMI_VERS_IMPL="$(cat ${scmi_info_dir}/impl_ver)"
> > +
> > +       ksft_log "Found stack: $SCMI_VENDOR/$SCMI_SUB_VENDOR ${SCMI_VERS_MAJ}.${SCMI_VERS_MAJ} - $SCMI_VERS_IMPL"
> > +
> > +       SCMI_TEST_PROTOS=""
> > +       for p in ${SCMI_DEBUGFS_TOPDIR}/protocol_*; do
> > +               SCMI_TEST_PROTOS="${SCMI_TEST_PROTOS} $(basename $p)"
> > +       done
> > +
> > +       ksft_log "Found testing protocols: $SCMI_TEST_PROTOS"
> > +
> > +       export SCMI_TEST_PROTOS
> > +       SCMI_TRANSPORT_IS_ATOMIC="N"
> > +       [ -d "${SCMI_DEBUGFS_TOPDIR}/transport" ] &&
> > +               SCMI_TRANSPORT_IS_ATOMIC=$(cat "${SCMI_DEBUGFS_TOPDIR}/transport/is_atomic")
> > +       export SCMI_TRANSPORT_IS_ATOMIC
> > +}
> > +
> > +# Setup
> > +check_root_privs
> > +
> > +check_scmi_testing_stack
> > +
> > +setup_scmi_test_env
> > +
> > +# Main
> > +# Run all available tests for the found protocols
> > +#
> > +for proto_dir in $SCMI_TEST_PROTOS; do
> > +       [ ! -d $proto_dir ] && ksft_log "$proto_dir tests NOT supported." && continue
> > +       export TST_PROTO_DIR="${SCMI_DEBUGFS_TOPDIR}/${proto_dir}"
> > +       TST_PROTO_VERSION=$(cat ${TST_PROTO_DIR}/version)
> > +       ksft_log "Running tests for SCMI $proto_dir ver:$TST_PROTO_VERSION"
> > +       for tst in $proto_dir/*; do
> > +               ksft_scmi_run_one $tst
> > +       done
> > +done
> > +
> > +ksft_results
> > diff --git a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
> > new file mode 100755
> > index 000000000000..4cdf3a097ba7
> > --- /dev/null
> > +++ b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable.sh
> > @@ -0,0 +1,33 @@
> > +#!/bin/bash
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +. ./kselftest_scmi_lib.sh
> > +
> > +supported_fw="EMU-SCMI-VM:userland"
> > +ksft_scmi_check_fw_version $supported_fw
> 
> what is the necessity of this check? Won't it limits the use of this
> common test script across multiple platforms?
> 

Yes, indeed the basic idea here was to showcase in this RFC series that
the testcases could be written so as to be run only on a restricted set
of platforms: the crux of the matter is that some of the SCMI tests by
their own nature can be very invasive and disruptive, but for the sake
of testing the Kernel stack some of those are worth to be run and, with
this 'version-bsed' approach, you could run it safely as long as you
deploy them against some sort of special emulated SCMI-server which is
is instead safe to be tested in any way (since no real clocks are in
fact involved...)

For this same reason, this kind of test tailored at a very special SCMI
server wouldn't be probably upstreamed unless you fw-emulation backend
is upstream in the open too, so I posted this test more to showcase the
version based mechanism than the test itself...

Thanks,
Cristian

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases
       [not found]   ` <CAKZGPAMoBPiikbpNE2SjDxsUQQKZC-Yn5cbn60Sx0ZRqGv47jA@mail.gmail.com>
@ 2022-08-01  7:01       ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-08-01  7:01 UTC (permalink / raw)
  To: Arun KS
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber

On Mon, Aug 01, 2022 at 11:02:28AM +0530, Arun KS wrote:
>    Hi Cristian,

Hi Arun,

sorry I found this mail a bit garbled and with HTML, I'll answer below
what I could see.

>    On Mon, Feb 28, 2022 at 12:16 PM Cristian Marussi
>    <[1]cristian.marussi@arm.com> wrote:
>    >
>    > A few initial testcases for Clock and Sensot protocol plus all the
>    test
>    > infrastructure, including the test runeer.
>    >
>    > All of this just an experimental demonstrator.
>    >
>    > Signed-off-by: Cristian Marussi <[2]cristian.marussi@arm.com>
>    > ---
>    >  tools/testing/selftests/arm64/Makefile        |   2 +-
>    >  tools/testing/selftests/arm64/scmi/Makefile   |   6 +
>    >  tools/testing/selftests/arm64/scmi/config     |   1 +
>    >  .../arm64/scmi/kselftest_scmi_lib.sh          | 118
>    ++++++++++++++++++
>    >  .../selftests/arm64/scmi/run_scmi_tests.sh    |  69 ++++++++++
>    >  .../testcases/protocol_0x14/clock_enable.sh   |  33 +++++
>    >  .../protocol_0x14/clock_rate_read.sh          |  18 +++
>    >  .../protocol_0x14/clock_rate_write.sh         |  29 +++++
>    >  .../testcases/protocol_0x15/sensor_reading.sh |  17 +++
>    >  9 files changed, 292 insertions(+), 1 deletion(-)
>    >  create mode 100644 tools/testing/selftests/arm64/scmi/Makefile
>    >  create mode 100644 tools/testing/selftests/arm64/scmi/config
>    >  create mode 100644
>    tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable
>    .sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_r
>    ead.sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_w
>    rite.sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_readi
>    ng.sh
>    >
>    > diff --git a/tools/testing/selftests/arm64/Makefile
>    b/tools/testing/selftests/arm64/Makefile
>    > index 1e8d9a8f59df..6648dd8e2173 100644
>    > --- a/tools/testing/selftests/arm64/Makefile
>    > +++ b/tools/testing/selftests/arm64/Makefile
>    > @@ -4,7 +4,7 @@
>    >  ARCH ?= $(shell uname -m 2>/dev/null || echo not)
>    >
>    >  ifneq (,$(filter $(ARCH),aarch64 arm64))
>    > -ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi
>    > +ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi scmi
>    >  else
>    >  ARM64_SUBTARGETS :=
>    >  endif
>    > diff --git a/tools/testing/selftests/arm64/scmi/Makefile
>    b/tools/testing/selftests/arm64/scmi/Makefile
>    > new file mode 100644
>    > index 000000000000..8786d8d4c332
>    > --- /dev/null
>    > +++ b/tools/testing/selftests/arm64/scmi/Makefile
>    > @@ -0,0 +1,6 @@
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +TEST_PROGS := run_scmi_tests.sh
>    > +TEST_FILES := kselftest_scmi_lib.sh testcases/*
>    > +
>    > +include ../../[3]lib.mk
>    > diff --git a/tools/testing/selftests/arm64/scmi/config
>    b/tools/testing/selftests/arm64/scmi/config
>    > new file mode 100644
>    > index 000000000000..161387084a3f
>    > --- /dev/null
>    > +++ b/tools/testing/selftests/arm64/scmi/config
>    > @@ -0,0 +1 @@
>    > +CONFIG_ARM_SCMI_TEST_DRIVER=y
>    > diff --git a/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>    b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>    > new file mode 100644
>    > index 000000000000..54d27b5f3e1a
>    > --- /dev/null
>    > +++ b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>    > @@ -0,0 +1,118 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +SCMI_TEST_DRV="scmi_test_driver"
>    > +TRES=(0 0 0)
>    > +
>    > +ksft_log()
>    > +{
>    > +       echo -e "[SCMI]: $1"
>    > +}
>    > +
>    > +ksft_skip()
>    > +{
>    > +       echo -e "[SKIP]: $1"
>    > +       exit 4
>    > +}
>    > +
>    > +ksft_pass()
>    > +{
>    > +       echo -e "[PASS]: $1"
>    > +}
>    > +
>    > +ksft_fail()
>    > +{
>    > +       echo -e "[FAIL]: $1"
>    > +       exit 1
>    > +}
>    > +
>    > +ksft_results()
>    > +{
>    > +       if [ $# -gt 0 ]; then
>    > +               local val
>    > +               local idx
>    > +               local ret=$1
>    > +
>    > +               case "$ret" in
>    > +                       0)
>    > +                               idx=0
>    > +                               ;;
>    > +                       4)
>    > +                               idx=1
>    > +                               ;;
>    > +                       *)
>    > +                               idx=2
>    > +                               ;;
>    > +               esac
>    > +               val=${TRES[${idx}]}
>    > +               TRES[$idx]=$((val + 1))
>    > +       else
>    > +               ksft_log "Summary - PASS[${TRES[0]}]
>    SKIP[${TRES[1]}]  FAIL[${TRES[2]}]"
>    > +               [ "x${TRES[2]}" != "x0" ] && exit 1
>    > +               [ "x${TRES[1]}" != "x0" -a "x${TRES[0]}" == "x0" ] &&
>    exit 4
>    > +               exit 0
>    > +       fi
>    > +}
>    > +
>    > +ksft_scmi_run_one()
>    > +{
>    > +       tcase=$1
>    > +
>    > +       echo "-> Running testcase: $tcase"
>    > +
>    > +       ./$tcase
>    > +       ret=$?
>    > +
>    > +       ksft_results $ret
>    > +}
>    > +
>    > +ksft_scmi_check_fw_version()
>    > +{
>    > +       local supported=$1
>    > +       local current="${SCMI_VENDOR}:${SCMI_SUB_VENDOR}"
>    > +
>    > +       if [ "x${current}" != "x${supported}" ]; then
>    > +               ksft_skip "Current FW('$current') is UNSUPPORTED.
>    Should be '$supported'"

No, because I want to write out that the FW currently found running is
not supported by this test.

>    > +       fi
>    > +}
>    > +
>    > +ksft_scmi_transport_is_atomic ()
>    > +{
>    > +       [ "x$SCMI_TRANSPORT_IS_ATOMIC" == "xY" ] && return 0 ||
>    return 1
>    > +}
>    > +
>    > +ksft_scmi_protocol_resources_get()
>    > +{
>    > +       local proto_dir=$1
>    > +       local resources=""
>    > +
>    > +       for d in ${proto_dir}/*; do
>    > +               rd="$(basename $d)"
>    > +               [[ $rd =~ [0-9] ]] && resources="$resources $rd"
>    > +       done
>    > +
>    > +       echo "$resources"
>    > +}
>    > +
>    > +ksft_scmi_value_get()
>    > +{
>    > +       local syspath=$1
>    > +       local __retval=$2
>    > +       local value
>    > +
>    > +       value=$(cat $syspath)
>    > +       [ "x$?" != "x0" ] && ksft_fail "Fail to read $syspath"
>    > +
>    > +       eval $__retval="'$value'"
>    > +}
>    > +
>    > +ksft_scmi_value_set()
>    > +{
>    > +       local syspath=$1
>    > +       local value=$2
>    > +
>    > +       echo $value > $syspath
>    > +       [ "x$?" != "x0" ] && ksft_fail "Fail to write $syspath -
>    err:$?"
>    > +}
>    > +
>    > +
>    > diff --git a/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>    b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>    > new file mode 100755
>    > index 000000000000..f372744a4579
>    > --- /dev/null
>    > +++ b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>    > @@ -0,0 +1,69 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +. ./kselftest_scmi_lib.sh
>    > +
>    > +check_root_privs()
>    > +{
>    > +       [ x"$(id -u)" != "x0" ] && ksft_skip "You need to be root"
>    > +}
>    > +
>    > +check_scmi_testing_stack()
>    > +{
>    > +       local debugfs_root=$(findmnt -o TARGET -t debugfs | grep -v
>    TARGET)
>    > +       export SCMI_DEBUGFS_TOPDIR="$debugfs_root/scmi"
>    > +
>    > +       # Try to load module if not builtin
>    > +       if [ ! -d $SCMI_DEBUGFS_TOPDIR ]; then
>    > +               modprobe $SCMI_TEST_DRV || ksft_skip "Failed to load
>    $SCMI_TEST_DRV"
>    > +               [ ! -d $SCMI_DEBUGFS_TOPDIR ] && ksft_skip "SCMI Test
>    stack not found; is CONFIG_ARM_SCMI_TEST_DRIVER enabled ?"
>    > +       fi
>    > +}
>    > +
>    > +setup_scmi_test_env()
>    > +{
>    > +       local scmi_info_dir="${SCMI_DEBUGFS_TOPDIR}/info/"
>    > +
>    > +       export SCMI_VENDOR="$(cat ${scmi_info_dir}/vendor_id)"
>    > +       export SCMI_SUB_VENDOR="$(cat
>    ${scmi_info_dir}/sub_vendor_id)"
>    > +       export SCMI_VERS_MAJ="$(cat ${scmi_info_dir}/major_ver)"
>    > +       export SCMI_VERS_MIN="$(cat ${scmi_info_dir}/minor_ver)"
>    > +       export SCMI_VERS_IMPL="$(cat ${scmi_info_dir}/impl_ver)"
>    > +
>    > +       ksft_log "Found stack: $SCMI_VENDOR/$SCMI_SUB_VENDOR
>    ${SCMI_VERS_MAJ}.${SCMI_VERS_MAJ} - $SCMI_VERS_IMPL"
>    > +
>    > +       SCMI_TEST_PROTOS=""
>    > +       for p in ${SCMI_DEBUGFS_TOPDIR}/protocol_*; do
>    > +               SCMI_TEST_PROTOS="${SCMI_TEST_PROTOS} $(basename $p)"
>    > +       done
>    > +
>    > +       ksft_log "Found testing protocols: $SCMI_TEST_PROTOS"
>    > +
>    > +       export SCMI_TEST_PROTOS
>    > +       SCMI_TRANSPORT_IS_ATOMIC="N"
>    > +       [ -d "${SCMI_DEBUGFS_TOPDIR}/transport" ] &&
>    > +               SCMI_TRANSPORT_IS_ATOMIC=$(cat
>    "${SCMI_DEBUGFS_TOPDIR}/transport/is_atomic")
>    > +       export SCMI_TRANSPORT_IS_ATOMIC
>    > +}
>    > +
>    > +# Setup
>    > +check_root_privs
>    > +
>    > +check_scmi_testing_stack
>    > +
>    > +setup_scmi_test_env
>    > +
>    > +# Main
>    > +# Run all available tests for the found protocols
>    > +#
>    > +for proto_dir in $SCMI_TEST_PROTOS; do
>    > +       [ ! -d $proto_dir ] && ksft_log "$proto_dir tests NOT
>    supported." && continue
>    > +       export TST_PROTO_DIR="${SCMI_DEBUGFS_TOPDIR}/${proto_dir}"
>    > +       TST_PROTO_VERSION=$(cat ${TST_PROTO_DIR}/version)
>    > +       ksft_log "Running tests for SCMI $proto_dir
>    ver:$TST_PROTO_VERSION"
>    > +       for tst in $proto_dir/*; do
>    > +               ksft_scmi_run_one $tst
>    > +       done
>    > +done
>    > +
>    > +ksft_results
>    > diff --git
>    a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enab
>    le.sh
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enab
>    le.sh
>    > new file mode 100755
>    > index 000000000000..4cdf3a097ba7
>    > --- /dev/null
>    > +++
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enab
>    le.sh
>    > @@ -0,0 +1,33 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +. ./kselftest_scmi_lib.sh
>    > +
>    > +supported_fw="EMU-SCMI-VM:userland"
>    > +ksft_scmi_check_fw_version $supported_fw
>    > +
>    > +clock_enable_disable() {
>    > +       rname=$1
>    > +       rdir=$2
>    > +       clk_op=$3
>    > +
>    > +       ksft_scmi_value_set $rdir/$clk_op Y
>    > +       ksft_scmi_value_set $rdir/$clk_op N
>    > +       ksft_log "Clock $rname: $clk_op - ON/OFF ... OK"
>    > +}
>    > +
>    > +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
>    > +ksft_log "Found Clock resources: $resources"
>    > +
>    > +for res in $resources;do
>    > +       resd="$TST_PROTO_DIR/$res"
>    > +       name="$(cat $resd/info/name)"
>    > +
>    > +       clock_enable_disable $name $resd "enable"
>    > +       if [ ksft_transport_is_atomic ]; then
>    > +               clock_enable_disable $name $resd
>    "enable_atomic_irqs_off"
>    > +               clock_enable_disable $name $resd
>    "enable_atomic_irqs_on"
>    > +       fi
>    > +done
>    > +
>    > +ksft_pass "$0"
>    > diff --git
>    a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _read.sh
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _read.sh
>    > new file mode 100755
>    > index 000000000000..88c444fd317d
>    > --- /dev/null
>    > +++
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _read.sh
>    > @@ -0,0 +1,18 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +. ./kselftest_scmi_lib.sh
>    > +
>    > +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
>    > +ksft_log "Found Clock resources: $resources"
>    > +
>    > +for res in $resources;do
>    > +       resd="$TST_PROTO_DIR/$res"
>    > +       name="$(cat $resd/info/name)"
>    > +       val=0
>    > +
>    > +       ksft_scmi_value_get $resd/rate_get_set val
>    > +       ksft_log "$name READ => $val"
>    > +done
>    > +
>    > +ksft_pass "$0"
>    > diff --git
>    a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _write.sh
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _write.sh
>    > new file mode 100755
>    > index 000000000000..346084ec3812
>    > --- /dev/null
>    > +++
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _write.sh
>    > @@ -0,0 +1,29 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +. ./kselftest_scmi_lib.sh
>    > +
>    > +supported_fw="EMU-SCMI-VM:userland"
>    > +ksft_scmi_check_fw_version $supported_fw
>    > +
>    > +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
>    > +ksft_log "Found Clock resources: $resources"
>    > +
>    > +for res in $resources;do
>    > +       resd="$TST_PROTO_DIR/$res"
>    > +       name="$(cat $resd/info/name)"
>    > +       val=0
>    > +       oldval=0
>    > +       setval=0
>    > +
>    > +       ksft_scmi_value_get $resd/rate_get_set oldval
>    > +       setval=$((oldval + 666))
>    significance of 666?

Just a stupid dummy value that stands-out in my log when
testing this series .... clearly won't be the value in the final series.

>    > +
>    > +       ksft_scmi_value_set $resd/rate_get_set $setval
>     when setval is not a valid option(not in the list of possible clock
>    rates),
>     rate_get_set returns non zero value and ksft_scmi_value_set() calls
>    ksft_fail()
>     and then an exit. Is this what is intended to do?

Probably not, this should expect a failure...thanks.

Thanks,
Cristian

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases
@ 2022-08-01  7:01       ` Cristian Marussi
  0 siblings, 0 replies; 50+ messages in thread
From: Cristian Marussi @ 2022-08-01  7:01 UTC (permalink / raw)
  To: Arun KS
  Cc: linux-kernel, linux-arm-kernel, sudeep.holla, james.quinlan,
	Jonathan.Cameron, f.fainelli, vincent.guittot,
	souvik.chakravarty, peter.hilber

On Mon, Aug 01, 2022 at 11:02:28AM +0530, Arun KS wrote:
>    Hi Cristian,

Hi Arun,

sorry I found this mail a bit garbled and with HTML, I'll answer below
what I could see.

>    On Mon, Feb 28, 2022 at 12:16 PM Cristian Marussi
>    <[1]cristian.marussi@arm.com> wrote:
>    >
>    > A few initial testcases for Clock and Sensot protocol plus all the
>    test
>    > infrastructure, including the test runeer.
>    >
>    > All of this just an experimental demonstrator.
>    >
>    > Signed-off-by: Cristian Marussi <[2]cristian.marussi@arm.com>
>    > ---
>    >  tools/testing/selftests/arm64/Makefile        |   2 +-
>    >  tools/testing/selftests/arm64/scmi/Makefile   |   6 +
>    >  tools/testing/selftests/arm64/scmi/config     |   1 +
>    >  .../arm64/scmi/kselftest_scmi_lib.sh          | 118
>    ++++++++++++++++++
>    >  .../selftests/arm64/scmi/run_scmi_tests.sh    |  69 ++++++++++
>    >  .../testcases/protocol_0x14/clock_enable.sh   |  33 +++++
>    >  .../protocol_0x14/clock_rate_read.sh          |  18 +++
>    >  .../protocol_0x14/clock_rate_write.sh         |  29 +++++
>    >  .../testcases/protocol_0x15/sensor_reading.sh |  17 +++
>    >  9 files changed, 292 insertions(+), 1 deletion(-)
>    >  create mode 100644 tools/testing/selftests/arm64/scmi/Makefile
>    >  create mode 100644 tools/testing/selftests/arm64/scmi/config
>    >  create mode 100644
>    tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enable
>    .sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_r
>    ead.sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate_w
>    rite.sh
>    >  create mode 100755
>    tools/testing/selftests/arm64/scmi/testcases/protocol_0x15/sensor_readi
>    ng.sh
>    >
>    > diff --git a/tools/testing/selftests/arm64/Makefile
>    b/tools/testing/selftests/arm64/Makefile
>    > index 1e8d9a8f59df..6648dd8e2173 100644
>    > --- a/tools/testing/selftests/arm64/Makefile
>    > +++ b/tools/testing/selftests/arm64/Makefile
>    > @@ -4,7 +4,7 @@
>    >  ARCH ?= $(shell uname -m 2>/dev/null || echo not)
>    >
>    >  ifneq (,$(filter $(ARCH),aarch64 arm64))
>    > -ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi
>    > +ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi scmi
>    >  else
>    >  ARM64_SUBTARGETS :=
>    >  endif
>    > diff --git a/tools/testing/selftests/arm64/scmi/Makefile
>    b/tools/testing/selftests/arm64/scmi/Makefile
>    > new file mode 100644
>    > index 000000000000..8786d8d4c332
>    > --- /dev/null
>    > +++ b/tools/testing/selftests/arm64/scmi/Makefile
>    > @@ -0,0 +1,6 @@
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +TEST_PROGS := run_scmi_tests.sh
>    > +TEST_FILES := kselftest_scmi_lib.sh testcases/*
>    > +
>    > +include ../../[3]lib.mk
>    > diff --git a/tools/testing/selftests/arm64/scmi/config
>    b/tools/testing/selftests/arm64/scmi/config
>    > new file mode 100644
>    > index 000000000000..161387084a3f
>    > --- /dev/null
>    > +++ b/tools/testing/selftests/arm64/scmi/config
>    > @@ -0,0 +1 @@
>    > +CONFIG_ARM_SCMI_TEST_DRIVER=y
>    > diff --git a/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>    b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>    > new file mode 100644
>    > index 000000000000..54d27b5f3e1a
>    > --- /dev/null
>    > +++ b/tools/testing/selftests/arm64/scmi/kselftest_scmi_lib.sh
>    > @@ -0,0 +1,118 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +SCMI_TEST_DRV="scmi_test_driver"
>    > +TRES=(0 0 0)
>    > +
>    > +ksft_log()
>    > +{
>    > +       echo -e "[SCMI]: $1"
>    > +}
>    > +
>    > +ksft_skip()
>    > +{
>    > +       echo -e "[SKIP]: $1"
>    > +       exit 4
>    > +}
>    > +
>    > +ksft_pass()
>    > +{
>    > +       echo -e "[PASS]: $1"
>    > +}
>    > +
>    > +ksft_fail()
>    > +{
>    > +       echo -e "[FAIL]: $1"
>    > +       exit 1
>    > +}
>    > +
>    > +ksft_results()
>    > +{
>    > +       if [ $# -gt 0 ]; then
>    > +               local val
>    > +               local idx
>    > +               local ret=$1
>    > +
>    > +               case "$ret" in
>    > +                       0)
>    > +                               idx=0
>    > +                               ;;
>    > +                       4)
>    > +                               idx=1
>    > +                               ;;
>    > +                       *)
>    > +                               idx=2
>    > +                               ;;
>    > +               esac
>    > +               val=${TRES[${idx}]}
>    > +               TRES[$idx]=$((val + 1))
>    > +       else
>    > +               ksft_log "Summary - PASS[${TRES[0]}]
>    SKIP[${TRES[1]}]  FAIL[${TRES[2]}]"
>    > +               [ "x${TRES[2]}" != "x0" ] && exit 1
>    > +               [ "x${TRES[1]}" != "x0" -a "x${TRES[0]}" == "x0" ] &&
>    exit 4
>    > +               exit 0
>    > +       fi
>    > +}
>    > +
>    > +ksft_scmi_run_one()
>    > +{
>    > +       tcase=$1
>    > +
>    > +       echo "-> Running testcase: $tcase"
>    > +
>    > +       ./$tcase
>    > +       ret=$?
>    > +
>    > +       ksft_results $ret
>    > +}
>    > +
>    > +ksft_scmi_check_fw_version()
>    > +{
>    > +       local supported=$1
>    > +       local current="${SCMI_VENDOR}:${SCMI_SUB_VENDOR}"
>    > +
>    > +       if [ "x${current}" != "x${supported}" ]; then
>    > +               ksft_skip "Current FW('$current') is UNSUPPORTED.
>    Should be '$supported'"

No, because I want to write out that the FW currently found running is
not supported by this test.

>    > +       fi
>    > +}
>    > +
>    > +ksft_scmi_transport_is_atomic ()
>    > +{
>    > +       [ "x$SCMI_TRANSPORT_IS_ATOMIC" == "xY" ] && return 0 ||
>    return 1
>    > +}
>    > +
>    > +ksft_scmi_protocol_resources_get()
>    > +{
>    > +       local proto_dir=$1
>    > +       local resources=""
>    > +
>    > +       for d in ${proto_dir}/*; do
>    > +               rd="$(basename $d)"
>    > +               [[ $rd =~ [0-9] ]] && resources="$resources $rd"
>    > +       done
>    > +
>    > +       echo "$resources"
>    > +}
>    > +
>    > +ksft_scmi_value_get()
>    > +{
>    > +       local syspath=$1
>    > +       local __retval=$2
>    > +       local value
>    > +
>    > +       value=$(cat $syspath)
>    > +       [ "x$?" != "x0" ] && ksft_fail "Fail to read $syspath"
>    > +
>    > +       eval $__retval="'$value'"
>    > +}
>    > +
>    > +ksft_scmi_value_set()
>    > +{
>    > +       local syspath=$1
>    > +       local value=$2
>    > +
>    > +       echo $value > $syspath
>    > +       [ "x$?" != "x0" ] && ksft_fail "Fail to write $syspath -
>    err:$?"
>    > +}
>    > +
>    > +
>    > diff --git a/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>    b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>    > new file mode 100755
>    > index 000000000000..f372744a4579
>    > --- /dev/null
>    > +++ b/tools/testing/selftests/arm64/scmi/run_scmi_tests.sh
>    > @@ -0,0 +1,69 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +. ./kselftest_scmi_lib.sh
>    > +
>    > +check_root_privs()
>    > +{
>    > +       [ x"$(id -u)" != "x0" ] && ksft_skip "You need to be root"
>    > +}
>    > +
>    > +check_scmi_testing_stack()
>    > +{
>    > +       local debugfs_root=$(findmnt -o TARGET -t debugfs | grep -v
>    TARGET)
>    > +       export SCMI_DEBUGFS_TOPDIR="$debugfs_root/scmi"
>    > +
>    > +       # Try to load module if not builtin
>    > +       if [ ! -d $SCMI_DEBUGFS_TOPDIR ]; then
>    > +               modprobe $SCMI_TEST_DRV || ksft_skip "Failed to load
>    $SCMI_TEST_DRV"
>    > +               [ ! -d $SCMI_DEBUGFS_TOPDIR ] && ksft_skip "SCMI Test
>    stack not found; is CONFIG_ARM_SCMI_TEST_DRIVER enabled ?"
>    > +       fi
>    > +}
>    > +
>    > +setup_scmi_test_env()
>    > +{
>    > +       local scmi_info_dir="${SCMI_DEBUGFS_TOPDIR}/info/"
>    > +
>    > +       export SCMI_VENDOR="$(cat ${scmi_info_dir}/vendor_id)"
>    > +       export SCMI_SUB_VENDOR="$(cat
>    ${scmi_info_dir}/sub_vendor_id)"
>    > +       export SCMI_VERS_MAJ="$(cat ${scmi_info_dir}/major_ver)"
>    > +       export SCMI_VERS_MIN="$(cat ${scmi_info_dir}/minor_ver)"
>    > +       export SCMI_VERS_IMPL="$(cat ${scmi_info_dir}/impl_ver)"
>    > +
>    > +       ksft_log "Found stack: $SCMI_VENDOR/$SCMI_SUB_VENDOR
>    ${SCMI_VERS_MAJ}.${SCMI_VERS_MAJ} - $SCMI_VERS_IMPL"
>    > +
>    > +       SCMI_TEST_PROTOS=""
>    > +       for p in ${SCMI_DEBUGFS_TOPDIR}/protocol_*; do
>    > +               SCMI_TEST_PROTOS="${SCMI_TEST_PROTOS} $(basename $p)"
>    > +       done
>    > +
>    > +       ksft_log "Found testing protocols: $SCMI_TEST_PROTOS"
>    > +
>    > +       export SCMI_TEST_PROTOS
>    > +       SCMI_TRANSPORT_IS_ATOMIC="N"
>    > +       [ -d "${SCMI_DEBUGFS_TOPDIR}/transport" ] &&
>    > +               SCMI_TRANSPORT_IS_ATOMIC=$(cat
>    "${SCMI_DEBUGFS_TOPDIR}/transport/is_atomic")
>    > +       export SCMI_TRANSPORT_IS_ATOMIC
>    > +}
>    > +
>    > +# Setup
>    > +check_root_privs
>    > +
>    > +check_scmi_testing_stack
>    > +
>    > +setup_scmi_test_env
>    > +
>    > +# Main
>    > +# Run all available tests for the found protocols
>    > +#
>    > +for proto_dir in $SCMI_TEST_PROTOS; do
>    > +       [ ! -d $proto_dir ] && ksft_log "$proto_dir tests NOT
>    supported." && continue
>    > +       export TST_PROTO_DIR="${SCMI_DEBUGFS_TOPDIR}/${proto_dir}"
>    > +       TST_PROTO_VERSION=$(cat ${TST_PROTO_DIR}/version)
>    > +       ksft_log "Running tests for SCMI $proto_dir
>    ver:$TST_PROTO_VERSION"
>    > +       for tst in $proto_dir/*; do
>    > +               ksft_scmi_run_one $tst
>    > +       done
>    > +done
>    > +
>    > +ksft_results
>    > diff --git
>    a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enab
>    le.sh
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enab
>    le.sh
>    > new file mode 100755
>    > index 000000000000..4cdf3a097ba7
>    > --- /dev/null
>    > +++
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_enab
>    le.sh
>    > @@ -0,0 +1,33 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +. ./kselftest_scmi_lib.sh
>    > +
>    > +supported_fw="EMU-SCMI-VM:userland"
>    > +ksft_scmi_check_fw_version $supported_fw
>    > +
>    > +clock_enable_disable() {
>    > +       rname=$1
>    > +       rdir=$2
>    > +       clk_op=$3
>    > +
>    > +       ksft_scmi_value_set $rdir/$clk_op Y
>    > +       ksft_scmi_value_set $rdir/$clk_op N
>    > +       ksft_log "Clock $rname: $clk_op - ON/OFF ... OK"
>    > +}
>    > +
>    > +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
>    > +ksft_log "Found Clock resources: $resources"
>    > +
>    > +for res in $resources;do
>    > +       resd="$TST_PROTO_DIR/$res"
>    > +       name="$(cat $resd/info/name)"
>    > +
>    > +       clock_enable_disable $name $resd "enable"
>    > +       if [ ksft_transport_is_atomic ]; then
>    > +               clock_enable_disable $name $resd
>    "enable_atomic_irqs_off"
>    > +               clock_enable_disable $name $resd
>    "enable_atomic_irqs_on"
>    > +       fi
>    > +done
>    > +
>    > +ksft_pass "$0"
>    > diff --git
>    a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _read.sh
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _read.sh
>    > new file mode 100755
>    > index 000000000000..88c444fd317d
>    > --- /dev/null
>    > +++
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _read.sh
>    > @@ -0,0 +1,18 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +. ./kselftest_scmi_lib.sh
>    > +
>    > +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
>    > +ksft_log "Found Clock resources: $resources"
>    > +
>    > +for res in $resources;do
>    > +       resd="$TST_PROTO_DIR/$res"
>    > +       name="$(cat $resd/info/name)"
>    > +       val=0
>    > +
>    > +       ksft_scmi_value_get $resd/rate_get_set val
>    > +       ksft_log "$name READ => $val"
>    > +done
>    > +
>    > +ksft_pass "$0"
>    > diff --git
>    a/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _write.sh
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _write.sh
>    > new file mode 100755
>    > index 000000000000..346084ec3812
>    > --- /dev/null
>    > +++
>    b/tools/testing/selftests/arm64/scmi/testcases/protocol_0x14/clock_rate
>    _write.sh
>    > @@ -0,0 +1,29 @@
>    > +#!/bin/bash
>    > +# SPDX-License-Identifier: GPL-2.0
>    > +
>    > +. ./kselftest_scmi_lib.sh
>    > +
>    > +supported_fw="EMU-SCMI-VM:userland"
>    > +ksft_scmi_check_fw_version $supported_fw
>    > +
>    > +resources=$(ksft_scmi_protocol_resources_get $TST_PROTO_DIR)
>    > +ksft_log "Found Clock resources: $resources"
>    > +
>    > +for res in $resources;do
>    > +       resd="$TST_PROTO_DIR/$res"
>    > +       name="$(cat $resd/info/name)"
>    > +       val=0
>    > +       oldval=0
>    > +       setval=0
>    > +
>    > +       ksft_scmi_value_get $resd/rate_get_set oldval
>    > +       setval=$((oldval + 666))
>    significance of 666?

Just a stupid dummy value that stands-out in my log when
testing this series .... clearly won't be the value in the final series.

>    > +
>    > +       ksft_scmi_value_set $resd/rate_get_set $setval
>     when setval is not a valid option(not in the list of possible clock
>    rates),
>     rate_get_set returns non zero value and ksft_scmi_value_set() calls
>    ksft_fail()
>     and then an exit. Is this what is intended to do?

Probably not, this should expect a failure...thanks.

Thanks,
Cristian

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2022-08-01  7:02 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-27 20:55 [RFC PATCH 00/16] Introduce SCMI test driver and related Kselftest Cristian Marussi
2022-02-27 20:55 ` Cristian Marussi
2022-02-27 20:55 ` [RFC PATCH 01/16] firmware: arm_scmi: Simplify scmi_devm_notifier_unregister Cristian Marussi
2022-02-27 20:55   ` Cristian Marussi
2022-02-27 20:55 ` [RFC PATCH 02/16] firmware: arm_scmi: Make protocols init fail on basic errors Cristian Marussi
2022-02-27 20:55   ` Cristian Marussi
2022-02-27 20:55 ` [RFC PATCH 03/16] firmware: arm_scmi: Add multiple protocols registration support Cristian Marussi
2022-02-27 20:55   ` Cristian Marussi
2022-02-27 20:55 ` [RFC PATCH 04/16] firmware: arm_scmi: Add .version_get protocol operation Cristian Marussi
2022-02-27 20:55   ` Cristian Marussi
2022-02-27 20:55 ` [RFC PATCH 05/16] firmware: arm_scmi: Expose information on configured transport Cristian Marussi
2022-02-27 20:55   ` Cristian Marussi
2022-02-27 20:55 ` [RFC PATCH 06/16] firmware: arm_scmi: Define a common SCMI_MAX_PROTOCOLS value Cristian Marussi
2022-02-27 20:55   ` Cristian Marussi
2022-02-27 20:55 ` [RFC PATCH 07/16] debugfs: Add signed versions of debugfs_create_u32/64 helpers Cristian Marussi
2022-02-27 20:55   ` Cristian Marussi
2022-03-18 13:21   ` Greg Kroah-Hartman
2022-03-18 13:21     ` Greg Kroah-Hartman
2022-03-18 15:39     ` Cristian Marussi
2022-03-18 15:39       ` Cristian Marussi
2022-03-18 15:49       ` Greg Kroah-Hartman
2022-03-18 15:49         ` Greg Kroah-Hartman
2022-02-27 20:56 ` [RFC PATCH 08/16] firmware: arm_scmi: Add SCMI Testing driver Cristian Marussi
2022-02-27 20:56   ` Cristian Marussi
2022-02-27 20:56 ` [RFC PATCH 09/16] firmware: arm_scmi: testing: Add Clock protocol full support Cristian Marussi
2022-02-27 20:56   ` Cristian Marussi
2022-02-27 20:56 ` [RFC PATCH 10/16] firmware: arm_scmi: testing: Add Sensor protocol basic support Cristian Marussi
2022-02-27 20:56   ` Cristian Marussi
2022-02-27 20:56 ` [RFC PATCH 11/16] firmware: arm_scmi: Add test driver generic notification helpers Cristian Marussi
2022-02-27 20:56   ` Cristian Marussi
2022-02-27 20:56 ` [RFC PATCH 12/16] firmware: arm_scmi: Add Sensor notifications testing support Cristian Marussi
2022-02-27 20:56   ` Cristian Marussi
2022-02-27 20:56 ` [RFC PATCH 13/16] firmware: arm_scmi: Add testing Power protocol support Cristian Marussi
2022-02-27 20:56   ` Cristian Marussi
2022-02-27 20:56 ` [RFC PATCH 14/16] firmware: arm_scmi: Add testing Voltage " Cristian Marussi
2022-02-27 20:56   ` Cristian Marussi
2022-08-01  4:47   ` Arun KS
2022-08-01  4:47     ` Arun KS
2022-08-01  6:44     ` Cristian Marussi
2022-08-01  6:44       ` Cristian Marussi
2022-02-27 20:56 ` [RFC PATCH 15/16] selftests: arm64: Add initial SCMI testcases Cristian Marussi
2022-02-27 20:56   ` Cristian Marussi
2022-08-01  4:52   ` Arun KS
2022-08-01  4:52     ` Arun KS
2022-08-01  6:54     ` Cristian Marussi
2022-08-01  6:54       ` Cristian Marussi
     [not found]   ` <CAKZGPAMoBPiikbpNE2SjDxsUQQKZC-Yn5cbn60Sx0ZRqGv47jA@mail.gmail.com>
2022-08-01  7:01     ` Cristian Marussi
2022-08-01  7:01       ` Cristian Marussi
2022-02-27 20:56 ` [RFC PATCH 16/16] [DEBUG]: firmware: arm_scmi: Add Kconfig to allow SCMI Testing driver coexistence Cristian Marussi
2022-02-27 20:56   ` Cristian Marussi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.