2021-03-16 19:50:55

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 00/38] SCMI vendor protocols and modularization

Hi all,

The current SCMI implementation does not provide an interface to easily
develop and include a custom vendor protocol implementation as prescribed
by the SCMI standard, also because, there is not currently any custom
protocol in the upstream to justify the development of a custom interface
and its maintenance.

Moreover the current interface exposes protocol operations to the SCMI
driver users attaching per-protocol operations directly to the handle
structure, which, in this way, tends to grow indefinitely for each new
protocol addition.

Beside this, protocols private data are also exposed via handle *_priv
pointers, making such private data accessible also to the SCMI drivers
even if neither really needed nor advisable.

This series wants to address this by simplifying the SCMI protocols
interface and reducing it, roughly, to these common generic operations:

- handle->devm_protocol_get()
- handle->devm_protocol_put()
- handle->notify_ops->*

All protocols' private data pointers are removed from handle too and made
accessible only to the protocols code through dedicated internal helpers.

The concept of protocol handle is also introduced in the SCMI protocol code
to represent a protocol instance initialized against a specific SCMI
instance (handle), so that all the new protocol code uses such protocol
handles wherever previously SCMI handle was used: this enable tighter
control of what is exposed to the protocol code vs the SCMI drivers.

Moreover protocol initialization is moved away from device probe and now
happens on demand when the first user shows up (first .protocol_get), while
de-initialization is performed once the last user of the protocol, even in
terms of registered notifications callback, is gone, with the SCMI core
taking care to perform all the needed underlying resource accounting.

This way any new future standard or custom protocol implementation will
expose a common unified interface which does not need to be extended
endlessly: no need to maintain a custom interface only for vendor protos.
SCMI drivers written on top of standard or custom protocols will use this
same common interface to access any protocol operations.

All existent upstream SCMI drivers are converted to this new interface.

In order to make this migration painless and to avoid the need of a big
un-mergeable jumbo patch touching all over the protocols and drivers (like
it was in v2), since v3 the migration process has been heavily split with a
bit of transient code added along the way (to preserve bisectability) and
finally removed towards the ends of the series.
Protocols and SCMI drivers migration to the new interface happens along
patches 10->30.

Leveraging this new centralized and common initialization flow we took
care also to refactor and simplify protocol-events registration and remove
*notify_priv from the handle interface making it accessible only to the
notification core.

Patch 37 builds on top of this new interface and introduces a mechanism to
define an SCMI protocol as a full blown module (possibly loadable) while
leaving the core dealing with proper resource accounting.
Standard protocols are still kept as builtins in this series, though.

Finally, patch 38 introduces dynamic SCMI devices creation to avoid having
to update the static module device table in the core each time a new driver
is added.

The whole SCMI stack can still be built alternatively as a module, with all
the standard protocols included in scmi-module.ko in such a case.

On top of this series an example SCMI Custom protocol 0x99 and related
SCMI Custom Dummy driver has been built and it is available at [1] as a
series of DEBUG patches on top this same series.

The series is currently based on sudeep/for-next/scmi [2] on top of:

commit 908a4f778dc7 ("Merge branch 'ib-iio-scmi-5.12-rc2-take3' of
git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into
for-next/scmi")

Any feedback welcome.

Thanks,

Cristian

---
v6 --> v7
- rebased on top of sudeep/for-next/scmi incudling IIO immutable branch
containing scmi_iio driver
- ported scmi_iio driver to the new API
- renamed some functions to use a naming pattern exposing the action verb
as last token (including API methods rooted at handle->)
- reverted scmi_available_protocols to scmi_protocols
- constified src_id param in events notifier registration helper
- removed devm_acquire_protocol API
- refactored scmi_get_protocol_instance()
- fixed checkpatch CHECK on MACROS params side effects
- added missing .woner to voltage.c

v5 --> v6
- rebased on top of for-next/scmi
- added devm_acquire_protocol() helper
- added Cc:

v4 --> v5
- using standard kernel list instead of ad-hoc lists in 36/36
- renamed devm_get/put_ops to devm_get/put_protocol
- dropped RFC patch on non devres get/put_ops

v3 --> v4
- rebased on sudeep/for-next/scmi v5.11-rc1
- added a few comments more

v2 --> v3
- added dynamic SCMI devices creation (getting rid of static device table)
- heavy split of protocols and drivers migrations to the new interface
- rebased on top of next-20201201 so migrating also:
+ SCMIv3.0 Voltage Domain protocol & SCMI Regulator
+ SCMIv3.0 Sensor Extensions

v1 --> v2
- rebased on for-next/scmi v5.10-rc1
- introduced protocol handles
- added devres managed devm_ variant for protocols operations
- made all scmi_protocol refs const
- introduced IDR to handle protocols instead of static array
- refactored code around fast path

[1]:https://gitlab.arm.com/linux-arm/linux-cm/-/commits/scmi_modules_ext_V7/
[2]:https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/log/?h=for-next/scmi


Cristian Marussi (38):
firmware: arm_scmi: review protocol registration interface
firmware: arm_scmi: introduce protocol handle definitions
firmware: arm_scmi: introduce devres get/put protocols operations
firmware: arm_scmi: make notifications aware of protocols users
firmware: arm_scmi: introduce new devres notification ops
firmware: arm_scmi: refactor events registration
firmware: arm_scmi: convert events registration to protocol handles
firmware: arm_scmi: add new protocol handle core xfer ops
firmware: arm_scmi: add helper to access revision area memory
firmware: arm_scmi: port Base protocol to new interface
firmware: arm_scmi: port Perf protocol to new protocols interface
cpufreq: scmi: port driver to the new scmi_perf_proto_ops interface
firmware: arm_scmi: remove legacy scmi_perf_ops protocol interface
firmware: arm_scmi: port Power protocol to new protocols interface
firmware: arm_scmi: port GenPD driver to the new scmi_power_proto_ops
interface
firmware: arm_scmi: remove legacy scmi_power_ops protocol interface
firmware: arm_scmi: port Clock protocol to new protocols interface
clk: scmi: port driver to the new scmi_clk_proto_ops interface
firmware: arm_scmi: remove legacy scmi_clk_ops protocol interface
firmware: arm_scmi: port Reset protocol to new protocols interface
reset: reset-scmi: port driver to the new scmi_reset_proto_ops
interface
firmware: arm_scmi: remove legacy scmi_reset_ops protocol interface
firmware: arm_scmi: port Sensor protocol to new protocols interface
hwmon: (scmi) port driver to the new scmi_sensor_proto_ops interface
iio/scmi: port driver to the new scmi_sensor_proto_ops interface
firmware: arm_scmi: remove legacy scmi_sensor_ops protocol interface
firmware: arm_scmi: port SystemPower protocol to new protocols
interface
firmware: arm_scmi: port Voltage protocol to new protocols interface
regulator: scmi: port driver to the new scmi_voltage_proto_ops
interface
firmware: arm_scmi: remove legacy scmi_voltage_ops protocol interface
firmware: arm_scmi: make references to handle const
firmware: arm_scmi: cleanup legacy protocol init code
firmware: arm_scmi: cleanup unused core xfer wrappers
firmware: arm_scmi: cleanup events registration transient code
firmware: arm_scmi: make notify_priv really private
firmware: arm_scmi: rename non devres notify_ops
firmware: arm_scmi: add protocol modularization support
firmware: arm_scmi: add dynamic scmi devices creation

drivers/clk/clk-scmi.c | 27 +-
drivers/cpufreq/scmi-cpufreq.c | 39 +-
drivers/firmware/arm_scmi/base.c | 142 ++--
drivers/firmware/arm_scmi/bus.c | 100 ++-
drivers/firmware/arm_scmi/clock.c | 129 ++--
drivers/firmware/arm_scmi/common.h | 133 +++-
drivers/firmware/arm_scmi/driver.c | 798 +++++++++++++++++++--
drivers/firmware/arm_scmi/notify.c | 328 +++++++--
drivers/firmware/arm_scmi/notify.h | 40 +-
drivers/firmware/arm_scmi/perf.c | 262 +++----
drivers/firmware/arm_scmi/power.c | 134 ++--
drivers/firmware/arm_scmi/reset.c | 146 ++--
drivers/firmware/arm_scmi/scmi_pm_domain.c | 26 +-
drivers/firmware/arm_scmi/sensors.c | 232 +++---
drivers/firmware/arm_scmi/system.c | 63 +-
drivers/firmware/arm_scmi/voltage.c | 126 ++--
drivers/hwmon/scmi-hwmon.c | 24 +-
drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++-
drivers/regulator/scmi-regulator.c | 42 +-
drivers/reset/reset-scmi.c | 33 +-
include/linux/scmi_protocol.h | 200 +++---
21 files changed, 2118 insertions(+), 997 deletions(-)

--
2.17.1


2021-03-16 19:51:18

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 07/38] firmware: arm_scmi: convert events registration to protocol handles

Convert refactored events registration routines to use protocol handles.

In order to maintain bisectability and to allow protocols and drivers
to be later ported to the new protocol handle interface one by one,
introduce here also some transient code and typing that will be removed
later in order to ease such transition.

Signed-off-by: Cristian Marussi <[email protected]>
---
In particular void* argument typing will be reverted later on once all
the protocols have been ported.

v6 --> v7
- reworks to fit into refactored scmi_get_protocol_instance()
---
drivers/firmware/arm_scmi/base.c | 4 ++--
drivers/firmware/arm_scmi/driver.c | 1 +
drivers/firmware/arm_scmi/notify.c | 13 +++++++++----
drivers/firmware/arm_scmi/notify.h | 7 ++++---
drivers/firmware/arm_scmi/perf.c | 9 +++++----
drivers/firmware/arm_scmi/power.c | 9 +++++----
drivers/firmware/arm_scmi/reset.c | 9 +++++----
drivers/firmware/arm_scmi/sensors.c | 12 +++++++-----
drivers/firmware/arm_scmi/system.c | 4 ++--
9 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
index 34c8a29ede0c..6a5cdef197d0 100644
--- a/drivers/firmware/arm_scmi/base.c
+++ b/drivers/firmware/arm_scmi/base.c
@@ -262,7 +262,7 @@ static int scmi_base_error_notify(const struct scmi_handle *handle, bool enable)
return ret;
}

-static int scmi_base_set_notify_enabled(const struct scmi_handle *handle,
+static int scmi_base_set_notify_enabled(const void *handle,
u8 evt_id, u32 src_id, bool enable)
{
int ret;
@@ -274,7 +274,7 @@ static int scmi_base_set_notify_enabled(const struct scmi_handle *handle,
return ret;
}

-static void *scmi_base_fill_custom_report(const struct scmi_handle *handle,
+static void *scmi_base_fill_custom_report(const void *handle,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 2357b93732ae..568b3f963e15 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -641,6 +641,7 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
*/
if (pi->proto->events) {
ret = scmi_register_protocol_events(handle, pi->proto->id,
+ &pi->ph,
pi->proto->events);
if (ret)
dev_warn(handle->dev,
diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index cbb2b004eb60..023c93deb14b 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -178,7 +178,7 @@
#define REVT_NOTIFY_SET_STATUS(revt, eid, sid, state) \
({ \
typeof(revt) r = revt; \
- r->proto->ops->set_notify_enabled(r->proto->ni->handle, \
+ r->proto->ops->set_notify_enabled(r->proto->ph, \
(eid), (sid), (state)); \
})

@@ -191,7 +191,7 @@
#define REVT_FILL_REPORT(revt, ...) \
({ \
typeof(revt) r = revt; \
- r->proto->ops->fill_custom_report(r->proto->ni->handle, \
+ r->proto->ops->fill_custom_report(r->proto->ph, \
__VA_ARGS__); \
})

@@ -279,6 +279,7 @@ struct scmi_registered_event;
* events' descriptors, whose fixed-size is determined at
* compile time.
* @registered_mtx: A mutex to protect @registered_events_handlers
+ * @ph: SCMI protocol handle reference
* @registered_events_handlers: An hashtable containing all events' handlers
* descriptors registered for this protocol
*
@@ -303,6 +304,7 @@ struct scmi_registered_events_desc {
struct scmi_registered_event **registered_events;
/* mutex to protect registered_events_handlers */
struct mutex registered_mtx;
+ const struct scmi_protocol_handle *ph;
DECLARE_HASHTABLE(registered_events_handlers, SCMI_REGISTERED_HASH_SZ);
};

@@ -735,6 +737,7 @@ scmi_allocate_registered_events_desc(struct scmi_notify_instance *ni,
* @handle: The handle identifying the platform instance against which the
* protocol's events are registered
* @proto_id: Protocol ID
+ * @ph: SCMI protocol handle.
* @ee: A structure describing the events supported by this protocol.
*
* Used by SCMI Protocols initialization code to register with the notification
@@ -745,6 +748,7 @@ scmi_allocate_registered_events_desc(struct scmi_notify_instance *ni,
* Return: 0 on Success
*/
int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
+ const struct scmi_protocol_handle *ph,
const struct scmi_protocol_events *ee)
{
int i;
@@ -754,7 +758,7 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
struct scmi_notify_instance *ni;
const struct scmi_event *evt;

- if (!ee || !ee->ops || !ee->evts ||
+ if (!ee || !ee->ops || !ee->evts || !ph ||
(!ee->num_sources && !ee->ops->get_num_sources))
return -EINVAL;

@@ -768,7 +772,7 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
if (ee->num_sources) {
num_sources = ee->num_sources;
} else {
- int nsrc = ee->ops->get_num_sources(handle);
+ int nsrc = ee->ops->get_num_sources(ph);

if (nsrc <= 0)
return -EINVAL;
@@ -786,6 +790,7 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
if (IS_ERR(pd))
return PTR_ERR(pd);

+ pd->ph = ph;
for (i = 0; i < ee->num_events; i++, evt++) {
struct scmi_registered_event *r_evt;

diff --git a/drivers/firmware/arm_scmi/notify.h b/drivers/firmware/arm_scmi/notify.h
index 03500ca9cf56..97c0e3dd973b 100644
--- a/drivers/firmware/arm_scmi/notify.h
+++ b/drivers/firmware/arm_scmi/notify.h
@@ -50,10 +50,10 @@ struct scmi_protocol_handle;
* process context.
*/
struct scmi_event_ops {
- int (*get_num_sources)(const struct scmi_handle *handle);
- int (*set_notify_enabled)(const struct scmi_handle *handle,
+ int (*get_num_sources)(const void *handle);
+ int (*set_notify_enabled)(const void *handle,
u8 evt_id, u32 src_id, bool enabled);
- void *(*fill_custom_report)(const struct scmi_handle *handle,
+ void *(*fill_custom_report)(const void *handle,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id);
@@ -82,6 +82,7 @@ void scmi_notification_exit(struct scmi_handle *handle);

struct scmi_protocol_handle;
int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
+ const struct scmi_protocol_handle *ph,
const struct scmi_protocol_events *ee);
void scmi_deregister_protocol_events(const struct scmi_handle *handle,
u8 proto_id);
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 80af823af8ec..6e37a6ebfcd8 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -772,7 +772,7 @@ static const struct scmi_perf_ops perf_ops = {
.power_scale_mw_get = scmi_power_scale_mw_get,
};

-static int scmi_perf_set_notify_enabled(const struct scmi_handle *handle,
+static int scmi_perf_set_notify_enabled(const void *handle,
u8 evt_id, u32 src_id, bool enable)
{
int ret, cmd_id;
@@ -789,7 +789,7 @@ static int scmi_perf_set_notify_enabled(const struct scmi_handle *handle,
return ret;
}

-static void *scmi_perf_fill_custom_report(const struct scmi_handle *handle,
+static void *scmi_perf_fill_custom_report(const void *handle,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
@@ -837,9 +837,10 @@ static void *scmi_perf_fill_custom_report(const struct scmi_handle *handle,
return rep;
}

-static int scmi_perf_get_num_sources(const struct scmi_handle *handle)
+static int scmi_perf_get_num_sources(const void *handle)
{
- struct scmi_perf_info *pi = handle->perf_priv;
+ struct scmi_perf_info *pi =
+ ((const struct scmi_handle *)(handle))->perf_priv;

if (!pi)
return -EINVAL;
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index 1cfd10dc18a5..5f43c45ebc13 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -213,7 +213,7 @@ static int scmi_power_request_notify(const struct scmi_handle *handle,
return ret;
}

-static int scmi_power_set_notify_enabled(const struct scmi_handle *handle,
+static int scmi_power_set_notify_enabled(const void *handle,
u8 evt_id, u32 src_id, bool enable)
{
int ret;
@@ -226,7 +226,7 @@ static int scmi_power_set_notify_enabled(const struct scmi_handle *handle,
return ret;
}

-static void *scmi_power_fill_custom_report(const struct scmi_handle *handle,
+static void *scmi_power_fill_custom_report(const void *handle,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
@@ -246,9 +246,10 @@ static void *scmi_power_fill_custom_report(const struct scmi_handle *handle,
return r;
}

-static int scmi_power_get_num_sources(const struct scmi_handle *handle)
+static int scmi_power_get_num_sources(const void *handle)
{
- struct scmi_power_info *pinfo = handle->power_priv;
+ struct scmi_power_info *pinfo =
+ ((const struct scmi_handle *)(handle))->power_priv;

if (!pinfo)
return -EINVAL;
diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 06fecf044153..572dc1fdcede 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -224,7 +224,7 @@ static int scmi_reset_notify(const struct scmi_handle *handle, u32 domain_id,
return ret;
}

-static int scmi_reset_set_notify_enabled(const struct scmi_handle *handle,
+static int scmi_reset_set_notify_enabled(const void *handle,
u8 evt_id, u32 src_id, bool enable)
{
int ret;
@@ -237,7 +237,7 @@ static int scmi_reset_set_notify_enabled(const struct scmi_handle *handle,
return ret;
}

-static void *scmi_reset_fill_custom_report(const struct scmi_handle *handle,
+static void *scmi_reset_fill_custom_report(const void *handle,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
@@ -257,9 +257,10 @@ static void *scmi_reset_fill_custom_report(const struct scmi_handle *handle,
return r;
}

-static int scmi_reset_get_num_sources(const struct scmi_handle *handle)
+static int scmi_reset_get_num_sources(const void *handle)
{
- struct scmi_reset_info *pinfo = handle->reset_priv;
+ struct scmi_reset_info *pinfo =
+ ((const struct scmi_handle *)(handle))->reset_priv;

if (!pinfo)
return -EINVAL;
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index 03b7a274ee80..e40e49869a5d 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -835,7 +835,7 @@ static const struct scmi_sensor_ops sensor_ops = {
.config_set = scmi_sensor_config_set,
};

-static int scmi_sensor_set_notify_enabled(const struct scmi_handle *handle,
+static int scmi_sensor_set_notify_enabled(const void *handle,
u8 evt_id, u32 src_id, bool enable)
{
int ret;
@@ -860,7 +860,7 @@ static int scmi_sensor_set_notify_enabled(const struct scmi_handle *handle,
return ret;
}

-static void *scmi_sensor_fill_custom_report(const struct scmi_handle *handle,
+static void *scmi_sensor_fill_custom_report(const void *handle,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
@@ -890,7 +890,8 @@ static void *scmi_sensor_fill_custom_report(const struct scmi_handle *handle,
struct scmi_sensor_info *s;
const struct scmi_sensor_update_notify_payld *p = payld;
struct scmi_sensor_update_report *r = report;
- struct sensors_info *sinfo = handle->sensor_priv;
+ struct sensors_info *sinfo =
+ ((const struct scmi_handle *)(handle))->sensor_priv;

/* payld_sz is variable for this event */
r->sensor_id = le32_to_cpu(p->sensor_id);
@@ -920,9 +921,10 @@ static void *scmi_sensor_fill_custom_report(const struct scmi_handle *handle,
return rep;
}

-static int scmi_sensor_get_num_sources(const struct scmi_handle *handle)
+static int scmi_sensor_get_num_sources(const void *handle)
{
- struct sensors_info *si = handle->sensor_priv;
+ struct sensors_info *si =
+ ((const struct scmi_handle *)(handle))->sensor_priv;

return si->num_sensors;
}
diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c
index e1ee6327f761..9d016dff4be5 100644
--- a/drivers/firmware/arm_scmi/system.c
+++ b/drivers/firmware/arm_scmi/system.c
@@ -53,7 +53,7 @@ static int scmi_system_request_notify(const struct scmi_handle *handle,
return ret;
}

-static int scmi_system_set_notify_enabled(const struct scmi_handle *handle,
+static int scmi_system_set_notify_enabled(const void *handle,
u8 evt_id, u32 src_id, bool enable)
{
int ret;
@@ -65,7 +65,7 @@ static int scmi_system_set_notify_enabled(const struct scmi_handle *handle,
return ret;
}

-static void *scmi_system_fill_custom_report(const struct scmi_handle *handle,
+static void *scmi_system_fill_custom_report(const void *handle,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
--
2.17.1

2021-03-16 19:51:59

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 08/38] firmware: arm_scmi: add new protocol handle core xfer ops

Add new core SCMI xfer operations based on protocol handles to enable
protocols to builds and send their own protocol specific messages.

Keep old original scmi_xfer_ operations interface as wrappers around the
new interface in order to let coexist old and new interfaces to ease
protocol by protocol migration.

In order to support such migration the above wrappers and some additional
transient code is also introduced in this commit: it will be later removed
as a whole once the full migration of protocols and SCMI drivers will have
been completed.

Signed-off-by: Cristian Marussi <[email protected]>
---
An exmaple of transient code:

scmi_map_protocol_handle() / scmi_map_scmi_handle()

and their usage will removed later on together with all the scmi_xfer
wrappers.

v6 --> v7
- reworks to fit into refactored scmi_get_protocol_instance()
---
drivers/firmware/arm_scmi/common.h | 12 +-
drivers/firmware/arm_scmi/driver.c | 182 +++++++++++++++++++++++------
2 files changed, 158 insertions(+), 36 deletions(-)

diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 9478b8240589..10e24ad43f0f 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -19,6 +19,8 @@

#include <asm/unaligned.h>

+#include "notify.h"
+
#define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0)
#define PROTOCOL_REV_MAJOR_MASK GENMASK(31, 16)
#define PROTOCOL_REV_MAJOR(x) (u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x)))
@@ -179,6 +181,11 @@ struct scmi_protocol_handle {
void *(*get_priv)(const struct scmi_protocol_handle *ph);
};

+const struct scmi_protocol_handle *
+scmi_map_protocol_handle(const struct scmi_handle *handle, u8 prot_id);
+
+struct scmi_handle *scmi_map_scmi_handle(const struct scmi_protocol_handle *ph);
+
/**
* struct scmi_xfer_ops - References to the core SCMI xfer operations.
* @version_get: Get this version protocol.
@@ -217,6 +224,7 @@ void scmi_setup_protocol_implemented(const struct scmi_handle *handle,

int scmi_base_protocol_init(struct scmi_handle *h);
typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *);
+typedef int (*scmi_prot_init_ph_fn_t)(const struct scmi_protocol_handle *);

/**
* struct scmi_protocol - Protocol descriptor
@@ -231,8 +239,8 @@ typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *);
struct scmi_protocol {
const u8 id;
const scmi_prot_init_fn_t init;
- const scmi_prot_init_fn_t instance_init;
- const scmi_prot_init_fn_t instance_deinit;
+ const scmi_prot_init_ph_fn_t instance_init;
+ const scmi_prot_init_ph_fn_t instance_deinit;
const void *ops;
const struct scmi_protocol_events *events;
};
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 568b3f963e15..8db450a0c294 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -349,19 +349,54 @@ void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
}
}

+/* Transient code wrapper to ease API migration */
+const struct scmi_protocol_handle *
+scmi_map_protocol_handle(const struct scmi_handle *handle, u8 prot_id)
+{
+ struct scmi_info *info = handle_to_scmi_info(handle);
+ const struct scmi_protocol_instance *pi;
+
+ mutex_lock(&info->protocols_mtx);
+ pi = idr_find(&info->protocols, prot_id);
+ mutex_unlock(&info->protocols_mtx);
+
+ return pi ? &pi->ph : NULL;
+}
+
+/* Transient code wrapper to ease API migration */
+struct scmi_handle *scmi_map_scmi_handle(const struct scmi_protocol_handle *ph)
+{
+ const struct scmi_protocol_instance *pi = ph_to_pi(ph);
+
+ return (struct scmi_handle *)pi->handle;
+}
+
/**
- * scmi_xfer_put() - Release a transmit message
+ * xfer_put() - Release a transmit message
*
- * @handle: Pointer to SCMI entity handle
+ * @ph: Pointer to SCMI protocol handle
* @xfer: message that was reserved by scmi_xfer_get
*/
-void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+static void xfer_put(const struct scmi_protocol_handle *ph,
+ struct scmi_xfer *xfer)
{
- struct scmi_info *info = handle_to_scmi_info(handle);
+ const struct scmi_protocol_instance *pi = ph_to_pi(ph);
+ struct scmi_info *info = handle_to_scmi_info(pi->handle);

__scmi_xfer_put(&info->tx_minfo, xfer);
}

+void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer)
+{
+ const struct scmi_protocol_handle *ph;
+
+ ph = scmi_map_protocol_handle(h, xfer->hdr.protocol_id);
+ if (!ph)
+ return;
+
+ return xfer_put(ph, xfer);
+}
+
#define SCMI_MAX_POLL_TO_NS (100 * NSEC_PER_USEC)

static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
@@ -374,23 +409,32 @@ static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
}

/**
- * scmi_do_xfer() - Do one transfer
+ * do_xfer() - Do one transfer
*
- * @handle: Pointer to SCMI entity handle
+ * @ph: Pointer to SCMI protocol handle
* @xfer: Transfer to initiate and wait for response
*
* Return: -ETIMEDOUT in case of no response, if transmit error,
* return corresponding error, else if all goes well,
* return 0.
*/
-int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+static int do_xfer(const struct scmi_protocol_handle *ph,
+ struct scmi_xfer *xfer)
{
int ret;
int timeout;
- struct scmi_info *info = handle_to_scmi_info(handle);
+ const struct scmi_protocol_instance *pi = ph_to_pi(ph);
+ struct scmi_info *info = handle_to_scmi_info(pi->handle);
struct device *dev = info->dev;
struct scmi_chan_info *cinfo;

+ /*
+ * Re-instate protocol id here from protocol handle so that cannot be
+ * overridden by mistake (or malice) by the protocol code mangling with
+ * the scmi_xfer structure.
+ */
+ xfer->hdr.protocol_id = pi->proto->id;
+
cinfo = idr_find(&info->tx_idr, xfer->hdr.protocol_id);
if (unlikely(!cinfo))
return -EINVAL;
@@ -436,35 +480,62 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
return ret;
}

+int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer)
+{
+ const struct scmi_protocol_handle *ph;
+
+ ph = scmi_map_protocol_handle(h, xfer->hdr.protocol_id);
+ if (!ph)
+ return -EINVAL;
+
+ return do_xfer(ph, xfer);
+}
+
+static void reset_rx_to_maxsz(const struct scmi_protocol_handle *ph,
+ struct scmi_xfer *xfer)
+{
+ const struct scmi_protocol_instance *pi = ph_to_pi(ph);
+ struct scmi_info *info = handle_to_scmi_info(pi->handle);
+
+ xfer->rx.len = info->desc->max_msg_size;
+}
+
void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle,
struct scmi_xfer *xfer)
{
- struct scmi_info *info = handle_to_scmi_info(handle);
+ const struct scmi_protocol_handle *ph;

- xfer->rx.len = info->desc->max_msg_size;
+ ph = scmi_map_protocol_handle(handle, xfer->hdr.protocol_id);
+ if (!ph)
+ return;
+
+ return reset_rx_to_maxsz(ph, xfer);
}

#define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC)

/**
- * scmi_do_xfer_with_response() - Do one transfer and wait until the delayed
+ * do_xfer_with_response() - Do one transfer and wait until the delayed
* response is received
*
- * @handle: Pointer to SCMI entity handle
+ * @ph: Pointer to SCMI protocol handle
* @xfer: Transfer to initiate and wait for response
*
* Return: -ETIMEDOUT in case of no delayed response, if transmit error,
* return corresponding error, else if all goes well, return 0.
*/
-int scmi_do_xfer_with_response(const struct scmi_handle *handle,
- struct scmi_xfer *xfer)
+static int do_xfer_with_response(const struct scmi_protocol_handle *ph,
+ struct scmi_xfer *xfer)
{
int ret, timeout = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT);
+ const struct scmi_protocol_instance *pi = ph_to_pi(ph);
DECLARE_COMPLETION_ONSTACK(async_response);

+ xfer->hdr.protocol_id = pi->proto->id;
+
xfer->async_done = &async_response;

- ret = scmi_do_xfer(handle, xfer);
+ ret = do_xfer(ph, xfer);
if (!ret && !wait_for_completion_timeout(xfer->async_done, timeout))
ret = -ETIMEDOUT;

@@ -472,12 +543,23 @@ int scmi_do_xfer_with_response(const struct scmi_handle *handle,
return ret;
}

+int scmi_do_xfer_with_response(const struct scmi_handle *h,
+ struct scmi_xfer *xfer)
+{
+ const struct scmi_protocol_handle *ph;
+
+ ph = scmi_map_protocol_handle(h, xfer->hdr.protocol_id);
+ if (!ph)
+ return -EINVAL;
+
+ return do_xfer_with_response(ph, xfer);
+}
+
/**
- * scmi_xfer_get_init() - Allocate and initialise one message for transmit
+ * xfer_get_init() - Allocate and initialise one message for transmit
*
- * @handle: Pointer to SCMI entity handle
+ * @ph: Pointer to SCMI protocol handle
* @msg_id: Message identifier
- * @prot_id: Protocol identifier for the message
* @tx_size: transmit message size
* @rx_size: receive message size
* @p: pointer to the allocated and initialised message
@@ -488,12 +570,14 @@ int scmi_do_xfer_with_response(const struct scmi_handle *handle,
* Return: 0 if all went fine with @p pointing to message, else
* corresponding error.
*/
-int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
- size_t tx_size, size_t rx_size, struct scmi_xfer **p)
+static int xfer_get_init(const struct scmi_protocol_handle *ph,
+ u8 msg_id, size_t tx_size, size_t rx_size,
+ struct scmi_xfer **p)
{
int ret;
struct scmi_xfer *xfer;
- struct scmi_info *info = handle_to_scmi_info(handle);
+ const struct scmi_protocol_instance *pi = ph_to_pi(ph);
+ struct scmi_info *info = handle_to_scmi_info(pi->handle);
struct scmi_xfers_info *minfo = &info->tx_minfo;
struct device *dev = info->dev;

@@ -502,7 +586,7 @@ int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
tx_size > info->desc->max_msg_size)
return -ERANGE;

- xfer = scmi_xfer_get(handle, minfo);
+ xfer = scmi_xfer_get(pi->handle, minfo);
if (IS_ERR(xfer)) {
ret = PTR_ERR(xfer);
dev_err(dev, "failed to get free message slot(%d)\n", ret);
@@ -512,7 +596,7 @@ int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
xfer->tx.len = tx_size;
xfer->rx.len = rx_size ? : info->desc->max_msg_size;
xfer->hdr.id = msg_id;
- xfer->hdr.protocol_id = prot_id;
+ xfer->hdr.protocol_id = pi->proto->id;
xfer->hdr.poll_completion = false;

*p = xfer;
@@ -520,39 +604,59 @@ int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
return 0;
}

+int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
+ size_t tx_size, size_t rx_size, struct scmi_xfer **p)
+{
+ const struct scmi_protocol_handle *ph;
+
+ ph = scmi_map_protocol_handle(h, prot_id);
+ if (!ph)
+ return -EINVAL;
+
+ return xfer_get_init(ph, msg_id, tx_size, rx_size, p);
+}
+
/**
- * scmi_version_get() - command to get the revision of the SCMI entity
+ * version_get() - command to get the revision of the SCMI entity
*
- * @handle: Pointer to SCMI entity handle
- * @protocol: Protocol identifier for the message
+ * @ph: Pointer to SCMI protocol handle
* @version: Holds returned version of protocol.
*
* Updates the SCMI information in the internal data structure.
*
* Return: 0 if all went fine, else return appropriate error.
*/
-int scmi_version_get(const struct scmi_handle *handle, u8 protocol,
- u32 *version)
+static int version_get(const struct scmi_protocol_handle *ph, u32 *version)
{
int ret;
__le32 *rev_info;
struct scmi_xfer *t;

- ret = scmi_xfer_get_init(handle, PROTOCOL_VERSION, protocol, 0,
- sizeof(*version), &t);
+ ret = xfer_get_init(ph, PROTOCOL_VERSION, 0, sizeof(*version), &t);
if (ret)
return ret;

- ret = scmi_do_xfer(handle, t);
+ ret = do_xfer(ph, t);
if (!ret) {
rev_info = t->rx.buf;
*version = le32_to_cpu(*rev_info);
}

- scmi_xfer_put(handle, t);
+ xfer_put(ph, t);
return ret;
}

+int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version)
+{
+ const struct scmi_protocol_handle *ph;
+
+ ph = scmi_map_protocol_handle(h, protocol);
+ if (!ph)
+ return -EINVAL;
+
+ return version_get(ph, version);
+}
+
/**
* scmi_set_protocol_priv - Set protocol specific data at init time
*
@@ -585,6 +689,15 @@ static void *scmi_get_protocol_priv(const struct scmi_protocol_handle *ph)
return pi->priv;
}

+static const struct scmi_xfer_ops xfer_ops = {
+ .version_get = version_get,
+ .xfer_get_init = xfer_get_init,
+ .reset_rx_to_maxsz = reset_rx_to_maxsz,
+ .do_xfer = do_xfer,
+ .do_xfer_with_response = do_xfer_with_response,
+ .xfer_put = xfer_put,
+};
+
/**
* scmi_alloc_init_protocol_instance - Allocate and initialize a protocol
* instance descriptor.
@@ -622,11 +735,12 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
pi->proto = proto;
pi->handle = handle;
pi->ph.dev = handle->dev;
+ pi->ph.xops = &xfer_ops;
pi->ph.set_priv = scmi_set_protocol_priv;
pi->ph.get_priv = scmi_get_protocol_priv;
refcount_set(&pi->users, 1);
/* proto->init is assured NON NULL by scmi_protocol_register */
- ret = pi->proto->instance_init(handle);
+ ret = pi->proto->instance_init(&pi->ph);
if (ret)
goto clean;

@@ -737,7 +851,7 @@ void scmi_protocol_release(struct scmi_handle *handle, u8 protocol_id)
scmi_deregister_protocol_events(handle, protocol_id);

if (pi->proto->instance_deinit)
- pi->proto->instance_deinit(handle);
+ pi->proto->instance_deinit(&pi->ph);

idr_remove(&info->protocols, protocol_id);

--
2.17.1

2021-03-16 19:52:53

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 09/38] firmware: arm_scmi: add helper to access revision area memory

Add an helper to grab, from a protocol handle, the handle common memory
area allocated to store SCMI version data which is exposed on sysfs.
Such helper will be needed by SCMI Base protocol initialization once it
will be moved to new protocol handles scheme.

Signed-off-by: Cristian Marussi <[email protected]>
---
v6 --> v7
- renamed non-static function to fit scmi_<OBJ>_<ACTION> naming pattern
---
drivers/firmware/arm_scmi/common.h | 2 ++
drivers/firmware/arm_scmi/driver.c | 19 +++++++++++++++++++
2 files changed, 21 insertions(+)

diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 10e24ad43f0f..6a06adc73f20 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -215,6 +215,8 @@ struct scmi_xfer_ops {
struct scmi_xfer *xfer);
};

+struct scmi_revision_info *
+scmi_revision_area_get(const struct scmi_protocol_handle *ph);
int scmi_handle_put(const struct scmi_handle *handle);
struct scmi_handle *scmi_handle_get(struct device *dev);
void scmi_set_handle(struct scmi_device *scmi_dev);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 8db450a0c294..fa83e1aec6d7 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -698,6 +698,25 @@ static const struct scmi_xfer_ops xfer_ops = {
.xfer_put = xfer_put,
};

+/**
+ * scmi_revision_area_get - Retrieve version memory area.
+ *
+ * @ph: A reference to the protocol handle.
+ *
+ * A helper to grab the version memory area reference during SCMI Base protocol
+ * initialization.
+ *
+ * Return: A reference to the version memory area associated to the SCMI
+ * instance underlying this protocol handle.
+ */
+struct scmi_revision_info *
+scmi_revision_area_get(const struct scmi_protocol_handle *ph)
+{
+ const struct scmi_protocol_instance *pi = ph_to_pi(ph);
+
+ return pi->handle->version;
+}
+
/**
* scmi_alloc_init_protocol_instance - Allocate and initialize a protocol
* instance descriptor.
--
2.17.1

2021-03-16 19:52:57

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 10/38] firmware: arm_scmi: port Base protocol to new interface

Port Base protocol to new protocol handles based interface.

Signed-off-by: Cristian Marussi <[email protected]>
---
v6 --> v7
- renamed non-static function to fit scmi_<OBJ>_<ACTION> naming pattern
---
drivers/firmware/arm_scmi/base.c | 117 +++++++++++++++--------------
drivers/firmware/arm_scmi/common.h | 3 +-
drivers/firmware/arm_scmi/driver.c | 14 +++-
3 files changed, 71 insertions(+), 63 deletions(-)

diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
index 6a5cdef197d0..b5b6bd08132e 100644
--- a/drivers/firmware/arm_scmi/base.c
+++ b/drivers/firmware/arm_scmi/base.c
@@ -50,30 +50,30 @@ struct scmi_base_error_notify_payld {
* scmi_base_attributes_get() - gets the implementation details
* that are associated with the base protocol.
*
- * @handle: SCMI entity handle
+ * @ph: SCMI protocol handle
*
* Return: 0 on success, else appropriate SCMI error.
*/
-static int scmi_base_attributes_get(const struct scmi_handle *handle)
+static int scmi_base_attributes_get(const struct scmi_protocol_handle *ph)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_resp_base_attributes *attr_info;
- struct scmi_revision_info *rev = handle->version;
+ struct scmi_revision_info *rev = ph->get_priv(ph);

- ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
- SCMI_PROTOCOL_BASE, 0, sizeof(*attr_info), &t);
+ ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
+ 0, sizeof(*attr_info), &t);
if (ret)
return ret;

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
attr_info = t->rx.buf;
rev->num_protocols = attr_info->num_protocols;
rev->num_agents = attr_info->num_agents;
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);

return ret;
}
@@ -81,19 +81,20 @@ static int scmi_base_attributes_get(const struct scmi_handle *handle)
/**
* scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
*
- * @handle: SCMI entity handle
+ * @ph: SCMI protocol handle
* @sub_vendor: specify true if sub-vendor ID is needed
*
* Return: 0 on success, else appropriate SCMI error.
*/
static int
-scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
+scmi_base_vendor_id_get(const struct scmi_protocol_handle *ph, bool sub_vendor)
{
u8 cmd;
int ret, size;
char *vendor_id;
struct scmi_xfer *t;
- struct scmi_revision_info *rev = handle->version;
+ struct scmi_revision_info *rev = ph->get_priv(ph);
+

if (sub_vendor) {
cmd = BASE_DISCOVER_SUB_VENDOR;
@@ -105,15 +106,15 @@ scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
size = ARRAY_SIZE(rev->vendor_id);
}

- ret = scmi_xfer_get_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t);
+ ret = ph->xops->xfer_get_init(ph, cmd, 0, size, &t);
if (ret)
return ret;

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret)
memcpy(vendor_id, t->rx.buf, size);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);

return ret;
}
@@ -123,30 +124,30 @@ scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
* implementation 32-bit version. The format of the version number is
* vendor-specific
*
- * @handle: SCMI entity handle
+ * @ph: SCMI protocol handle
*
* Return: 0 on success, else appropriate SCMI error.
*/
static int
-scmi_base_implementation_version_get(const struct scmi_handle *handle)
+scmi_base_implementation_version_get(const struct scmi_protocol_handle *ph)
{
int ret;
__le32 *impl_ver;
struct scmi_xfer *t;
- struct scmi_revision_info *rev = handle->version;
+ struct scmi_revision_info *rev = ph->get_priv(ph);

- ret = scmi_xfer_get_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION,
- SCMI_PROTOCOL_BASE, 0, sizeof(*impl_ver), &t);
+ ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_IMPLEMENT_VERSION,
+ 0, sizeof(*impl_ver), &t);
if (ret)
return ret;

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
impl_ver = t->rx.buf;
rev->impl_ver = le32_to_cpu(*impl_ver);
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);

return ret;
}
@@ -155,23 +156,24 @@ scmi_base_implementation_version_get(const struct scmi_handle *handle)
* scmi_base_implementation_list_get() - gets the list of protocols it is
* OSPM is allowed to access
*
- * @handle: SCMI entity handle
+ * @ph: SCMI protocol handle
* @protocols_imp: pointer to hold the list of protocol identifiers
*
* Return: 0 on success, else appropriate SCMI error.
*/
-static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
- u8 *protocols_imp)
+static int
+scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
+ u8 *protocols_imp)
{
u8 *list;
int ret, loop;
struct scmi_xfer *t;
__le32 *num_skip, *num_ret;
u32 tot_num_ret = 0, loop_num_ret;
- struct device *dev = handle->dev;
+ struct device *dev = ph->dev;

- ret = scmi_xfer_get_init(handle, BASE_DISCOVER_LIST_PROTOCOLS,
- SCMI_PROTOCOL_BASE, sizeof(*num_skip), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS,
+ sizeof(*num_skip), 0, &t);
if (ret)
return ret;

@@ -183,7 +185,7 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
/* Set the number of protocols to be skipped/already read */
*num_skip = cpu_to_le32(tot_num_ret);

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (ret)
break;

@@ -198,10 +200,10 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle,

tot_num_ret += loop_num_ret;

- scmi_reset_rx_to_maxsz(handle, t);
+ ph->xops->reset_rx_to_maxsz(ph, t);
} while (loop_num_ret);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);

return ret;
}
@@ -209,7 +211,7 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
/**
* scmi_base_discover_agent_get() - discover the name of an agent
*
- * @handle: SCMI entity handle
+ * @ph: SCMI protocol handle
* @id: Agent identifier
* @name: Agent identifier ASCII string
*
@@ -218,63 +220,63 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
*
* Return: 0 on success, else appropriate SCMI error.
*/
-static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
+static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph,
int id, char *name)
{
int ret;
struct scmi_xfer *t;

- ret = scmi_xfer_get_init(handle, BASE_DISCOVER_AGENT,
- SCMI_PROTOCOL_BASE, sizeof(__le32),
- SCMI_MAX_STR_SIZE, &t);
+ ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT,
+ sizeof(__le32), SCMI_MAX_STR_SIZE, &t);
if (ret)
return ret;

put_unaligned_le32(id, t->tx.buf);

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret)
strlcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);

return ret;
}

-static int scmi_base_error_notify(const struct scmi_handle *handle, bool enable)
+static int scmi_base_error_notify(const struct scmi_protocol_handle *ph,
+ bool enable)
{
int ret;
u32 evt_cntl = enable ? BASE_TP_NOTIFY_ALL : 0;
struct scmi_xfer *t;
struct scmi_msg_base_error_notify *cfg;

- ret = scmi_xfer_get_init(handle, BASE_NOTIFY_ERRORS,
- SCMI_PROTOCOL_BASE, sizeof(*cfg), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, BASE_NOTIFY_ERRORS,
+ sizeof(*cfg), 0, &t);
if (ret)
return ret;

cfg = t->tx.buf;
cfg->event_control = cpu_to_le32(evt_cntl);

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int scmi_base_set_notify_enabled(const void *handle,
+static int scmi_base_set_notify_enabled(const void *ph,
u8 evt_id, u32 src_id, bool enable)
{
int ret;

- ret = scmi_base_error_notify(handle, enable);
+ ret = scmi_base_error_notify(ph, enable);
if (ret)
pr_debug("FAIL_ENABLED - evt[%X] ret:%d\n", evt_id, ret);

return ret;
}

-static void *scmi_base_fill_custom_report(const void *handle,
+static void *scmi_base_fill_custom_report(const void *ph,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
@@ -326,17 +328,16 @@ static const struct scmi_protocol_events base_protocol_events = {
.num_sources = SCMI_BASE_NUM_SOURCES,
};

-int scmi_base_protocol_init(struct scmi_handle *h)
+static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
{
int id, ret;
u8 *prot_imp;
u32 version;
char name[SCMI_MAX_STR_SIZE];
- const struct scmi_handle *handle = h;
- struct device *dev = handle->dev;
- struct scmi_revision_info *rev = handle->version;
+ struct device *dev = ph->dev;
+ struct scmi_revision_info *rev = scmi_revision_area_get(ph);

- ret = scmi_version_get(handle, SCMI_PROTOCOL_BASE, &version);
+ ret = ph->xops->version_get(ph, &version);
if (ret)
return ret;

@@ -346,13 +347,15 @@ int scmi_base_protocol_init(struct scmi_handle *h)

rev->major_ver = PROTOCOL_REV_MAJOR(version),
rev->minor_ver = PROTOCOL_REV_MINOR(version);
+ ph->set_priv(ph, rev);
+
+ scmi_base_attributes_get(ph);
+ scmi_base_vendor_id_get(ph, false);
+ scmi_base_vendor_id_get(ph, true);
+ scmi_base_implementation_version_get(ph);
+ scmi_base_implementation_list_get(ph, prot_imp);

- scmi_base_attributes_get(handle);
- scmi_base_vendor_id_get(handle, false);
- scmi_base_vendor_id_get(handle, true);
- scmi_base_implementation_version_get(handle);
- scmi_base_implementation_list_get(handle, prot_imp);
- scmi_setup_protocol_implemented(handle, prot_imp);
+ scmi_setup_protocol_implemented(ph, prot_imp);

dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",
rev->major_ver, rev->minor_ver, rev->vendor_id,
@@ -361,7 +364,7 @@ int scmi_base_protocol_init(struct scmi_handle *h)
rev->num_agents);

for (id = 0; id < rev->num_agents; id++) {
- scmi_base_discover_agent_get(handle, id, name);
+ scmi_base_discover_agent_get(ph, id, name);
dev_dbg(dev, "Agent %d: %s\n", id, name);
}

@@ -370,7 +373,7 @@ int scmi_base_protocol_init(struct scmi_handle *h)

static const struct scmi_protocol scmi_base = {
.id = SCMI_PROTOCOL_BASE,
- .init = &scmi_base_protocol_init,
+ .instance_init = &scmi_base_protocol_init,
.ops = NULL,
.events = &base_protocol_events,
};
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 6a06adc73f20..1bd332b5daa7 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -221,10 +221,9 @@ int scmi_handle_put(const struct scmi_handle *handle);
struct scmi_handle *scmi_handle_get(struct device *dev);
void scmi_set_handle(struct scmi_device *scmi_dev);
int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version);
-void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph,
u8 *prot_imp);

-int scmi_base_protocol_init(struct scmi_handle *h);
typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *);
typedef int (*scmi_prot_init_ph_fn_t)(const struct scmi_protocol_handle *);

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index fa83e1aec6d7..23d26e8f2684 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -883,10 +883,11 @@ void scmi_protocol_release(struct scmi_handle *handle, u8 protocol_id)
mutex_unlock(&info->protocols_mtx);
}

-void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph,
u8 *prot_imp)
{
- struct scmi_info *info = handle_to_scmi_info(handle);
+ const struct scmi_protocol_instance *pi = ph_to_pi(ph);
+ struct scmi_info *info = handle_to_scmi_info(pi->handle);

info->protocols_imp = prot_imp;
}
@@ -1263,9 +1264,14 @@ static int scmi_probe(struct platform_device *pdev)
if (scmi_notification_init(handle))
dev_err(dev, "SCMI Notifications NOT available.\n");

- ret = scmi_base_protocol_init(handle);
+ /*
+ * Trigger SCMI Base protocol initialization.
+ * It's mandatory and won't be ever released/deinit until the
+ * SCMI stack is shutdown/unloaded as a whole.
+ */
+ ret = scmi_protocol_acquire(handle, SCMI_PROTOCOL_BASE);
if (ret) {
- dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
+ dev_err(dev, "unable to communicate with SCMI\n");
return ret;
}

--
2.17.1

2021-03-16 19:53:25

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 13/38] firmware: arm_scmi: remove legacy scmi_perf_ops protocol interface

Now that all the SCMI driver users have been migrated to the new interface
remove the legacy interface and all the transient code.

Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/firmware/arm_scmi/perf.c | 120 -------------------------------
include/linux/scmi_protocol.h | 27 -------
2 files changed, 147 deletions(-)

diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 73f04d7809b3..9770821c4819 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -391,15 +391,6 @@ static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
return scmi_perf_mb_limits_set(ph, domain, max_perf, min_perf);
}

-static int __scmi_perf_limits_set(const struct scmi_handle *handle,
- u32 domain, u32 max_perf, u32 min_perf)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_perf_limits_set(ph, domain, max_perf, min_perf);
-}
-
static int scmi_perf_mb_limits_get(const struct scmi_protocol_handle *ph,
u32 domain, u32 *max_perf, u32 *min_perf)
{
@@ -441,15 +432,6 @@ static int scmi_perf_limits_get(const struct scmi_protocol_handle *ph,
return scmi_perf_mb_limits_get(ph, domain, max_perf, min_perf);
}

-static int __scmi_perf_limits_get(const struct scmi_handle *handle,
- u32 domain, u32 *max_perf, u32 *min_perf)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_perf_limits_get(ph, domain, max_perf, min_perf);
-}
-
static int scmi_perf_mb_level_set(const struct scmi_protocol_handle *ph,
u32 domain, u32 level, bool poll)
{
@@ -487,15 +469,6 @@ static int scmi_perf_level_set(const struct scmi_protocol_handle *ph,
return scmi_perf_mb_level_set(ph, domain, level, poll);
}

-static int __scmi_perf_level_set(const struct scmi_handle *handle,
- u32 domain, u32 level, bool poll)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_perf_level_set(ph, domain, level, poll);
-}
-
static int scmi_perf_mb_level_get(const struct scmi_protocol_handle *ph,
u32 domain, u32 *level, bool poll)
{
@@ -532,15 +505,6 @@ static int scmi_perf_level_get(const struct scmi_protocol_handle *ph,
return scmi_perf_mb_level_get(ph, domain, level, poll);
}

-static int __scmi_perf_level_get(const struct scmi_handle *handle,
- u32 domain, u32 *level, bool poll)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_perf_level_get(ph, domain, level, poll);
-}
-
static int scmi_perf_level_limits_notify(const struct scmi_protocol_handle *ph,
u32 domain, int message_id,
bool enable)
@@ -704,15 +668,6 @@ static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
return 0;
}

-static int __scmi_dvfs_device_opps_add(const struct scmi_handle *handle,
- struct device *dev)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_dvfs_device_opps_add(ph, dev);
-}
-
static int
scmi_dvfs_transition_latency_get(const struct scmi_protocol_handle *ph,
struct device *dev)
@@ -729,16 +684,6 @@ scmi_dvfs_transition_latency_get(const struct scmi_protocol_handle *ph,
return dom->opp[dom->opp_count - 1].trans_latency_us * 1000;
}

-static int
-__scmi_dvfs_transition_latency_get(const struct scmi_handle *handle,
- struct device *dev)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_dvfs_transition_latency_get(ph, dev);
-}
-
static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain,
unsigned long freq, bool poll)
{
@@ -748,15 +693,6 @@ static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain,
return scmi_perf_level_set(ph, domain, freq / dom->mult_factor, poll);
}

-static int __scmi_dvfs_freq_set(const struct scmi_handle *handle,
- u32 domain, unsigned long freq, bool poll)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_dvfs_freq_set(ph, domain, freq, poll);
-}
-
static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain,
unsigned long *freq, bool poll)
{
@@ -772,15 +708,6 @@ static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain,
return ret;
}

-static int __scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain,
- unsigned long *freq, bool poll)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_dvfs_freq_get(ph, domain, freq, poll);
-}
-
static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
u32 domain, unsigned long *freq,
unsigned long *power)
@@ -809,16 +736,6 @@ static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
return ret;
}

-static int __scmi_dvfs_est_power_get(const struct scmi_handle *handle,
- u32 domain, unsigned long *freq,
- unsigned long *power)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_dvfs_est_power_get(ph, domain, freq, power);
-}
-
static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph,
struct device *dev)
{
@@ -830,15 +747,6 @@ static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph,
return dom->fc_info && dom->fc_info->level_set_addr;
}

-static bool __scmi_fast_switch_possible(const struct scmi_handle *handle,
- struct device *dev)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_fast_switch_possible(ph, dev);
-}
-
static bool scmi_power_scale_mw_get(const struct scmi_protocol_handle *ph)
{
struct scmi_perf_info *pi = ph->get_priv(ph);
@@ -846,29 +754,6 @@ static bool scmi_power_scale_mw_get(const struct scmi_protocol_handle *ph)
return pi->power_scale_mw;
}

-static bool __scmi_power_scale_mw_get(const struct scmi_handle *handle)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_PERF);
-
- return scmi_power_scale_mw_get(ph);
-}
-
-static const struct scmi_perf_ops perf_ops = {
- .limits_set = __scmi_perf_limits_set,
- .limits_get = __scmi_perf_limits_get,
- .level_set = __scmi_perf_level_set,
- .level_get = __scmi_perf_level_get,
- .device_domain_id = scmi_dev_domain_id,
- .transition_latency_get = __scmi_dvfs_transition_latency_get,
- .device_opps_add = __scmi_dvfs_device_opps_add,
- .freq_set = __scmi_dvfs_freq_set,
- .freq_get = __scmi_dvfs_freq_get,
- .est_power_get = __scmi_dvfs_est_power_get,
- .fast_switch_possible = __scmi_fast_switch_possible,
- .power_scale_mw_get = __scmi_power_scale_mw_get,
-};
-
static const struct scmi_perf_proto_ops perf_proto_ops = {
.limits_set = scmi_perf_limits_set,
.limits_get = scmi_perf_limits_get,
@@ -991,7 +876,6 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
int domain;
u32 version;
struct scmi_perf_info *pinfo;
- struct scmi_handle *handle;

ph->xops->version_get(ph, &version);

@@ -1021,10 +905,6 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)

pinfo->version = version;

- /* Transient code for legacy ops interface */
- handle = scmi_map_scmi_handle(ph);
- handle->perf_ops = &perf_ops;
-
return ph->set_priv(ph, pinfo);
}

diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index c658aec78e15..c71d7c297125 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -127,31 +127,6 @@ struct scmi_perf_proto_ops {
bool (*power_scale_mw_get)(const struct scmi_protocol_handle *ph);
};

-struct scmi_perf_ops {
- int (*limits_set)(const struct scmi_handle *handle, u32 domain,
- u32 max_perf, u32 min_perf);
- int (*limits_get)(const struct scmi_handle *handle, u32 domain,
- u32 *max_perf, u32 *min_perf);
- int (*level_set)(const struct scmi_handle *handle, u32 domain,
- u32 level, bool poll);
- int (*level_get)(const struct scmi_handle *handle, u32 domain,
- u32 *level, bool poll);
- int (*device_domain_id)(struct device *dev);
- int (*transition_latency_get)(const struct scmi_handle *handle,
- struct device *dev);
- int (*device_opps_add)(const struct scmi_handle *handle,
- struct device *dev);
- int (*freq_set)(const struct scmi_handle *handle, u32 domain,
- unsigned long rate, bool poll);
- int (*freq_get)(const struct scmi_handle *handle, u32 domain,
- unsigned long *rate, bool poll);
- int (*est_power_get)(const struct scmi_handle *handle, u32 domain,
- unsigned long *rate, unsigned long *power);
- bool (*fast_switch_possible)(const struct scmi_handle *handle,
- struct device *dev);
- bool (*power_scale_mw_get)(const struct scmi_handle *handle);
-};
-
/**
* struct scmi_power_ops - represents the various operations provided
* by SCMI Power Protocol
@@ -631,7 +606,6 @@ struct scmi_notify_ops {
* @dev: pointer to the SCMI device
* @version: pointer to the structure containing SCMI version information
* @power_ops: pointer to set of power protocol operations
- * @perf_ops: pointer to set of performance protocol operations
* @clk_ops: pointer to set of clock protocol operations
* @sensor_ops: pointer to set of sensor protocol operations
* @reset_ops: pointer to set of reset protocol operations
@@ -656,7 +630,6 @@ struct scmi_notify_ops {
struct scmi_handle {
struct device *dev;
struct scmi_revision_info *version;
- const struct scmi_perf_ops *perf_ops;
const struct scmi_clk_ops *clk_ops;
const struct scmi_power_ops *power_ops;
const struct scmi_sensor_ops *sensor_ops;
--
2.17.1

2021-03-16 19:53:25

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 12/38] cpufreq: scmi: port driver to the new scmi_perf_proto_ops interface

Port driver to the new SCMI Perf interface based on protocol handles
and common devm_get_ops().

Cc: Rafael J. Wysocki <[email protected]>
Cc: Viresh Kumar <[email protected]>
Acked-by: Viresh Kumar <[email protected]>
Signed-off-by: Cristian Marussi <[email protected]>
---
v6 -> v7
- fixed Copyright
- reworked on top of recent cpufreq changes:
dac7a57d2a89 scmi-cpufreq: Get opp_shared_cpus from opp-v2 for EM
2a3390d53bd7 scmi-cpufreq: Remove deferred probe
- renamed non-static function to fit scmi_<OBJ>_<ACTION> naming pattern
v4 --> v5
- using renamed devm_get/put_protocol
---
drivers/cpufreq/scmi-cpufreq.c | 39 ++++++++++++++++++----------------
1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index a4e1637d335d..c8a4364ad3c2 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -2,7 +2,7 @@
/*
* System Control and Power Interface (SCMI) based CPUFreq Interface driver
*
- * Copyright (C) 2018 ARM Ltd.
+ * Copyright (C) 2018-2021 ARM Ltd.
* Sudeep Holla <[email protected]>
*/

@@ -25,17 +25,17 @@ struct scmi_data {
struct device *cpu_dev;
};

-static const struct scmi_handle *handle;
+static struct scmi_protocol_handle *ph;
+static const struct scmi_perf_proto_ops *perf_ops;

static unsigned int scmi_cpufreq_get_rate(unsigned int cpu)
{
struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
- const struct scmi_perf_ops *perf_ops = handle->perf_ops;
struct scmi_data *priv = policy->driver_data;
unsigned long rate;
int ret;

- ret = perf_ops->freq_get(handle, priv->domain_id, &rate, false);
+ ret = perf_ops->freq_get(ph, priv->domain_id, &rate, false);
if (ret)
return 0;
return rate / 1000;
@@ -50,19 +50,17 @@ static int
scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
{
struct scmi_data *priv = policy->driver_data;
- const struct scmi_perf_ops *perf_ops = handle->perf_ops;
u64 freq = policy->freq_table[index].frequency;

- return perf_ops->freq_set(handle, priv->domain_id, freq * 1000, false);
+ return perf_ops->freq_set(ph, priv->domain_id, freq * 1000, false);
}

static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy,
unsigned int target_freq)
{
struct scmi_data *priv = policy->driver_data;
- const struct scmi_perf_ops *perf_ops = handle->perf_ops;

- if (!perf_ops->freq_set(handle, priv->domain_id,
+ if (!perf_ops->freq_set(ph, priv->domain_id,
target_freq * 1000, true))
return target_freq;

@@ -75,7 +73,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
int cpu, domain, tdomain;
struct device *tcpu_dev;

- domain = handle->perf_ops->device_domain_id(cpu_dev);
+ domain = perf_ops->device_domain_id(cpu_dev);
if (domain < 0)
return domain;

@@ -87,7 +85,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
if (!tcpu_dev)
continue;

- tdomain = handle->perf_ops->device_domain_id(tcpu_dev);
+ tdomain = perf_ops->device_domain_id(tcpu_dev);
if (tdomain == domain)
cpumask_set_cpu(cpu, cpumask);
}
@@ -102,13 +100,13 @@ scmi_get_cpu_power(unsigned long *power, unsigned long *KHz,
unsigned long Hz;
int ret, domain;

- domain = handle->perf_ops->device_domain_id(cpu_dev);
+ domain = perf_ops->device_domain_id(cpu_dev);
if (domain < 0)
return domain;

/* Get the power cost of the performance domain. */
Hz = *KHz * 1000;
- ret = handle->perf_ops->est_power_get(handle, domain, &Hz, power);
+ ret = perf_ops->est_power_get(ph, domain, &Hz, power);
if (ret)
return ret;

@@ -167,7 +165,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
*/
nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
if (nr_opp <= 0) {
- ret = handle->perf_ops->device_opps_add(handle, cpu_dev);
+ ret = perf_ops->device_opps_add(ph, cpu_dev);
if (ret) {
dev_warn(cpu_dev, "failed to add opps to the device\n");
goto out_free_cpumask;
@@ -190,7 +188,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
goto out_free_opp;
}

- power_scale_mw = handle->perf_ops->power_scale_mw_get(handle);
+ power_scale_mw = perf_ops->power_scale_mw_get(ph);
em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb,
opp_shared_cpus, power_scale_mw);
}
@@ -208,7 +206,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
}

priv->cpu_dev = cpu_dev;
- priv->domain_id = handle->perf_ops->device_domain_id(cpu_dev);
+ priv->domain_id = perf_ops->device_domain_id(cpu_dev);

policy->driver_data = priv;
policy->freq_table = freq_table;
@@ -216,14 +214,14 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
/* SCMI allows DVFS request for any domain from any CPU */
policy->dvfs_possible_from_any_cpu = true;

- latency = handle->perf_ops->transition_latency_get(handle, cpu_dev);
+ latency = perf_ops->transition_latency_get(ph, cpu_dev);
if (!latency)
latency = CPUFREQ_ETERNAL;

policy->cpuinfo.transition_latency = latency;

policy->fast_switch_possible =
- handle->perf_ops->fast_switch_possible(handle, cpu_dev);
+ perf_ops->fast_switch_possible(ph, cpu_dev);

free_cpumask_var(opp_shared_cpus);
return 0;
@@ -269,12 +267,17 @@ static int scmi_cpufreq_probe(struct scmi_device *sdev)
{
int ret;
struct device *dev = &sdev->dev;
+ const struct scmi_handle *handle;

handle = sdev->handle;

- if (!handle || !handle->perf_ops)
+ if (!handle)
return -ENODEV;

+ perf_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_PERF, &ph);
+ if (IS_ERR(perf_ops))
+ return PTR_ERR(perf_ops);
+
#ifdef CONFIG_COMMON_CLK
/* dummy clock provider as needed by OPP if clocks property is used */
if (of_find_property(dev->of_node, "#clock-cells", NULL))
--
2.17.1

2021-03-16 19:53:25

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 14/38] firmware: arm_scmi: port Power protocol to new protocols interface

Convert internals of protocol implementation to use protocol handles and
expose a new protocol operations interface for SCMI driver using the new
get/put common operations, while keeping the old handle->power_ops still
around to ease transition.

Remove handle->power_priv now unused.

Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/firmware/arm_scmi/power.c | 141 +++++++++++++++++++-----------
include/linux/scmi_protocol.h | 20 +++--
2 files changed, 105 insertions(+), 56 deletions(-)

diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index 5f43c45ebc13..c950c1fc0fbe 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -68,21 +68,21 @@ struct scmi_power_info {
struct power_dom_info *dom_info;
};

-static int scmi_power_attributes_get(const struct scmi_handle *handle,
+static int scmi_power_attributes_get(const struct scmi_protocol_handle *ph,
struct scmi_power_info *pi)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_resp_power_attributes *attr;

- ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
- SCMI_PROTOCOL_POWER, 0, sizeof(*attr), &t);
+ ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
+ 0, sizeof(*attr), &t);
if (ret)
return ret;

attr = t->rx.buf;

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
pi->num_domains = le16_to_cpu(attr->num_domains);
pi->stats_addr = le32_to_cpu(attr->stats_addr_low) |
@@ -90,28 +90,27 @@ static int scmi_power_attributes_get(const struct scmi_handle *handle,
pi->stats_size = le32_to_cpu(attr->stats_size);
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

static int
-scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
- struct power_dom_info *dom_info)
+scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
+ u32 domain, struct power_dom_info *dom_info)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_resp_power_domain_attributes *attr;

- ret = scmi_xfer_get_init(handle, POWER_DOMAIN_ATTRIBUTES,
- SCMI_PROTOCOL_POWER, sizeof(domain),
- sizeof(*attr), &t);
+ ret = ph->xops->xfer_get_init(ph, POWER_DOMAIN_ATTRIBUTES,
+ sizeof(domain), sizeof(*attr), &t);
if (ret)
return ret;

put_unaligned_le32(domain, t->tx.buf);
attr = t->rx.buf;

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
u32 flags = le32_to_cpu(attr->flags);

@@ -121,19 +120,18 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int
-scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state)
+static int scmi_power_state_set(const struct scmi_protocol_handle *ph,
+ u32 domain, u32 state)
{
int ret;
struct scmi_xfer *t;
struct scmi_power_set_state *st;

- ret = scmi_xfer_get_init(handle, POWER_STATE_SET, SCMI_PROTOCOL_POWER,
- sizeof(*st), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, POWER_STATE_SET, sizeof(*st), 0, &t);
if (ret)
return ret;

@@ -142,64 +140,106 @@ scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state)
st->domain = cpu_to_le32(domain);
st->state = cpu_to_le32(state);

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int
-scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state)
+static int __scmi_power_state_set(const struct scmi_handle *handle,
+ u32 domain, u32 state)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_POWER);
+
+ return scmi_power_state_set(ph, domain, state);
+}
+
+static int scmi_power_state_get(const struct scmi_protocol_handle *ph,
+ u32 domain, u32 *state)
{
int ret;
struct scmi_xfer *t;

- ret = scmi_xfer_get_init(handle, POWER_STATE_GET, SCMI_PROTOCOL_POWER,
- sizeof(u32), sizeof(u32), &t);
+ ret = ph->xops->xfer_get_init(ph, POWER_STATE_GET, sizeof(u32), sizeof(u32), &t);
if (ret)
return ret;

put_unaligned_le32(domain, t->tx.buf);

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret)
*state = get_unaligned_le32(t->rx.buf);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int scmi_power_num_domains_get(const struct scmi_handle *handle)
+static int __scmi_power_state_get(const struct scmi_handle *handle,
+ u32 domain, u32 *state)
{
- struct scmi_power_info *pi = handle->power_priv;
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_POWER);
+
+ return scmi_power_state_get(ph, domain, state);
+}
+
+static int scmi_power_num_domains_get(const struct scmi_protocol_handle *ph)
+{
+ struct scmi_power_info *pi = ph->get_priv(ph);

return pi->num_domains;
}

-static char *scmi_power_name_get(const struct scmi_handle *handle, u32 domain)
+static int __scmi_power_num_domains_get(const struct scmi_handle *handle)
{
- struct scmi_power_info *pi = handle->power_priv;
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_POWER);
+
+ return scmi_power_num_domains_get(ph);
+}
+
+static char *scmi_power_name_get(const struct scmi_protocol_handle *ph,
+ u32 domain)
+{
+ struct scmi_power_info *pi = ph->get_priv(ph);
struct power_dom_info *dom = pi->dom_info + domain;

return dom->name;
}

+static char *__scmi_power_name_get(const struct scmi_handle *handle,
+ u32 domain)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_POWER);
+
+ return scmi_power_name_get(ph, domain);
+}
+
static const struct scmi_power_ops power_ops = {
+ .num_domains_get = __scmi_power_num_domains_get,
+ .name_get = __scmi_power_name_get,
+ .state_set = __scmi_power_state_set,
+ .state_get = __scmi_power_state_get,
+};
+
+static const struct scmi_power_proto_ops power_proto_ops = {
.num_domains_get = scmi_power_num_domains_get,
.name_get = scmi_power_name_get,
.state_set = scmi_power_state_set,
.state_get = scmi_power_state_get,
};

-static int scmi_power_request_notify(const struct scmi_handle *handle,
+static int scmi_power_request_notify(const struct scmi_protocol_handle *ph,
u32 domain, bool enable)
{
int ret;
struct scmi_xfer *t;
struct scmi_power_state_notify *notify;

- ret = scmi_xfer_get_init(handle, POWER_STATE_NOTIFY,
- SCMI_PROTOCOL_POWER, sizeof(*notify), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, POWER_STATE_NOTIFY,
+ sizeof(*notify), 0, &t);
if (ret)
return ret;

@@ -207,18 +247,18 @@ static int scmi_power_request_notify(const struct scmi_handle *handle,
notify->domain = cpu_to_le32(domain);
notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0;

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int scmi_power_set_notify_enabled(const void *handle,
+static int scmi_power_set_notify_enabled(const void *ph,
u8 evt_id, u32 src_id, bool enable)
{
int ret;

- ret = scmi_power_request_notify(handle, src_id, enable);
+ ret = scmi_power_request_notify(ph, src_id, enable);
if (ret)
pr_debug("FAIL_ENABLE - evt[%X] dom[%d] - ret:%d\n",
evt_id, src_id, ret);
@@ -226,7 +266,7 @@ static int scmi_power_set_notify_enabled(const void *handle,
return ret;
}

-static void *scmi_power_fill_custom_report(const void *handle,
+static void *scmi_power_fill_custom_report(const void *ph,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
@@ -246,10 +286,10 @@ static void *scmi_power_fill_custom_report(const void *handle,
return r;
}

-static int scmi_power_get_num_sources(const void *handle)
+static int scmi_power_get_num_sources(const void *ph)
{
struct scmi_power_info *pinfo =
- ((const struct scmi_handle *)(handle))->power_priv;
+ ((const struct scmi_protocol_handle *)ph)->get_priv(ph);

if (!pinfo)
return -EINVAL;
@@ -279,24 +319,25 @@ static const struct scmi_protocol_events power_protocol_events = {
.num_events = ARRAY_SIZE(power_events),
};

-static int scmi_power_protocol_init(struct scmi_handle *handle)
+static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
{
int domain;
u32 version;
struct scmi_power_info *pinfo;
+ struct scmi_handle *handle;

- scmi_version_get(handle, SCMI_PROTOCOL_POWER, &version);
+ ph->xops->version_get(ph, &version);

- dev_dbg(handle->dev, "Power Version %d.%d\n",
+ dev_dbg(ph->dev, "Power Version %d.%d\n",
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));

- pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL);
+ pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
if (!pinfo)
return -ENOMEM;

- scmi_power_attributes_get(handle, pinfo);
+ scmi_power_attributes_get(ph, pinfo);

- pinfo->dom_info = devm_kcalloc(handle->dev, pinfo->num_domains,
+ pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
sizeof(*pinfo->dom_info), GFP_KERNEL);
if (!pinfo->dom_info)
return -ENOMEM;
@@ -304,20 +345,22 @@ static int scmi_power_protocol_init(struct scmi_handle *handle)
for (domain = 0; domain < pinfo->num_domains; domain++) {
struct power_dom_info *dom = pinfo->dom_info + domain;

- scmi_power_domain_attributes_get(handle, domain, dom);
+ scmi_power_domain_attributes_get(ph, domain, dom);
}

pinfo->version = version;
+
+ /* Transient code for legacy ops interface */
+ handle = scmi_map_scmi_handle(ph);
handle->power_ops = &power_ops;
- handle->power_priv = pinfo;

- return 0;
+ return ph->set_priv(ph, pinfo);
}

static const struct scmi_protocol scmi_power = {
.id = SCMI_PROTOCOL_POWER,
- .init = &scmi_power_protocol_init,
- .ops = &power_ops,
+ .instance_init = &scmi_power_protocol_init,
+ .ops = &power_proto_ops,
.events = &power_protocol_events,
};

diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index c71d7c297125..dfb3d2f5e0d3 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -128,7 +128,7 @@ struct scmi_perf_proto_ops {
};

/**
- * struct scmi_power_ops - represents the various operations provided
+ * struct scmi_power_proto_ops - represents the various operations provided
* by SCMI Power Protocol
*
* @num_domains_get: get the count of power domains provided by SCMI
@@ -136,9 +136,9 @@ struct scmi_perf_proto_ops {
* @state_set: sets the power state of a power domain
* @state_get: gets the power state of a power domain
*/
-struct scmi_power_ops {
- int (*num_domains_get)(const struct scmi_handle *handle);
- char *(*name_get)(const struct scmi_handle *handle, u32 domain);
+struct scmi_power_proto_ops {
+ 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
#define SCMI_POWER_STATE_ID_MASK (BIT(28) - 1)
#define SCMI_POWER_STATE_PARAM(type, id) \
@@ -146,6 +146,15 @@ struct scmi_power_ops {
((id) & SCMI_POWER_STATE_ID_MASK))
#define SCMI_POWER_STATE_GENERIC_ON SCMI_POWER_STATE_PARAM(0, 0)
#define SCMI_POWER_STATE_GENERIC_OFF SCMI_POWER_STATE_PARAM(1, 0)
+ int (*state_set)(const struct scmi_protocol_handle *ph, u32 domain,
+ u32 state);
+ int (*state_get)(const struct scmi_protocol_handle *ph, u32 domain,
+ u32 *state);
+};
+
+struct scmi_power_ops {
+ int (*num_domains_get)(const struct scmi_handle *handle);
+ char *(*name_get)(const struct scmi_handle *handle, u32 domain);
int (*state_set)(const struct scmi_handle *handle, u32 domain,
u32 state);
int (*state_get)(const struct scmi_handle *handle, u32 domain,
@@ -616,8 +625,6 @@ struct scmi_notify_ops {
* @notify_ops: pointer to set of notifications related operations
* @clk_priv: pointer to private data structure specific to clock
* protocol(for internal use only)
- * @power_priv: pointer to private data structure specific to power
- * protocol(for internal use only)
* @sensor_priv: pointer to private data structure specific to sensors
* protocol(for internal use only)
* @reset_priv: pointer to private data structure specific to reset
@@ -644,7 +651,6 @@ struct scmi_handle {
const struct scmi_notify_ops *notify_ops;
/* for protocol internal use */
void *clk_priv;
- void *power_priv;
void *sensor_priv;
void *reset_priv;
void *voltage_priv;
--
2.17.1

2021-03-16 19:53:57

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 16/38] firmware: arm_scmi: remove legacy scmi_power_ops protocol interface

Now that all the SCMI driver users have been migrated to the new interface
remove the legacy interface and all the transient code.

Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/firmware/arm_scmi/power.c | 47 -------------------------------
include/linux/scmi_protocol.h | 11 --------
2 files changed, 58 deletions(-)

diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index c950c1fc0fbe..ecdf49abd981 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -146,15 +146,6 @@ static int scmi_power_state_set(const struct scmi_protocol_handle *ph,
return ret;
}

-static int __scmi_power_state_set(const struct scmi_handle *handle,
- u32 domain, u32 state)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_POWER);
-
- return scmi_power_state_set(ph, domain, state);
-}
-
static int scmi_power_state_get(const struct scmi_protocol_handle *ph,
u32 domain, u32 *state)
{
@@ -175,15 +166,6 @@ static int scmi_power_state_get(const struct scmi_protocol_handle *ph,
return ret;
}

-static int __scmi_power_state_get(const struct scmi_handle *handle,
- u32 domain, u32 *state)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_POWER);
-
- return scmi_power_state_get(ph, domain, state);
-}
-
static int scmi_power_num_domains_get(const struct scmi_protocol_handle *ph)
{
struct scmi_power_info *pi = ph->get_priv(ph);
@@ -191,14 +173,6 @@ static int scmi_power_num_domains_get(const struct scmi_protocol_handle *ph)
return pi->num_domains;
}

-static int __scmi_power_num_domains_get(const struct scmi_handle *handle)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_POWER);
-
- return scmi_power_num_domains_get(ph);
-}
-
static char *scmi_power_name_get(const struct scmi_protocol_handle *ph,
u32 domain)
{
@@ -208,22 +182,6 @@ static char *scmi_power_name_get(const struct scmi_protocol_handle *ph,
return dom->name;
}

-static char *__scmi_power_name_get(const struct scmi_handle *handle,
- u32 domain)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_POWER);
-
- return scmi_power_name_get(ph, domain);
-}
-
-static const struct scmi_power_ops power_ops = {
- .num_domains_get = __scmi_power_num_domains_get,
- .name_get = __scmi_power_name_get,
- .state_set = __scmi_power_state_set,
- .state_get = __scmi_power_state_get,
-};
-
static const struct scmi_power_proto_ops power_proto_ops = {
.num_domains_get = scmi_power_num_domains_get,
.name_get = scmi_power_name_get,
@@ -324,7 +282,6 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)
int domain;
u32 version;
struct scmi_power_info *pinfo;
- struct scmi_handle *handle;

ph->xops->version_get(ph, &version);

@@ -350,10 +307,6 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)

pinfo->version = version;

- /* Transient code for legacy ops interface */
- handle = scmi_map_scmi_handle(ph);
- handle->power_ops = &power_ops;
-
return ph->set_priv(ph, pinfo);
}

diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index dfb3d2f5e0d3..2328d36b7597 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -152,15 +152,6 @@ struct scmi_power_proto_ops {
u32 *state);
};

-struct scmi_power_ops {
- int (*num_domains_get)(const struct scmi_handle *handle);
- char *(*name_get)(const struct scmi_handle *handle, u32 domain);
- int (*state_set)(const struct scmi_handle *handle, u32 domain,
- u32 state);
- int (*state_get)(const struct scmi_handle *handle, u32 domain,
- u32 *state);
-};
-
/**
* scmi_sensor_reading - represent a timestamped read
*
@@ -614,7 +605,6 @@ struct scmi_notify_ops {
*
* @dev: pointer to the SCMI device
* @version: pointer to the structure containing SCMI version information
- * @power_ops: pointer to set of power protocol operations
* @clk_ops: pointer to set of clock protocol operations
* @sensor_ops: pointer to set of sensor protocol operations
* @reset_ops: pointer to set of reset protocol operations
@@ -638,7 +628,6 @@ struct scmi_handle {
struct device *dev;
struct scmi_revision_info *version;
const struct scmi_clk_ops *clk_ops;
- const struct scmi_power_ops *power_ops;
const struct scmi_sensor_ops *sensor_ops;
const struct scmi_reset_ops *reset_ops;
const struct scmi_voltage_ops *voltage_ops;
--
2.17.1

2021-03-16 19:55:09

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 19/38] firmware: arm_scmi: remove legacy scmi_clk_ops protocol interface

Now that all the SCMI driver users have been migrated to the new interface
remove the legacy interface and all the transient code.

Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/firmware/arm_scmi/clock.c | 67 -------------------------------
include/linux/scmi_protocol.h | 15 -------
2 files changed, 82 deletions(-)

diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index 1b3b0278b73d..827cf25fc122 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -235,16 +235,6 @@ scmi_clock_rate_get(const struct scmi_protocol_handle *ph,
return ret;
}

-static int
-__scmi_clock_rate_get(const struct scmi_handle *handle,
- u32 clk_id, u64 *value)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_CLOCK);
-
- return scmi_clock_rate_get(ph, clk_id, value);
-}
-
static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph,
u32 clk_id, u64 rate)
{
@@ -280,15 +270,6 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph,
return ret;
}

-static int __scmi_clock_rate_set(const struct scmi_handle *handle,
- u32 clk_id, u64 rate)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_CLOCK);
-
- return scmi_clock_rate_set(ph, clk_id, rate);
-}
-
static int
scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id,
u32 config)
@@ -317,27 +298,11 @@ static int scmi_clock_enable(const struct scmi_protocol_handle *ph, u32 clk_id)
return scmi_clock_config_set(ph, clk_id, CLOCK_ENABLE);
}

-static int __scmi_clock_enable(const struct scmi_handle *handle, u32 clk_id)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_CLOCK);
-
- return scmi_clock_enable(ph, clk_id);
-}
-
static int scmi_clock_disable(const struct scmi_protocol_handle *ph, u32 clk_id)
{
return scmi_clock_config_set(ph, clk_id, 0);
}

-static int __scmi_clock_disable(const struct scmi_handle *handle, u32 clk_id)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_CLOCK);
-
- return scmi_clock_disable(ph, clk_id);
-}
-
static int scmi_clock_count_get(const struct scmi_protocol_handle *ph)
{
struct clock_info *ci = ph->get_priv(ph);
@@ -345,14 +310,6 @@ static int scmi_clock_count_get(const struct scmi_protocol_handle *ph)
return ci->num_clocks;
}

-static int __scmi_clock_count_get(const struct scmi_handle *handle)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_CLOCK);
-
- return scmi_clock_count_get(ph);
-}
-
static const struct scmi_clock_info *
scmi_clock_info_get(const struct scmi_protocol_handle *ph, u32 clk_id)
{
@@ -365,24 +322,6 @@ scmi_clock_info_get(const struct scmi_protocol_handle *ph, u32 clk_id)
return clk;
}

-static const struct scmi_clock_info *
-__scmi_clock_info_get(const struct scmi_handle *handle, u32 clk_id)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_CLOCK);
-
- return scmi_clock_info_get(ph, clk_id);
-}
-
-static const struct scmi_clk_ops clk_ops = {
- .count_get = __scmi_clock_count_get,
- .info_get = __scmi_clock_info_get,
- .rate_get = __scmi_clock_rate_get,
- .rate_set = __scmi_clock_rate_set,
- .enable = __scmi_clock_enable,
- .disable = __scmi_clock_disable,
-};
-
static const struct scmi_clk_proto_ops clk_proto_ops = {
.count_get = scmi_clock_count_get,
.info_get = scmi_clock_info_get,
@@ -397,7 +336,6 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
u32 version;
int clkid, ret;
struct clock_info *cinfo;
- struct scmi_handle *handle;

ph->xops->version_get(ph, &version);

@@ -424,11 +362,6 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
}

cinfo->version = version;
-
- /* Transient code for legacy ops interface */
- handle = scmi_map_scmi_handle(ph);
- handle->clk_ops = &clk_ops;
-
return ph->set_priv(ph, cinfo);
}

diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index b19797b23c5f..e2291b7787f8 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -84,19 +84,6 @@ struct scmi_clk_proto_ops {
int (*disable)(const struct scmi_protocol_handle *ph, u32 clk_id);
};

-struct scmi_clk_ops {
- int (*count_get)(const struct scmi_handle *hamdle);
-
- const struct scmi_clock_info *(*info_get)
- (const struct scmi_handle *handle, u32 clk_id);
- int (*rate_get)(const struct scmi_handle *handle, u32 clk_id,
- u64 *rate);
- int (*rate_set)(const struct scmi_handle *handle, u32 clk_id,
- u64 rate);
- int (*enable)(const struct scmi_handle *handle, u32 clk_id);
- int (*disable)(const struct scmi_handle *handle, u32 clk_id);
-};
-
/**
* struct scmi_perf_proto_ops - represents the various operations provided
* by SCMI Performance Protocol
@@ -618,7 +605,6 @@ struct scmi_notify_ops {
*
* @dev: pointer to the SCMI device
* @version: pointer to the structure containing SCMI version information
- * @clk_ops: pointer to set of clock protocol operations
* @sensor_ops: pointer to set of sensor protocol operations
* @reset_ops: pointer to set of reset protocol operations
* @voltage_ops: pointer to set of voltage protocol operations
@@ -638,7 +624,6 @@ struct scmi_notify_ops {
struct scmi_handle {
struct device *dev;
struct scmi_revision_info *version;
- const struct scmi_clk_ops *clk_ops;
const struct scmi_sensor_ops *sensor_ops;
const struct scmi_reset_ops *reset_ops;
const struct scmi_voltage_ops *voltage_ops;
--
2.17.1

2021-03-16 19:55:16

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 20/38] firmware: arm_scmi: port Reset protocol to new protocols interface

Convert internals of protocol implementation to use protocol handles and
expose a new protocol operations interface for SCMI driver using the new
get/put common operations, while keeping the old handle->reset_ops still
around to ease transition.

Remove handle->reset_priv now unused.

Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/firmware/arm_scmi/reset.c | 172 +++++++++++++++++++++---------
include/linux/scmi_protocol.h | 14 ++-
2 files changed, 129 insertions(+), 57 deletions(-)

diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 572dc1fdcede..26d517745d50 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -64,46 +64,45 @@ struct scmi_reset_info {
struct reset_dom_info *dom_info;
};

-static int scmi_reset_attributes_get(const struct scmi_handle *handle,
+static int scmi_reset_attributes_get(const struct scmi_protocol_handle *ph,
struct scmi_reset_info *pi)
{
int ret;
struct scmi_xfer *t;
u32 attr;

- ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
- SCMI_PROTOCOL_RESET, 0, sizeof(attr), &t);
+ ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
+ 0, sizeof(attr), &t);
if (ret)
return ret;

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
attr = get_unaligned_le32(t->rx.buf);
pi->num_domains = attr & NUM_RESET_DOMAIN_MASK;
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

static int
-scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
- struct reset_dom_info *dom_info)
+scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
+ u32 domain, struct reset_dom_info *dom_info)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_resp_reset_domain_attributes *attr;

- ret = scmi_xfer_get_init(handle, RESET_DOMAIN_ATTRIBUTES,
- SCMI_PROTOCOL_RESET, sizeof(domain),
- sizeof(*attr), &t);
+ ret = ph->xops->xfer_get_init(ph, RESET_DOMAIN_ATTRIBUTES,
+ sizeof(domain), sizeof(*attr), &t);
if (ret)
return ret;

put_unaligned_le32(domain, t->tx.buf);
attr = t->rx.buf;

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
u32 attributes = le32_to_cpu(attr->attributes);

@@ -115,47 +114,75 @@ scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int scmi_reset_num_domains_get(const struct scmi_handle *handle)
+static int scmi_reset_num_domains_get(const struct scmi_protocol_handle *ph)
{
- struct scmi_reset_info *pi = handle->reset_priv;
+ struct scmi_reset_info *pi = ph->get_priv(ph);

return pi->num_domains;
}

-static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain)
+static int __scmi_reset_num_domains_get(const struct scmi_handle *handle)
{
- struct scmi_reset_info *pi = handle->reset_priv;
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
+
+ return scmi_reset_num_domains_get(ph);
+}
+
+static char *scmi_reset_name_get(const struct scmi_protocol_handle *ph,
+ u32 domain)
+{
+ struct scmi_reset_info *pi = ph->get_priv(ph);
+
struct reset_dom_info *dom = pi->dom_info + domain;

return dom->name;
}

-static int scmi_reset_latency_get(const struct scmi_handle *handle, u32 domain)
+static char *__scmi_reset_name_get(const struct scmi_handle *handle,
+ u32 domain)
{
- struct scmi_reset_info *pi = handle->reset_priv;
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
+
+ return scmi_reset_name_get(ph, domain);
+}
+
+static int scmi_reset_latency_get(const struct scmi_protocol_handle *ph,
+ u32 domain)
+{
+ struct scmi_reset_info *pi = ph->get_priv(ph);
struct reset_dom_info *dom = pi->dom_info + domain;

return dom->latency_us;
}

-static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain,
+static int __scmi_reset_latency_get(const struct scmi_handle *handle,
+ u32 domain)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
+
+ return scmi_reset_latency_get(ph, domain);
+}
+
+static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
u32 flags, u32 state)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_reset_domain_reset *dom;
- struct scmi_reset_info *pi = handle->reset_priv;
+ struct scmi_reset_info *pi = ph->get_priv(ph);
struct reset_dom_info *rdom = pi->dom_info + domain;

if (rdom->async_reset)
flags |= ASYNCHRONOUS_RESET;

- ret = scmi_xfer_get_init(handle, RESET, SCMI_PROTOCOL_RESET,
- sizeof(*dom), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, RESET, sizeof(*dom), 0, &t);
if (ret)
return ret;

@@ -165,34 +192,71 @@ static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain,
dom->reset_state = cpu_to_le32(state);

if (rdom->async_reset)
- ret = scmi_do_xfer_with_response(handle, t);
+ ret = ph->xops->do_xfer_with_response(ph, t);
else
- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int scmi_reset_domain_reset(const struct scmi_handle *handle, u32 domain)
+static int scmi_reset_domain_reset(const struct scmi_protocol_handle *ph,
+ u32 domain)
{
- return scmi_domain_reset(handle, domain, AUTONOMOUS_RESET,
+ return scmi_domain_reset(ph, domain, AUTONOMOUS_RESET,
ARCH_COLD_RESET);
}

+static int __scmi_reset_domain_reset(const struct scmi_handle *handle,
+ u32 domain)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
+
+ return scmi_reset_domain_reset(ph, domain);
+}
+
static int
-scmi_reset_domain_assert(const struct scmi_handle *handle, u32 domain)
+scmi_reset_domain_assert(const struct scmi_protocol_handle *ph, u32 domain)
{
- return scmi_domain_reset(handle, domain, EXPLICIT_RESET_ASSERT,
+ return scmi_domain_reset(ph, domain, EXPLICIT_RESET_ASSERT,
ARCH_COLD_RESET);
}

static int
-scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain)
+__scmi_reset_domain_assert(const struct scmi_handle *handle, u32 domain)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
+
+ return scmi_reset_domain_assert(ph, domain);
+}
+
+static int
+scmi_reset_domain_deassert(const struct scmi_protocol_handle *ph, u32 domain)
{
- return scmi_domain_reset(handle, domain, 0, ARCH_COLD_RESET);
+ return scmi_domain_reset(ph, domain, 0, ARCH_COLD_RESET);
+}
+
+static int
+__scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
+
+ return scmi_reset_domain_deassert(ph, domain);
}

static const struct scmi_reset_ops reset_ops = {
+ .num_domains_get = __scmi_reset_num_domains_get,
+ .name_get = __scmi_reset_name_get,
+ .latency_get = __scmi_reset_latency_get,
+ .reset = __scmi_reset_domain_reset,
+ .assert = __scmi_reset_domain_assert,
+ .deassert = __scmi_reset_domain_deassert,
+};
+
+static const struct scmi_reset_proto_ops reset_proto_ops = {
.num_domains_get = scmi_reset_num_domains_get,
.name_get = scmi_reset_name_get,
.latency_get = scmi_reset_latency_get,
@@ -201,16 +265,15 @@ static const struct scmi_reset_ops reset_ops = {
.deassert = scmi_reset_domain_deassert,
};

-static int scmi_reset_notify(const struct scmi_handle *handle, u32 domain_id,
- bool enable)
+static int scmi_reset_notify(const struct scmi_protocol_handle *ph,
+ u32 domain_id, bool enable)
{
int ret;
u32 evt_cntl = enable ? RESET_TP_NOTIFY_ALL : 0;
struct scmi_xfer *t;
struct scmi_msg_reset_notify *cfg;

- ret = scmi_xfer_get_init(handle, RESET_NOTIFY,
- SCMI_PROTOCOL_RESET, sizeof(*cfg), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, RESET_NOTIFY, sizeof(*cfg), 0, &t);
if (ret)
return ret;

@@ -218,18 +281,18 @@ static int scmi_reset_notify(const struct scmi_handle *handle, u32 domain_id,
cfg->id = cpu_to_le32(domain_id);
cfg->event_control = cpu_to_le32(evt_cntl);

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int scmi_reset_set_notify_enabled(const void *handle,
+static int scmi_reset_set_notify_enabled(const void *ph,
u8 evt_id, u32 src_id, bool enable)
{
int ret;

- ret = scmi_reset_notify(handle, src_id, enable);
+ ret = scmi_reset_notify(ph, src_id, enable);
if (ret)
pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
evt_id, src_id, ret);
@@ -237,7 +300,7 @@ static int scmi_reset_set_notify_enabled(const void *handle,
return ret;
}

-static void *scmi_reset_fill_custom_report(const void *handle,
+static void *scmi_reset_fill_custom_report(const void *ph,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
@@ -257,10 +320,10 @@ static void *scmi_reset_fill_custom_report(const void *handle,
return r;
}

-static int scmi_reset_get_num_sources(const void *handle)
+static int scmi_reset_get_num_sources(const void *ph)
{
struct scmi_reset_info *pinfo =
- ((const struct scmi_handle *)(handle))->reset_priv;
+ ((const struct scmi_protocol_handle *)ph)->get_priv(ph);

if (!pinfo)
return -EINVAL;
@@ -289,24 +352,25 @@ static const struct scmi_protocol_events reset_protocol_events = {
.num_events = ARRAY_SIZE(reset_events),
};

-static int scmi_reset_protocol_init(struct scmi_handle *handle)
+static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
{
int domain;
u32 version;
struct scmi_reset_info *pinfo;
+ struct scmi_handle *handle;

- scmi_version_get(handle, SCMI_PROTOCOL_RESET, &version);
+ ph->xops->version_get(ph, &version);

- dev_dbg(handle->dev, "Reset Version %d.%d\n",
+ dev_dbg(ph->dev, "Reset Version %d.%d\n",
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));

- pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL);
+ pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
if (!pinfo)
return -ENOMEM;

- scmi_reset_attributes_get(handle, pinfo);
+ scmi_reset_attributes_get(ph, pinfo);

- pinfo->dom_info = devm_kcalloc(handle->dev, pinfo->num_domains,
+ pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
sizeof(*pinfo->dom_info), GFP_KERNEL);
if (!pinfo->dom_info)
return -ENOMEM;
@@ -314,20 +378,22 @@ static int scmi_reset_protocol_init(struct scmi_handle *handle)
for (domain = 0; domain < pinfo->num_domains; domain++) {
struct reset_dom_info *dom = pinfo->dom_info + domain;

- scmi_reset_domain_attributes_get(handle, domain, dom);
+ scmi_reset_domain_attributes_get(ph, domain, dom);
}

pinfo->version = version;
+
+ /* Transient code for legacy ops interface */
+ handle = scmi_map_scmi_handle(ph);
handle->reset_ops = &reset_ops;
- handle->reset_priv = pinfo;

- return 0;
+ return ph->set_priv(ph, pinfo);
}

static const struct scmi_protocol scmi_reset = {
.id = SCMI_PROTOCOL_RESET,
- .init = &scmi_reset_protocol_init,
- .ops = &reset_ops,
+ .instance_init = &scmi_reset_protocol_init,
+ .ops = &reset_proto_ops,
.events = &reset_protocol_events,
};

diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index e2291b7787f8..234b03a3f038 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -464,7 +464,7 @@ struct scmi_sensor_ops {
};

/**
- * struct scmi_reset_ops - represents the various operations provided
+ * struct scmi_reset_proto_ops - represents the various operations provided
* by SCMI Reset Protocol
*
* @num_domains_get: get the count of reset domains provided by SCMI
@@ -474,6 +474,15 @@ struct scmi_sensor_ops {
* @assert: explicitly assert reset signal of the specified reset domain
* @deassert: explicitly deassert reset signal of the specified reset domain
*/
+struct scmi_reset_proto_ops {
+ 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);
+ int (*reset)(const struct scmi_protocol_handle *ph, u32 domain);
+ int (*assert)(const struct scmi_protocol_handle *ph, u32 domain);
+ int (*deassert)(const struct scmi_protocol_handle *ph, u32 domain);
+};
+
struct scmi_reset_ops {
int (*num_domains_get)(const struct scmi_handle *handle);
char *(*name_get)(const struct scmi_handle *handle, u32 domain);
@@ -614,8 +623,6 @@ struct scmi_notify_ops {
* @notify_ops: pointer to set of notifications related operations
* @sensor_priv: pointer to private data structure specific to sensors
* protocol(for internal use only)
- * @reset_priv: pointer to private data structure specific to reset
- * protocol(for internal use only)
* @voltage_priv: pointer to private data structure specific to voltage
* protocol(for internal use only)
* @notify_priv: pointer to private data structure specific to notifications
@@ -636,7 +643,6 @@ struct scmi_handle {
const struct scmi_notify_ops *notify_ops;
/* for protocol internal use */
void *sensor_priv;
- void *reset_priv;
void *voltage_priv;
void *notify_priv;
void *system_priv;
--
2.17.1

2021-03-16 19:58:18

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 21/38] reset: reset-scmi: port driver to the new scmi_reset_proto_ops interface

Port driver to the new SCMI Reset interface based on protocol handles
and common devm_get_ops().

Cc: Philipp Zabel <[email protected]>
Acked-by: Philipp Zabel <[email protected]>
Signed-off-by: Cristian Marussi <[email protected]>
---
v6 -> v7
- fixed Copyright
- renamed non-static function to fit scmi_<OBJ>_<ACTION> naming pattern
v4 --> v5
- using renamed devm_get/put_protocol
---
drivers/reset/reset-scmi.c | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
index 8d3a858e3b19..4335811e0cfa 100644
--- a/drivers/reset/reset-scmi.c
+++ b/drivers/reset/reset-scmi.c
@@ -2,7 +2,7 @@
/*
* ARM System Control and Management Interface (ARM SCMI) reset driver
*
- * Copyright (C) 2019 ARM Ltd.
+ * Copyright (C) 2019-2021 ARM Ltd.
*/

#include <linux/module.h>
@@ -11,18 +11,20 @@
#include <linux/reset-controller.h>
#include <linux/scmi_protocol.h>

+static const struct scmi_reset_proto_ops *reset_ops;
+
/**
* struct scmi_reset_data - reset controller information structure
* @rcdev: reset controller entity
- * @handle: ARM SCMI handle used for communication with system controller
+ * @ph: ARM SCMI protocol handle used for communication with system controller
*/
struct scmi_reset_data {
struct reset_controller_dev rcdev;
- const struct scmi_handle *handle;
+ const struct scmi_protocol_handle *ph;
};

#define to_scmi_reset_data(p) container_of((p), struct scmi_reset_data, rcdev)
-#define to_scmi_handle(p) (to_scmi_reset_data(p)->handle)
+#define to_scmi_handle(p) (to_scmi_reset_data(p)->ph)

/**
* scmi_reset_assert() - assert device reset
@@ -37,9 +39,9 @@ struct scmi_reset_data {
static int
scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
- const struct scmi_handle *handle = to_scmi_handle(rcdev);
+ const struct scmi_protocol_handle *ph = to_scmi_handle(rcdev);

- return handle->reset_ops->assert(handle, id);
+ return reset_ops->assert(ph, id);
}

/**
@@ -55,9 +57,9 @@ scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
static int
scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
{
- const struct scmi_handle *handle = to_scmi_handle(rcdev);
+ const struct scmi_protocol_handle *ph = to_scmi_handle(rcdev);

- return handle->reset_ops->deassert(handle, id);
+ return reset_ops->deassert(ph, id);
}

/**
@@ -73,9 +75,9 @@ scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
static int
scmi_reset_reset(struct reset_controller_dev *rcdev, unsigned long id)
{
- const struct scmi_handle *handle = to_scmi_handle(rcdev);
+ const struct scmi_protocol_handle *ph = to_scmi_handle(rcdev);

- return handle->reset_ops->reset(handle, id);
+ return reset_ops->reset(ph, id);
}

static const struct reset_control_ops scmi_reset_ops = {
@@ -90,10 +92,15 @@ static int scmi_reset_probe(struct scmi_device *sdev)
struct device *dev = &sdev->dev;
struct device_node *np = dev->of_node;
const struct scmi_handle *handle = sdev->handle;
+ struct scmi_protocol_handle *ph;

- if (!handle || !handle->reset_ops)
+ if (!handle)
return -ENODEV;

+ reset_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_RESET, &ph);
+ if (IS_ERR(reset_ops))
+ return PTR_ERR(reset_ops);
+
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -101,8 +108,8 @@ static int scmi_reset_probe(struct scmi_device *sdev)
data->rcdev.ops = &scmi_reset_ops;
data->rcdev.owner = THIS_MODULE;
data->rcdev.of_node = np;
- data->rcdev.nr_resets = handle->reset_ops->num_domains_get(handle);
- data->handle = handle;
+ data->rcdev.nr_resets = reset_ops->num_domains_get(ph);
+ data->ph = ph;

return devm_reset_controller_register(dev, &data->rcdev);
}
--
2.17.1

2021-03-16 19:59:46

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 23/38] firmware: arm_scmi: port Sensor protocol to new protocols interface

Convert internals of protocol implementation to use protocol handles and
expose a new protocol operations interface for SCMI driver using the new
get/put common operations, while keeping the old handle->sensor_ops still
around to ease transition.

Remove handle->sensor_priv now unused.

Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/firmware/arm_scmi/sensors.c | 275 ++++++++++++++++++----------
include/linux/scmi_protocol.h | 22 ++-
2 files changed, 194 insertions(+), 103 deletions(-)

diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index e40e49869a5d..ae9f727730c8 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -201,21 +201,21 @@ struct sensors_info {
struct scmi_sensor_info *sensors;
};

-static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
+static int scmi_sensor_attributes_get(const struct scmi_protocol_handle *ph,
struct sensors_info *si)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_resp_sensor_attributes *attr;

- ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
- SCMI_PROTOCOL_SENSOR, 0, sizeof(*attr), &t);
+ ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
+ 0, sizeof(*attr), &t);
if (ret)
return ret;

attr = t->rx.buf;

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
si->num_sensors = le16_to_cpu(attr->num_sensors);
si->max_requests = attr->max_requests;
@@ -224,7 +224,7 @@ static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
si->reg_size = le32_to_cpu(attr->reg_size);
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

@@ -235,7 +235,7 @@ static inline void scmi_parse_range_attrs(struct scmi_range_attrs *out,
out->max_range = get_unaligned_le64((void *)&in->max_range_low);
}

-static int scmi_sensor_update_intervals(const struct scmi_handle *handle,
+static int scmi_sensor_update_intervals(const struct scmi_protocol_handle *ph,
struct scmi_sensor_info *s)
{
int ret, cnt;
@@ -245,8 +245,8 @@ static int scmi_sensor_update_intervals(const struct scmi_handle *handle,
struct scmi_msg_resp_sensor_list_update_intervals *buf;
struct scmi_msg_sensor_list_update_intervals *msg;

- ret = scmi_xfer_get_init(handle, SENSOR_LIST_UPDATE_INTERVALS,
- SCMI_PROTOCOL_SENSOR, sizeof(*msg), 0, &ti);
+ ret = ph->xops->xfer_get_init(ph, SENSOR_LIST_UPDATE_INTERVALS,
+ sizeof(*msg), 0, &ti);
if (ret)
return ret;

@@ -259,7 +259,7 @@ static int scmi_sensor_update_intervals(const struct scmi_handle *handle,
msg->id = cpu_to_le32(s->id);
msg->index = cpu_to_le32(desc_index);

- ret = scmi_do_xfer(handle, ti);
+ ret = ph->xops->do_xfer(ph, ti);
if (ret)
break;

@@ -277,7 +277,7 @@ static int scmi_sensor_update_intervals(const struct scmi_handle *handle,
/* segmented intervals are reported in one triplet */
if (s->intervals.segmented &&
(num_remaining || num_returned != 3)) {
- dev_err(handle->dev,
+ dev_err(ph->dev,
"Sensor ID:%d advertises an invalid segmented interval (%d)\n",
s->id, s->intervals.count);
s->intervals.segmented = false;
@@ -288,7 +288,7 @@ static int scmi_sensor_update_intervals(const struct scmi_handle *handle,
/* Direct allocation when exceeding pre-allocated */
if (s->intervals.count >= SCMI_MAX_PREALLOC_POOL) {
s->intervals.desc =
- devm_kcalloc(handle->dev,
+ devm_kcalloc(ph->dev,
s->intervals.count,
sizeof(*s->intervals.desc),
GFP_KERNEL);
@@ -300,7 +300,7 @@ static int scmi_sensor_update_intervals(const struct scmi_handle *handle,
}
}
} else if (desc_index + num_returned > s->intervals.count) {
- dev_err(handle->dev,
+ dev_err(ph->dev,
"No. of update intervals can't exceed %d\n",
s->intervals.count);
ret = -EINVAL;
@@ -313,18 +313,18 @@ static int scmi_sensor_update_intervals(const struct scmi_handle *handle,

desc_index += num_returned;

- scmi_reset_rx_to_maxsz(handle, ti);
+ ph->xops->reset_rx_to_maxsz(ph, ti);
/*
* check for both returned and remaining to avoid infinite
* loop due to buggy firmware
*/
} while (num_returned && num_remaining);

- scmi_xfer_put(handle, ti);
+ ph->xops->xfer_put(ph, ti);
return ret;
}

-static int scmi_sensor_axis_description(const struct scmi_handle *handle,
+static int scmi_sensor_axis_description(const struct scmi_protocol_handle *ph,
struct scmi_sensor_info *s)
{
int ret, cnt;
@@ -334,13 +334,13 @@ static int scmi_sensor_axis_description(const struct scmi_handle *handle,
struct scmi_msg_resp_sensor_axis_description *buf;
struct scmi_msg_sensor_axis_description_get *msg;

- s->axis = devm_kcalloc(handle->dev, s->num_axis,
+ s->axis = devm_kcalloc(ph->dev, s->num_axis,
sizeof(*s->axis), GFP_KERNEL);
if (!s->axis)
return -ENOMEM;

- ret = scmi_xfer_get_init(handle, SENSOR_AXIS_DESCRIPTION_GET,
- SCMI_PROTOCOL_SENSOR, sizeof(*msg), 0, &te);
+ ret = ph->xops->xfer_get_init(ph, SENSOR_AXIS_DESCRIPTION_GET,
+ sizeof(*msg), 0, &te);
if (ret)
return ret;

@@ -354,7 +354,7 @@ static int scmi_sensor_axis_description(const struct scmi_handle *handle,
msg->id = cpu_to_le32(s->id);
msg->axis_desc_index = cpu_to_le32(desc_index);

- ret = scmi_do_xfer(handle, te);
+ ret = ph->xops->do_xfer(ph, te);
if (ret)
break;

@@ -363,7 +363,7 @@ static int scmi_sensor_axis_description(const struct scmi_handle *handle,
num_remaining = NUM_AXIS_REMAINING(flags);

if (desc_index + num_returned > s->num_axis) {
- dev_err(handle->dev, "No. of axis can't exceed %d\n",
+ dev_err(ph->dev, "No. of axis can't exceed %d\n",
s->num_axis);
break;
}
@@ -405,18 +405,18 @@ static int scmi_sensor_axis_description(const struct scmi_handle *handle,

desc_index += num_returned;

- scmi_reset_rx_to_maxsz(handle, te);
+ ph->xops->reset_rx_to_maxsz(ph, te);
/*
* check for both returned and remaining to avoid infinite
* loop due to buggy firmware
*/
} while (num_returned && num_remaining);

- scmi_xfer_put(handle, te);
+ ph->xops->xfer_put(ph, te);
return ret;
}

-static int scmi_sensor_description_get(const struct scmi_handle *handle,
+static int scmi_sensor_description_get(const struct scmi_protocol_handle *ph,
struct sensors_info *si)
{
int ret, cnt;
@@ -425,8 +425,8 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
struct scmi_xfer *t;
struct scmi_msg_resp_sensor_description *buf;

- ret = scmi_xfer_get_init(handle, SENSOR_DESCRIPTION_GET,
- SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, SENSOR_DESCRIPTION_GET,
+ sizeof(__le32), 0, &t);
if (ret)
return ret;

@@ -437,7 +437,8 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,

/* Set the number of sensors to be skipped/already read */
put_unaligned_le32(desc_index, t->tx.buf);
- ret = scmi_do_xfer(handle, t);
+
+ ret = ph->xops->do_xfer(ph, t);
if (ret)
break;

@@ -445,7 +446,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
num_remaining = le16_to_cpu(buf->num_remaining);

if (desc_index + num_returned > si->num_sensors) {
- dev_err(handle->dev, "No. of sensors can't exceed %d",
+ dev_err(ph->dev, "No. of sensors can't exceed %d",
si->num_sensors);
break;
}
@@ -500,8 +501,8 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
* Since the command is optional, on error carry
* on without any update interval.
*/
- if (scmi_sensor_update_intervals(handle, s))
- dev_dbg(handle->dev,
+ if (scmi_sensor_update_intervals(ph, s))
+ dev_dbg(ph->dev,
"Update Intervals not available for sensor ID:%d\n",
s->id);
}
@@ -535,7 +536,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
}
}
if (s->num_axis > 0) {
- ret = scmi_sensor_axis_description(handle, s);
+ ret = scmi_sensor_axis_description(ph, s);
if (ret)
goto out;
}
@@ -545,7 +546,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,

desc_index += num_returned;

- scmi_reset_rx_to_maxsz(handle, t);
+ ph->xops->reset_rx_to_maxsz(ph, t);
/*
* check for both returned and remaining to avoid infinite
* loop due to buggy firmware
@@ -553,12 +554,12 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
} while (num_returned && num_remaining);

out:
- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

static inline int
-scmi_sensor_request_notify(const struct scmi_handle *handle, u32 sensor_id,
+scmi_sensor_request_notify(const struct scmi_protocol_handle *ph, u32 sensor_id,
u8 message_id, bool enable)
{
int ret;
@@ -566,8 +567,7 @@ scmi_sensor_request_notify(const struct scmi_handle *handle, u32 sensor_id,
struct scmi_xfer *t;
struct scmi_msg_sensor_request_notify *cfg;

- ret = scmi_xfer_get_init(handle, message_id,
- SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, message_id, sizeof(*cfg), 0, &t);
if (ret)
return ret;

@@ -575,40 +575,40 @@ scmi_sensor_request_notify(const struct scmi_handle *handle, u32 sensor_id,
cfg->id = cpu_to_le32(sensor_id);
cfg->event_control = cpu_to_le32(evt_cntl);

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle,
+static int scmi_sensor_trip_point_notify(const struct scmi_protocol_handle *ph,
u32 sensor_id, bool enable)
{
- return scmi_sensor_request_notify(handle, sensor_id,
+ return scmi_sensor_request_notify(ph, sensor_id,
SENSOR_TRIP_POINT_NOTIFY,
enable);
}

static int
-scmi_sensor_continuous_update_notify(const struct scmi_handle *handle,
+scmi_sensor_continuous_update_notify(const struct scmi_protocol_handle *ph,
u32 sensor_id, bool enable)
{
- return scmi_sensor_request_notify(handle, sensor_id,
+ return scmi_sensor_request_notify(ph, sensor_id,
SENSOR_CONTINUOUS_UPDATE_NOTIFY,
enable);
}

static int
-scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id,
- u8 trip_id, u64 trip_value)
+scmi_sensor_trip_point_config(const struct scmi_protocol_handle *ph,
+ u32 sensor_id, u8 trip_id, u64 trip_value)
{
int ret;
u32 evt_cntl = SENSOR_TP_BOTH;
struct scmi_xfer *t;
struct scmi_msg_set_sensor_trip_point *trip;

- ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_CONFIG,
- SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, SENSOR_TRIP_POINT_CONFIG,
+ sizeof(*trip), 0, &t);
if (ret)
return ret;

@@ -618,47 +618,66 @@ scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id,
trip->value_low = cpu_to_le32(trip_value & 0xffffffff);
trip->value_high = cpu_to_le32(trip_value >> 32);

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int scmi_sensor_config_get(const struct scmi_handle *handle,
+static int
+__scmi_sensor_trip_point_config(const struct scmi_handle *handle,
+ u32 sensor_id, u8 trip_id, u64 trip_value)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
+
+ return scmi_sensor_trip_point_config(ph, sensor_id, trip_id,
+ trip_value);
+}
+
+static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph,
u32 sensor_id, u32 *sensor_config)
{
int ret;
struct scmi_xfer *t;

- ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_GET,
- SCMI_PROTOCOL_SENSOR, sizeof(__le32),
- sizeof(__le32), &t);
+ ret = ph->xops->xfer_get_init(ph, SENSOR_CONFIG_GET,
+ sizeof(__le32), sizeof(__le32), &t);
if (ret)
return ret;

put_unaligned_le32(cpu_to_le32(sensor_id), t->tx.buf);
- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
- struct sensors_info *si = handle->sensor_priv;
+ struct sensors_info *si = ph->get_priv(ph);
struct scmi_sensor_info *s = si->sensors + sensor_id;

*sensor_config = get_unaligned_le64(t->rx.buf);
s->sensor_config = *sensor_config;
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

-static int scmi_sensor_config_set(const struct scmi_handle *handle,
+static int __scmi_sensor_config_get(const struct scmi_handle *handle,
+ u32 sensor_id, u32 *sensor_config)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
+
+ return scmi_sensor_config_get(ph, sensor_id, sensor_config);
+}
+
+static int scmi_sensor_config_set(const struct scmi_protocol_handle *ph,
u32 sensor_id, u32 sensor_config)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_config_set *msg;

- ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_SET,
- SCMI_PROTOCOL_SENSOR, sizeof(*msg), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, SENSOR_CONFIG_SET,
+ sizeof(*msg), 0, &t);
if (ret)
return ret;

@@ -666,21 +685,30 @@ static int scmi_sensor_config_set(const struct scmi_handle *handle,
msg->id = cpu_to_le32(sensor_id);
msg->sensor_config = cpu_to_le32(sensor_config);

- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
- struct sensors_info *si = handle->sensor_priv;
+ struct sensors_info *si = ph->get_priv(ph);
struct scmi_sensor_info *s = si->sensors + sensor_id;

s->sensor_config = sensor_config;
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

+static int __scmi_sensor_config_set(const struct scmi_handle *handle,
+ u32 sensor_id, u32 sensor_config)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
+
+ return scmi_sensor_config_set(ph, sensor_id, sensor_config);
+}
+
/**
* scmi_sensor_reading_get - Read scalar sensor value
- * @handle: Platform handle
+ * @ph: Protocol handle
* @sensor_id: Sensor ID
* @value: The 64bit value sensor reading
*
@@ -693,17 +721,17 @@ static int scmi_sensor_config_set(const struct scmi_handle *handle,
*
* Return: 0 on Success
*/
-static int scmi_sensor_reading_get(const struct scmi_handle *handle,
+static int scmi_sensor_reading_get(const struct scmi_protocol_handle *ph,
u32 sensor_id, u64 *value)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_reading_get *sensor;
- struct sensors_info *si = handle->sensor_priv;
+ struct sensors_info *si = ph->get_priv(ph);
struct scmi_sensor_info *s = si->sensors + sensor_id;

- ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
- SCMI_PROTOCOL_SENSOR, sizeof(*sensor), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, SENSOR_READING_GET,
+ sizeof(*sensor), 0, &t);
if (ret)
return ret;

@@ -711,7 +739,7 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle,
sensor->id = cpu_to_le32(sensor_id);
if (s->async) {
sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
- ret = scmi_do_xfer_with_response(handle, t);
+ ret = ph->xops->do_xfer_with_response(ph, t);
if (!ret) {
struct scmi_resp_sensor_reading_complete *resp;

@@ -723,15 +751,24 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle,
}
} else {
sensor->flags = cpu_to_le32(0);
- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret)
*value = get_unaligned_le64(t->rx.buf);
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

+static int __scmi_sensor_reading_get(const struct scmi_handle *handle,
+ u32 sensor_id, u64 *value)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
+
+ return scmi_sensor_reading_get(ph, sensor_id, value);
+}
+
static inline void
scmi_parse_sensor_readings(struct scmi_sensor_reading *out,
const struct scmi_sensor_reading_resp *in)
@@ -742,7 +779,7 @@ scmi_parse_sensor_readings(struct scmi_sensor_reading *out,

/**
* scmi_sensor_reading_get_timestamped - Read multiple-axis timestamped values
- * @handle: Platform handle
+ * @ph: Protocol handle
* @sensor_id: Sensor ID
* @count: The length of the provided @readings array
* @readings: An array of elements each representing a timestamped per-axis
@@ -755,22 +792,22 @@ scmi_parse_sensor_readings(struct scmi_sensor_reading *out,
* Return: 0 on Success
*/
static int
-scmi_sensor_reading_get_timestamped(const struct scmi_handle *handle,
+scmi_sensor_reading_get_timestamped(const struct scmi_protocol_handle *ph,
u32 sensor_id, u8 count,
struct scmi_sensor_reading *readings)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_reading_get *sensor;
- struct sensors_info *si = handle->sensor_priv;
+ struct sensors_info *si = ph->get_priv(ph);
struct scmi_sensor_info *s = si->sensors + sensor_id;

if (!count || !readings ||
(!s->num_axis && count > 1) || (s->num_axis && count > s->num_axis))
return -EINVAL;

- ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
- SCMI_PROTOCOL_SENSOR, sizeof(*sensor), 0, &t);
+ ret = ph->xops->xfer_get_init(ph, SENSOR_READING_GET,
+ sizeof(*sensor), 0, &t);
if (ret)
return ret;

@@ -778,7 +815,7 @@ scmi_sensor_reading_get_timestamped(const struct scmi_handle *handle,
sensor->id = cpu_to_le32(sensor_id);
if (s->async) {
sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
- ret = scmi_do_xfer_with_response(handle, t);
+ ret = ph->xops->do_xfer_with_response(ph, t);
if (!ret) {
int i;
struct scmi_resp_sensor_reading_complete_v3 *resp;
@@ -794,7 +831,7 @@ scmi_sensor_reading_get_timestamped(const struct scmi_handle *handle,
}
} else {
sensor->flags = cpu_to_le32(0);
- ret = scmi_do_xfer(handle, t);
+ ret = ph->xops->do_xfer(ph, t);
if (!ret) {
int i;
struct scmi_sensor_reading_resp *resp_readings;
@@ -806,26 +843,65 @@ scmi_sensor_reading_get_timestamped(const struct scmi_handle *handle,
}
}

- scmi_xfer_put(handle, t);
+ ph->xops->xfer_put(ph, t);
return ret;
}

+static int
+__scmi_sensor_reading_get_timestamped(const struct scmi_handle *handle,
+ u32 sensor_id, u8 count,
+ struct scmi_sensor_reading *readings)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
+
+ return scmi_sensor_reading_get_timestamped(ph, sensor_id, count,
+ readings);
+}
+
static const struct scmi_sensor_info *
-scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id)
+scmi_sensor_info_get(const struct scmi_protocol_handle *ph, u32 sensor_id)
{
- struct sensors_info *si = handle->sensor_priv;
+ struct sensors_info *si = ph->get_priv(ph);

return si->sensors + sensor_id;
}

-static int scmi_sensor_count_get(const struct scmi_handle *handle)
+static const struct scmi_sensor_info *
+__scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id)
{
- struct sensors_info *si = handle->sensor_priv;
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
+
+ return scmi_sensor_info_get(ph, sensor_id);
+}
+
+static int scmi_sensor_count_get(const struct scmi_protocol_handle *ph)
+{
+ struct sensors_info *si = ph->get_priv(ph);

return si->num_sensors;
}

+static int __scmi_sensor_count_get(const struct scmi_handle *handle)
+{
+ const struct scmi_protocol_handle *ph =
+ scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
+
+ return scmi_sensor_count_get(ph);
+}
+
static const struct scmi_sensor_ops sensor_ops = {
+ .count_get = __scmi_sensor_count_get,
+ .info_get = __scmi_sensor_info_get,
+ .trip_point_config = __scmi_sensor_trip_point_config,
+ .reading_get = __scmi_sensor_reading_get,
+ .reading_get_timestamped = __scmi_sensor_reading_get_timestamped,
+ .config_get = __scmi_sensor_config_get,
+ .config_set = __scmi_sensor_config_set,
+};
+
+static const struct scmi_sensor_proto_ops sensor_proto_ops = {
.count_get = scmi_sensor_count_get,
.info_get = scmi_sensor_info_get,
.trip_point_config = scmi_sensor_trip_point_config,
@@ -835,18 +911,17 @@ static const struct scmi_sensor_ops sensor_ops = {
.config_set = scmi_sensor_config_set,
};

-static int scmi_sensor_set_notify_enabled(const void *handle,
+static int scmi_sensor_set_notify_enabled(const void *ph,
u8 evt_id, u32 src_id, bool enable)
{
int ret;

switch (evt_id) {
case SCMI_EVENT_SENSOR_TRIP_POINT_EVENT:
- ret = scmi_sensor_trip_point_notify(handle, src_id, enable);
+ ret = scmi_sensor_trip_point_notify(ph, src_id, enable);
break;
case SCMI_EVENT_SENSOR_UPDATE:
- ret = scmi_sensor_continuous_update_notify(handle, src_id,
- enable);
+ ret = scmi_sensor_continuous_update_notify(ph, src_id, enable);
break;
default:
ret = -EINVAL;
@@ -860,7 +935,7 @@ static int scmi_sensor_set_notify_enabled(const void *handle,
return ret;
}

-static void *scmi_sensor_fill_custom_report(const void *handle,
+static void *scmi_sensor_fill_custom_report(const void *ph,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
@@ -891,7 +966,7 @@ static void *scmi_sensor_fill_custom_report(const void *handle,
const struct scmi_sensor_update_notify_payld *p = payld;
struct scmi_sensor_update_report *r = report;
struct sensors_info *sinfo =
- ((const struct scmi_handle *)(handle))->sensor_priv;
+ ((const struct scmi_protocol_handle *)ph)->get_priv(ph);

/* payld_sz is variable for this event */
r->sensor_id = le32_to_cpu(p->sensor_id);
@@ -921,10 +996,10 @@ static void *scmi_sensor_fill_custom_report(const void *handle,
return rep;
}

-static int scmi_sensor_get_num_sources(const void *handle)
+static int scmi_sensor_get_num_sources(const void *ph)
{
struct sensors_info *si =
- ((const struct scmi_handle *)(handle))->sensor_priv;
+ ((const struct scmi_protocol_handle *)ph)->get_priv(ph);

return si->num_sensors;
}
@@ -960,44 +1035,46 @@ static const struct scmi_protocol_events sensor_protocol_events = {
.num_events = ARRAY_SIZE(sensor_events),
};

-static int scmi_sensors_protocol_init(struct scmi_handle *handle)
+static int scmi_sensors_protocol_init(const struct scmi_protocol_handle *ph)
{
u32 version;
int ret;
struct sensors_info *sinfo;
+ struct scmi_handle *handle;

- scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version);
+ ph->xops->version_get(ph, &version);

- dev_dbg(handle->dev, "Sensor Version %d.%d\n",
+ dev_dbg(ph->dev, "Sensor Version %d.%d\n",
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));

- sinfo = devm_kzalloc(handle->dev, sizeof(*sinfo), GFP_KERNEL);
+ sinfo = devm_kzalloc(ph->dev, sizeof(*sinfo), GFP_KERNEL);
if (!sinfo)
return -ENOMEM;
sinfo->version = version;

- ret = scmi_sensor_attributes_get(handle, sinfo);
+ ret = scmi_sensor_attributes_get(ph, sinfo);
if (ret)
return ret;
- sinfo->sensors = devm_kcalloc(handle->dev, sinfo->num_sensors,
+ sinfo->sensors = devm_kcalloc(ph->dev, sinfo->num_sensors,
sizeof(*sinfo->sensors), GFP_KERNEL);
if (!sinfo->sensors)
return -ENOMEM;

- ret = scmi_sensor_description_get(handle, sinfo);
+ ret = scmi_sensor_description_get(ph, sinfo);
if (ret)
return ret;

- handle->sensor_priv = sinfo;
+ /* Transient code for legacy ops interface */
+ handle = scmi_map_scmi_handle(ph);
handle->sensor_ops = &sensor_ops;

- return 0;
+ return ph->set_priv(ph, sinfo);
}

static const struct scmi_protocol scmi_sensors = {
.id = SCMI_PROTOCOL_SENSOR,
- .init = &scmi_sensors_protocol_init,
- .ops = &sensor_ops,
+ .instance_init = &scmi_sensors_protocol_init,
+ .ops = &sensor_proto_ops,
.events = &sensor_protocol_events,
};

diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index c5bf9dc707aa..ead06db7be18 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -431,7 +431,7 @@ enum scmi_sensor_class {
};

/**
- * struct scmi_sensor_ops - represents the various operations provided
+ * struct scmi_sensor_proto_ops - represents the various operations provided
* by SCMI Sensor Protocol
*
* @count_get: get the count of sensors provided by SCMI
@@ -446,6 +446,23 @@ enum scmi_sensor_class {
* @config_get: Get sensor current configuration
* @config_set: Set sensor current configuration
*/
+struct scmi_sensor_proto_ops {
+ 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);
+ int (*trip_point_config)(const struct scmi_protocol_handle *ph,
+ u32 sensor_id, u8 trip_id, u64 trip_value);
+ int (*reading_get)(const struct scmi_protocol_handle *ph, u32 sensor_id,
+ u64 *value);
+ int (*reading_get_timestamped)(const struct scmi_protocol_handle *ph,
+ u32 sensor_id, u8 count,
+ struct scmi_sensor_reading *readings);
+ int (*config_get)(const struct scmi_protocol_handle *ph,
+ u32 sensor_id, u32 *sensor_config);
+ int (*config_set)(const struct scmi_protocol_handle *ph,
+ u32 sensor_id, u32 sensor_config);
+};
+
struct scmi_sensor_ops {
int (*count_get)(const struct scmi_handle *handle);
const struct scmi_sensor_info *(*info_get)
@@ -611,8 +628,6 @@ struct scmi_notify_ops {
* operations and a dedicated protocol handler
* @devm_protocol_put: devres managed method to release a protocol
* @notify_ops: pointer to set of notifications related operations
- * @sensor_priv: pointer to private data structure specific to sensors
- * protocol(for internal use only)
* @voltage_priv: pointer to private data structure specific to voltage
* protocol(for internal use only)
* @notify_priv: pointer to private data structure specific to notifications
@@ -631,7 +646,6 @@ struct scmi_handle {

const struct scmi_notify_ops *notify_ops;
/* for protocol internal use */
- void *sensor_priv;
void *voltage_priv;
void *notify_priv;
void *system_priv;
--
2.17.1

2021-03-16 20:00:00

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 22/38] firmware: arm_scmi: remove legacy scmi_reset_ops protocol interface

Now that all the SCMI driver users have been migrated to the new interface
remove the legacy interface and all the transient code.

Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/firmware/arm_scmi/reset.c | 68 -------------------------------
include/linux/scmi_protocol.h | 11 -----
2 files changed, 79 deletions(-)

diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 26d517745d50..7ea1286bfed6 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -125,14 +125,6 @@ static int scmi_reset_num_domains_get(const struct scmi_protocol_handle *ph)
return pi->num_domains;
}

-static int __scmi_reset_num_domains_get(const struct scmi_handle *handle)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
-
- return scmi_reset_num_domains_get(ph);
-}
-
static char *scmi_reset_name_get(const struct scmi_protocol_handle *ph,
u32 domain)
{
@@ -143,15 +135,6 @@ static char *scmi_reset_name_get(const struct scmi_protocol_handle *ph,
return dom->name;
}

-static char *__scmi_reset_name_get(const struct scmi_handle *handle,
- u32 domain)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
-
- return scmi_reset_name_get(ph, domain);
-}
-
static int scmi_reset_latency_get(const struct scmi_protocol_handle *ph,
u32 domain)
{
@@ -161,15 +144,6 @@ static int scmi_reset_latency_get(const struct scmi_protocol_handle *ph,
return dom->latency_us;
}

-static int __scmi_reset_latency_get(const struct scmi_handle *handle,
- u32 domain)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
-
- return scmi_reset_latency_get(ph, domain);
-}
-
static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
u32 flags, u32 state)
{
@@ -207,15 +181,6 @@ static int scmi_reset_domain_reset(const struct scmi_protocol_handle *ph,
ARCH_COLD_RESET);
}

-static int __scmi_reset_domain_reset(const struct scmi_handle *handle,
- u32 domain)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
-
- return scmi_reset_domain_reset(ph, domain);
-}
-
static int
scmi_reset_domain_assert(const struct scmi_protocol_handle *ph, u32 domain)
{
@@ -223,39 +188,12 @@ scmi_reset_domain_assert(const struct scmi_protocol_handle *ph, u32 domain)
ARCH_COLD_RESET);
}

-static int
-__scmi_reset_domain_assert(const struct scmi_handle *handle, u32 domain)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
-
- return scmi_reset_domain_assert(ph, domain);
-}
-
static int
scmi_reset_domain_deassert(const struct scmi_protocol_handle *ph, u32 domain)
{
return scmi_domain_reset(ph, domain, 0, ARCH_COLD_RESET);
}

-static int
-__scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_RESET);
-
- return scmi_reset_domain_deassert(ph, domain);
-}
-
-static const struct scmi_reset_ops reset_ops = {
- .num_domains_get = __scmi_reset_num_domains_get,
- .name_get = __scmi_reset_name_get,
- .latency_get = __scmi_reset_latency_get,
- .reset = __scmi_reset_domain_reset,
- .assert = __scmi_reset_domain_assert,
- .deassert = __scmi_reset_domain_deassert,
-};
-
static const struct scmi_reset_proto_ops reset_proto_ops = {
.num_domains_get = scmi_reset_num_domains_get,
.name_get = scmi_reset_name_get,
@@ -357,7 +295,6 @@ static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
int domain;
u32 version;
struct scmi_reset_info *pinfo;
- struct scmi_handle *handle;

ph->xops->version_get(ph, &version);

@@ -382,11 +319,6 @@ static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
}

pinfo->version = version;
-
- /* Transient code for legacy ops interface */
- handle = scmi_map_scmi_handle(ph);
- handle->reset_ops = &reset_ops;
-
return ph->set_priv(ph, pinfo);
}

diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 234b03a3f038..c5bf9dc707aa 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -483,15 +483,6 @@ struct scmi_reset_proto_ops {
int (*deassert)(const struct scmi_protocol_handle *ph, u32 domain);
};

-struct scmi_reset_ops {
- int (*num_domains_get)(const struct scmi_handle *handle);
- char *(*name_get)(const struct scmi_handle *handle, u32 domain);
- int (*latency_get)(const struct scmi_handle *handle, u32 domain);
- int (*reset)(const struct scmi_handle *handle, u32 domain);
- int (*assert)(const struct scmi_handle *handle, u32 domain);
- int (*deassert)(const struct scmi_handle *handle, u32 domain);
-};
-
/**
* struct scmi_voltage_info - describe one available SCMI Voltage Domain
*
@@ -615,7 +606,6 @@ struct scmi_notify_ops {
* @dev: pointer to the SCMI device
* @version: pointer to the structure containing SCMI version information
* @sensor_ops: pointer to set of sensor protocol operations
- * @reset_ops: pointer to set of reset protocol operations
* @voltage_ops: pointer to set of voltage protocol operations
* @devm_protocol_get: devres managed method to acquire a protocol and get specific
* operations and a dedicated protocol handler
@@ -632,7 +622,6 @@ struct scmi_handle {
struct device *dev;
struct scmi_revision_info *version;
const struct scmi_sensor_ops *sensor_ops;
- const struct scmi_reset_ops *reset_ops;
const struct scmi_voltage_ops *voltage_ops;

const void __must_check *
--
2.17.1

2021-03-16 20:00:11

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 24/38] hwmon: (scmi) port driver to the new scmi_sensor_proto_ops interface

Port driver to the new SCMI Sensor interface based on protocol handles
and common devm_get_ops().

Cc: Guenter Roeck <[email protected]>
Cc: Jean Delvare <[email protected]>
Acked-by: Guenter Roeck <[email protected]>
Signed-off-by: Cristian Marussi <[email protected]>
---
v6 -> v7
- fixed Copyright
- renamed non-static function to fit scmi_<OBJ>_<ACTION> naming pattern
v4 --> v5
- using renamed devm_get/put_protocol
---
drivers/hwmon/scmi-hwmon.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
index 17d064e58938..b1329a58ce40 100644
--- a/drivers/hwmon/scmi-hwmon.c
+++ b/drivers/hwmon/scmi-hwmon.c
@@ -2,7 +2,7 @@
/*
* System Control and Management Interface(SCMI) based hwmon sensor driver
*
- * Copyright (C) 2018 ARM Ltd.
+ * Copyright (C) 2018-2021 ARM Ltd.
* Sudeep Holla <[email protected]>
*/

@@ -13,8 +13,10 @@
#include <linux/sysfs.h>
#include <linux/thermal.h>

+static const struct scmi_sensor_proto_ops *sensor_ops;
+
struct scmi_sensors {
- const struct scmi_handle *handle;
+ const struct scmi_protocol_handle *ph;
const struct scmi_sensor_info **info[hwmon_max];
};

@@ -69,10 +71,9 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u64 value;
const struct scmi_sensor_info *sensor;
struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
- const struct scmi_handle *h = scmi_sensors->handle;

sensor = *(scmi_sensors->info[type] + channel);
- ret = h->sensor_ops->reading_get(h, sensor->id, &value);
+ ret = sensor_ops->reading_get(scmi_sensors->ph, sensor->id, &value);
if (ret)
return ret;

@@ -169,11 +170,16 @@ static int scmi_hwmon_probe(struct scmi_device *sdev)
struct hwmon_channel_info *scmi_hwmon_chan;
const struct hwmon_channel_info **ptr_scmi_ci;
const struct scmi_handle *handle = sdev->handle;
+ struct scmi_protocol_handle *ph;

- if (!handle || !handle->sensor_ops)
+ if (!handle)
return -ENODEV;

- nr_sensors = handle->sensor_ops->count_get(handle);
+ sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
+ if (IS_ERR(sensor_ops))
+ return PTR_ERR(sensor_ops);
+
+ nr_sensors = sensor_ops->count_get(ph);
if (!nr_sensors)
return -EIO;

@@ -181,10 +187,10 @@ static int scmi_hwmon_probe(struct scmi_device *sdev)
if (!scmi_sensors)
return -ENOMEM;

- scmi_sensors->handle = handle;
+ scmi_sensors->ph = ph;

for (i = 0; i < nr_sensors; i++) {
- sensor = handle->sensor_ops->info_get(handle, i);
+ sensor = sensor_ops->info_get(ph, i);
if (!sensor)
return -EINVAL;

@@ -236,7 +242,7 @@ static int scmi_hwmon_probe(struct scmi_device *sdev)
}

for (i = nr_sensors - 1; i >= 0 ; i--) {
- sensor = handle->sensor_ops->info_get(handle, i);
+ sensor = sensor_ops->info_get(ph, i);
if (!sensor)
continue;

--
2.17.1

2021-03-16 20:00:32

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 26/38] firmware: arm_scmi: remove legacy scmi_sensor_ops protocol interface

Now that all the SCMI driver users have been migrated to the new interface
remove the legacy interface and all the transient code.

Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/firmware/arm_scmi/sensors.c | 82 -----------------------------
include/linux/scmi_protocol.h | 19 -------
2 files changed, 101 deletions(-)

diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index ae9f727730c8..2f5b06135468 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -624,17 +624,6 @@ scmi_sensor_trip_point_config(const struct scmi_protocol_handle *ph,
return ret;
}

-static int
-__scmi_sensor_trip_point_config(const struct scmi_handle *handle,
- u32 sensor_id, u8 trip_id, u64 trip_value)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
-
- return scmi_sensor_trip_point_config(ph, sensor_id, trip_id,
- trip_value);
-}
-
static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph,
u32 sensor_id, u32 *sensor_config)
{
@@ -660,15 +649,6 @@ static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph,
return ret;
}

-static int __scmi_sensor_config_get(const struct scmi_handle *handle,
- u32 sensor_id, u32 *sensor_config)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
-
- return scmi_sensor_config_get(ph, sensor_id, sensor_config);
-}
-
static int scmi_sensor_config_set(const struct scmi_protocol_handle *ph,
u32 sensor_id, u32 sensor_config)
{
@@ -697,15 +677,6 @@ static int scmi_sensor_config_set(const struct scmi_protocol_handle *ph,
return ret;
}

-static int __scmi_sensor_config_set(const struct scmi_handle *handle,
- u32 sensor_id, u32 sensor_config)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
-
- return scmi_sensor_config_set(ph, sensor_id, sensor_config);
-}
-
/**
* scmi_sensor_reading_get - Read scalar sensor value
* @ph: Protocol handle
@@ -760,15 +731,6 @@ static int scmi_sensor_reading_get(const struct scmi_protocol_handle *ph,
return ret;
}

-static int __scmi_sensor_reading_get(const struct scmi_handle *handle,
- u32 sensor_id, u64 *value)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
-
- return scmi_sensor_reading_get(ph, sensor_id, value);
-}
-
static inline void
scmi_parse_sensor_readings(struct scmi_sensor_reading *out,
const struct scmi_sensor_reading_resp *in)
@@ -847,18 +809,6 @@ scmi_sensor_reading_get_timestamped(const struct scmi_protocol_handle *ph,
return ret;
}

-static int
-__scmi_sensor_reading_get_timestamped(const struct scmi_handle *handle,
- u32 sensor_id, u8 count,
- struct scmi_sensor_reading *readings)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
-
- return scmi_sensor_reading_get_timestamped(ph, sensor_id, count,
- readings);
-}
-
static const struct scmi_sensor_info *
scmi_sensor_info_get(const struct scmi_protocol_handle *ph, u32 sensor_id)
{
@@ -867,15 +817,6 @@ scmi_sensor_info_get(const struct scmi_protocol_handle *ph, u32 sensor_id)
return si->sensors + sensor_id;
}

-static const struct scmi_sensor_info *
-__scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
-
- return scmi_sensor_info_get(ph, sensor_id);
-}
-
static int scmi_sensor_count_get(const struct scmi_protocol_handle *ph)
{
struct sensors_info *si = ph->get_priv(ph);
@@ -883,24 +824,6 @@ static int scmi_sensor_count_get(const struct scmi_protocol_handle *ph)
return si->num_sensors;
}

-static int __scmi_sensor_count_get(const struct scmi_handle *handle)
-{
- const struct scmi_protocol_handle *ph =
- scmi_map_protocol_handle(handle, SCMI_PROTOCOL_SENSOR);
-
- return scmi_sensor_count_get(ph);
-}
-
-static const struct scmi_sensor_ops sensor_ops = {
- .count_get = __scmi_sensor_count_get,
- .info_get = __scmi_sensor_info_get,
- .trip_point_config = __scmi_sensor_trip_point_config,
- .reading_get = __scmi_sensor_reading_get,
- .reading_get_timestamped = __scmi_sensor_reading_get_timestamped,
- .config_get = __scmi_sensor_config_get,
- .config_set = __scmi_sensor_config_set,
-};
-
static const struct scmi_sensor_proto_ops sensor_proto_ops = {
.count_get = scmi_sensor_count_get,
.info_get = scmi_sensor_info_get,
@@ -1040,7 +963,6 @@ static int scmi_sensors_protocol_init(const struct scmi_protocol_handle *ph)
u32 version;
int ret;
struct sensors_info *sinfo;
- struct scmi_handle *handle;

ph->xops->version_get(ph, &version);

@@ -1064,10 +986,6 @@ static int scmi_sensors_protocol_init(const struct scmi_protocol_handle *ph)
if (ret)
return ret;

- /* Transient code for legacy ops interface */
- handle = scmi_map_scmi_handle(ph);
- handle->sensor_ops = &sensor_ops;
-
return ph->set_priv(ph, sinfo);
}

diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index ead06db7be18..3ec0ac30fe60 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -463,23 +463,6 @@ struct scmi_sensor_proto_ops {
u32 sensor_id, u32 sensor_config);
};

-struct scmi_sensor_ops {
- int (*count_get)(const struct scmi_handle *handle);
- const struct scmi_sensor_info *(*info_get)
- (const struct scmi_handle *handle, u32 sensor_id);
- int (*trip_point_config)(const struct scmi_handle *handle,
- u32 sensor_id, u8 trip_id, u64 trip_value);
- int (*reading_get)(const struct scmi_handle *handle, u32 sensor_id,
- u64 *value);
- int (*reading_get_timestamped)(const struct scmi_handle *handle,
- u32 sensor_id, u8 count,
- struct scmi_sensor_reading *readings);
- int (*config_get)(const struct scmi_handle *handle,
- u32 sensor_id, u32 *sensor_config);
- int (*config_set)(const struct scmi_handle *handle,
- u32 sensor_id, u32 sensor_config);
-};
-
/**
* struct scmi_reset_proto_ops - represents the various operations provided
* by SCMI Reset Protocol
@@ -622,7 +605,6 @@ struct scmi_notify_ops {
*
* @dev: pointer to the SCMI device
* @version: pointer to the structure containing SCMI version information
- * @sensor_ops: pointer to set of sensor protocol operations
* @voltage_ops: pointer to set of voltage protocol operations
* @devm_protocol_get: devres managed method to acquire a protocol and get specific
* operations and a dedicated protocol handler
@@ -636,7 +618,6 @@ struct scmi_notify_ops {
struct scmi_handle {
struct device *dev;
struct scmi_revision_info *version;
- const struct scmi_sensor_ops *sensor_ops;
const struct scmi_voltage_ops *voltage_ops;

const void __must_check *
--
2.17.1

2021-03-16 20:00:55

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

Port driver to the new SCMI Sensor interface based on protocol handles
and common devm_get_ops().

Cc: Jyoti Bhayana <[email protected]>
Cc: Jonathan Cameron <[email protected]>
Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++++++++++------------
1 file changed, 41 insertions(+), 50 deletions(-)

diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
index 872d87ca6256..b4bdc3f3a946 100644
--- a/drivers/iio/common/scmi_sensors/scmi_iio.c
+++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
@@ -21,8 +21,10 @@

#define SCMI_IIO_NUM_OF_AXIS 3

+static const struct scmi_sensor_proto_ops *sensor_ops;
+
struct scmi_iio_priv {
- struct scmi_handle *handle;
+ struct scmi_protocol_handle *ph;
const struct scmi_sensor_info *sensor_info;
struct iio_dev *indio_dev;
/* adding one additional channel for timestamp */
@@ -82,7 +84,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
{
struct scmi_iio_priv *sensor = iio_priv(iio_dev);
- u32 sensor_id = sensor->sensor_info->id;
u32 sensor_config = 0;
int err;

@@ -92,27 +93,11 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)

sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
SCMI_SENS_CFG_SENSOR_ENABLE);
-
- err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
- SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
- &sensor_id, &sensor->sensor_update_nb);
- if (err) {
- dev_err(&iio_dev->dev,
- "Error in registering sensor update notifier for sensor %s err %d",
- sensor->sensor_info->name, err);
- return err;
- }
-
- err = sensor->handle->sensor_ops->config_set(sensor->handle,
- sensor->sensor_info->id, sensor_config);
- if (err) {
- sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
- SCMI_PROTOCOL_SENSOR,
- SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
- &sensor->sensor_update_nb);
+ err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
+ sensor_config);
+ if (err)
dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
sensor->sensor_info->name, err);
- }

return err;
}
@@ -120,25 +105,13 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
{
struct scmi_iio_priv *sensor = iio_priv(iio_dev);
- u32 sensor_id = sensor->sensor_info->id;
u32 sensor_config = 0;
int err;

sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
SCMI_SENS_CFG_SENSOR_DISABLE);
-
- err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
- SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
- &sensor_id, &sensor->sensor_update_nb);
- if (err) {
- dev_err(&iio_dev->dev,
- "Error in unregistering sensor update notifier for sensor %s err %d",
- sensor->sensor_info->name, err);
- return err;
- }
-
- err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
- sensor_config);
+ err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
+ sensor_config);
if (err) {
dev_err(&iio_dev->dev,
"Error in disabling sensor %s with err %d",
@@ -161,8 +134,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
u32 sensor_config;
char buf[32];

- int err = sensor->handle->sensor_ops->config_get(sensor->handle,
- sensor->sensor_info->id, &sensor_config);
+ int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
+ &sensor_config);
if (err) {
dev_err(&iio_dev->dev,
"Error in getting sensor config for sensor %s err %d",
@@ -208,8 +181,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
sensor_config |=
FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);

- err = sensor->handle->sensor_ops->config_set(sensor->handle,
- sensor->sensor_info->id, sensor_config);
+ err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
+ sensor_config);
if (err)
dev_err(&iio_dev->dev,
"Error in setting sensor update interval for sensor %s value %u err %d",
@@ -274,8 +247,8 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
u32 sensor_config;
int mult;

- int err = sensor->handle->sensor_ops->config_get(sensor->handle,
- sensor->sensor_info->id, &sensor_config);
+ int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
+ &sensor_config);
if (err) {
dev_err(&iio_dev->dev,
"Error in getting sensor config for sensor %s err %d",
@@ -542,15 +515,17 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
return 0;
}

-static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
- struct scmi_handle *handle,
- const struct scmi_sensor_info *sensor_info)
+static struct iio_dev *
+scmi_alloc_iiodev(struct scmi_device *sdev, struct scmi_protocol_handle *ph,
+ const struct scmi_sensor_info *sensor_info)
{
struct iio_chan_spec *iio_channels;
struct scmi_iio_priv *sensor;
enum iio_modifier modifier;
enum iio_chan_type type;
struct iio_dev *iiodev;
+ struct device *dev = &sdev->dev;
+ const struct scmi_handle *handle = sdev->handle;
int i, ret;

iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
@@ -560,7 +535,7 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
iiodev->modes = INDIO_DIRECT_MODE;
iiodev->dev.parent = dev;
sensor = iio_priv(iiodev);
- sensor->handle = handle;
+ sensor->ph = ph;
sensor->sensor_info = sensor_info;
sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
sensor->indio_dev = iiodev;
@@ -595,6 +570,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
sensor_info->axis[i].id);
}

+ ret = handle->notify_ops->devm_event_notifier_register(sdev,
+ SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
+ &sensor->sensor_info->id,
+ &sensor->sensor_update_nb);
+ if (ret) {
+ dev_err(&iiodev->dev,
+ "Error in registering sensor update notifier for sensor %s err %d",
+ sensor->sensor_info->name, ret);
+ return ERR_PTR(ret);
+ }
+
scmi_iio_set_timestamp_channel(&iio_channels[i], i);
iiodev->channels = iio_channels;
return iiodev;
@@ -604,24 +590,29 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
{
const struct scmi_sensor_info *sensor_info;
struct scmi_handle *handle = sdev->handle;
+ struct scmi_protocol_handle *ph;
struct device *dev = &sdev->dev;
struct iio_dev *scmi_iio_dev;
u16 nr_sensors;
int err = -ENODEV, i;

- if (!handle || !handle->sensor_ops) {
+ if (!handle)
+ return -ENODEV;
+
+ sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
+ if (IS_ERR(sensor_ops)) {
dev_err(dev, "SCMI device has no sensor interface\n");
- return -EINVAL;
+ return PTR_ERR(sensor_ops);
}

- nr_sensors = handle->sensor_ops->count_get(handle);
+ nr_sensors = sensor_ops->count_get(ph);
if (!nr_sensors) {
dev_dbg(dev, "0 sensors found via SCMI bus\n");
return -ENODEV;
}

for (i = 0; i < nr_sensors; i++) {
- sensor_info = handle->sensor_ops->info_get(handle, i);
+ sensor_info = sensor_ops->info_get(ph, i);
if (!sensor_info) {
dev_err(dev, "SCMI sensor %d has missing info\n", i);
return -EINVAL;
@@ -636,7 +627,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
sensor_info->axis[0].type != RADIANS_SEC)
continue;

- scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
+ scmi_iio_dev = scmi_alloc_iiodev(sdev, ph, sensor_info);
if (IS_ERR(scmi_iio_dev)) {
dev_err(dev,
"failed to allocate IIO device for sensor %s: %ld\n",
--
2.17.1

2021-03-16 20:05:17

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 29/38] regulator: scmi: port driver to the new scmi_voltage_proto_ops interface

Port driver to the new SCMI Voltage interface based on protocol handles
and common devm_get_ops().

Cc: Mark Brown <[email protected]>
Acked-by: Mark Brown <[email protected]>
Signed-off-by: Cristian Marussi <[email protected]>
---
v6 -> v7
- fixed Copyright
v4 --> v5
- using renamed devm_get/put_protocol
---
drivers/regulator/scmi-regulator.c | 42 ++++++++++++++++--------------
1 file changed, 23 insertions(+), 19 deletions(-)

diff --git a/drivers/regulator/scmi-regulator.c b/drivers/regulator/scmi-regulator.c
index 0e8b3caa8146..a38343f8c843 100644
--- a/drivers/regulator/scmi-regulator.c
+++ b/drivers/regulator/scmi-regulator.c
@@ -2,7 +2,7 @@
//
// System Control and Management Interface (SCMI) based regulator driver
//
-// Copyright (C) 2020 ARM Ltd.
+// Copyright (C) 2020-2021 ARM Ltd.
//
// Implements a regulator driver on top of the SCMI Voltage Protocol.
//
@@ -33,9 +33,12 @@
#include <linux/slab.h>
#include <linux/types.h>

+static const struct scmi_voltage_proto_ops *voltage_ops;
+
struct scmi_regulator {
u32 id;
struct scmi_device *sdev;
+ struct scmi_protocol_handle *ph;
struct regulator_dev *rdev;
struct device_node *of_node;
struct regulator_desc desc;
@@ -50,19 +53,17 @@ struct scmi_regulator_info {
static int scmi_reg_enable(struct regulator_dev *rdev)
{
struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
- const struct scmi_handle *handle = sreg->sdev->handle;

- return handle->voltage_ops->config_set(handle, sreg->id,
- SCMI_VOLTAGE_ARCH_STATE_ON);
+ return voltage_ops->config_set(sreg->ph, sreg->id,
+ SCMI_VOLTAGE_ARCH_STATE_ON);
}

static int scmi_reg_disable(struct regulator_dev *rdev)
{
struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
- const struct scmi_handle *handle = sreg->sdev->handle;

- return handle->voltage_ops->config_set(handle, sreg->id,
- SCMI_VOLTAGE_ARCH_STATE_OFF);
+ return voltage_ops->config_set(sreg->ph, sreg->id,
+ SCMI_VOLTAGE_ARCH_STATE_OFF);
}

static int scmi_reg_is_enabled(struct regulator_dev *rdev)
@@ -70,10 +71,8 @@ static int scmi_reg_is_enabled(struct regulator_dev *rdev)
int ret;
u32 config;
struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
- const struct scmi_handle *handle = sreg->sdev->handle;

- ret = handle->voltage_ops->config_get(handle, sreg->id,
- &config);
+ ret = voltage_ops->config_get(sreg->ph, sreg->id, &config);
if (ret) {
dev_err(&sreg->sdev->dev,
"Error %d reading regulator %s status.\n",
@@ -89,9 +88,8 @@ static int scmi_reg_get_voltage_sel(struct regulator_dev *rdev)
int ret;
s32 volt_uV;
struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
- const struct scmi_handle *handle = sreg->sdev->handle;

- ret = handle->voltage_ops->level_get(handle, sreg->id, &volt_uV);
+ ret = voltage_ops->level_get(sreg->ph, sreg->id, &volt_uV);
if (ret)
return ret;

@@ -103,13 +101,12 @@ static int scmi_reg_set_voltage_sel(struct regulator_dev *rdev,
{
s32 volt_uV;
struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
- const struct scmi_handle *handle = sreg->sdev->handle;

volt_uV = sreg->desc.ops->list_voltage(rdev, selector);
if (volt_uV <= 0)
return -EINVAL;

- return handle->voltage_ops->level_set(handle, sreg->id, 0x0, volt_uV);
+ return voltage_ops->level_set(sreg->ph, sreg->id, 0x0, volt_uV);
}

static const struct regulator_ops scmi_reg_fixed_ops = {
@@ -204,11 +201,10 @@ scmi_config_discrete_regulator_mappings(struct scmi_regulator *sreg,
static int scmi_regulator_common_init(struct scmi_regulator *sreg)
{
int ret;
- const struct scmi_handle *handle = sreg->sdev->handle;
struct device *dev = &sreg->sdev->dev;
const struct scmi_voltage_info *vinfo;

- vinfo = handle->voltage_ops->info_get(handle, sreg->id);
+ vinfo = voltage_ops->info_get(sreg->ph, sreg->id);
if (!vinfo) {
dev_warn(dev, "Failure to get voltage domain %d\n",
sreg->id);
@@ -257,6 +253,7 @@ static int scmi_regulator_common_init(struct scmi_regulator *sreg)
}

static int process_scmi_regulator_of_node(struct scmi_device *sdev,
+ struct scmi_protocol_handle *ph,
struct device_node *np,
struct scmi_regulator_info *rinfo)
{
@@ -284,6 +281,7 @@ static int process_scmi_regulator_of_node(struct scmi_device *sdev,

rinfo->sregv[dom]->id = dom;
rinfo->sregv[dom]->sdev = sdev;
+ rinfo->sregv[dom]->ph = ph;

/* get hold of good nodes */
of_node_get(np);
@@ -302,11 +300,17 @@ static int scmi_regulator_probe(struct scmi_device *sdev)
struct device_node *np, *child;
const struct scmi_handle *handle = sdev->handle;
struct scmi_regulator_info *rinfo;
+ struct scmi_protocol_handle *ph;

- if (!handle || !handle->voltage_ops)
+ if (!handle)
return -ENODEV;

- num_doms = handle->voltage_ops->num_domains_get(handle);
+ voltage_ops = handle->devm_protocol_get(sdev,
+ SCMI_PROTOCOL_VOLTAGE, &ph);
+ if (IS_ERR(voltage_ops))
+ return PTR_ERR(voltage_ops);
+
+ num_doms = voltage_ops->num_domains_get(ph);
if (num_doms <= 0) {
if (!num_doms) {
dev_err(&sdev->dev,
@@ -341,7 +345,7 @@ static int scmi_regulator_probe(struct scmi_device *sdev)
*/
np = of_find_node_by_name(handle->dev->of_node, "regulators");
for_each_child_of_node(np, child) {
- ret = process_scmi_regulator_of_node(sdev, child, rinfo);
+ ret = process_scmi_regulator_of_node(sdev, ph, child, rinfo);
/* abort on any mem issue */
if (ret == -ENOMEM)
return ret;
--
2.17.1

2021-03-16 20:05:20

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 35/38] firmware: arm_scmi: make notify_priv really private

Notification private data is currently accessible via handle->notify_priv;
this data was indeed meant to be private to the notification core support
and not to be accessible by SCMI drivers: make it private hiding it inside
instance descriptor struct scmi_info and accessible only via dedicated
helpers.

Signed-off-by: Cristian Marussi <[email protected]>
---
v6 --> v7
- renamed non-static function to fit scmi_<OBJ>_<ACTION> naming pattern
---
drivers/firmware/arm_scmi/common.h | 4 +++
drivers/firmware/arm_scmi/driver.c | 21 ++++++++++++++
drivers/firmware/arm_scmi/notify.c | 45 ++++++++++--------------------
include/linux/scmi_protocol.h | 3 --
4 files changed, 40 insertions(+), 33 deletions(-)

diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index c4a1262fb18d..c093f332cdcd 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -343,4 +343,8 @@ void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem);
bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer);

+void scmi_notification_instance_data_set(const struct scmi_handle *handle,
+ void *priv);
+void *scmi_notification_instance_data_get(const struct scmi_handle *handle);
+
#endif /* _SCMI_COMMON_H */
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 27213bf768c0..563a64131035 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -113,6 +113,7 @@ struct scmi_protocol_instance {
* @protocols_mtx: A mutex to protect protocols instances initialization.
* @protocols_imp: List of protocols implemented, currently maximum of
* MAX_PROTOCOLS_IMP elements allocated by the base protocol
+ * @notify_priv: Pointer to private data structure specific to notifications.
* @node: List head
* @users: Number of users of this instance
*/
@@ -129,6 +130,7 @@ struct scmi_info {
/* Ensure mutual exclusive access to protocols instance array */
struct mutex protocols_mtx;
u8 *protocols_imp;
+ void *notify_priv;
struct list_head node;
int users;
};
@@ -170,6 +172,25 @@ static inline void scmi_dump_header_dbg(struct device *dev,
hdr->id, hdr->seq, hdr->protocol_id);
}

+void scmi_notification_instance_data_set(const struct scmi_handle *handle,
+ void *priv)
+{
+ struct scmi_info *info = handle_to_scmi_info(handle);
+
+ info->notify_priv = priv;
+ /* Ensure updated protocol private date are visible */
+ smp_wmb();
+}
+
+void *scmi_notification_instance_data_get(const struct scmi_handle *handle)
+{
+ struct scmi_info *info = handle_to_scmi_info(handle);
+
+ /* Ensure protocols_private_data has been updated */
+ smp_rmb();
+ return info->notify_priv;
+}
+
/**
* scmi_xfer_get() - Allocate one message
*
diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index 023c93deb14b..9ca019dd0aeb 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -582,11 +582,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id,
struct scmi_event_header eh;
struct scmi_notify_instance *ni;

- /* Ensure notify_priv is updated */
- smp_rmb();
- if (!handle->notify_priv)
+ ni = scmi_notification_instance_data_get(handle);
+ if (!ni)
return 0;
- ni = handle->notify_priv;

r_evt = SCMI_GET_REVT(ni, proto_id, evt_id);
if (!r_evt)
@@ -762,11 +760,9 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
(!ee->num_sources && !ee->ops->get_num_sources))
return -EINVAL;

- /* Ensure notify_priv is updated */
- smp_rmb();
- if (!handle->notify_priv)
+ ni = scmi_notification_instance_data_get(handle);
+ if (!ni)
return -ENOMEM;
- ni = handle->notify_priv;

/* num_sources cannot be <= 0 */
if (ee->num_sources) {
@@ -846,12 +842,10 @@ void scmi_deregister_protocol_events(const struct scmi_handle *handle,
struct scmi_notify_instance *ni;
struct scmi_registered_events_desc *pd;

- /* Ensure notify_priv is updated */
- smp_rmb();
- if (!handle->notify_priv)
+ ni = scmi_notification_instance_data_get(handle);
+ if (!ni)
return;

- ni = handle->notify_priv;
pd = ni->registered_protocols[proto_id];
if (!pd)
return;
@@ -1354,11 +1348,9 @@ static int scmi_register_notifier(const struct scmi_handle *handle,
struct scmi_event_handler *hndl;
struct scmi_notify_instance *ni;

- /* Ensure notify_priv is updated */
- smp_rmb();
- if (!handle->notify_priv)
+ ni = scmi_notification_instance_data_get(handle);
+ if (!ni)
return -ENODEV;
- ni = handle->notify_priv;

evt_key = MAKE_HASH_KEY(proto_id, evt_id,
src_id ? *src_id : SRC_ID_MASK);
@@ -1402,11 +1394,9 @@ static int scmi_unregister_notifier(const struct scmi_handle *handle,
struct scmi_event_handler *hndl;
struct scmi_notify_instance *ni;

- /* Ensure notify_priv is updated */
- smp_rmb();
- if (!handle->notify_priv)
+ ni = scmi_notification_instance_data_get(handle);
+ if (!ni)
return -ENODEV;
- ni = handle->notify_priv;

evt_key = MAKE_HASH_KEY(proto_id, evt_id,
src_id ? *src_id : SRC_ID_MASK);
@@ -1681,8 +1671,8 @@ int scmi_notification_init(struct scmi_handle *handle)

INIT_WORK(&ni->init_work, scmi_protocols_late_init);

+ scmi_notification_instance_data_set(handle, ni);
handle->notify_ops = &notify_ops;
- handle->notify_priv = ni;
/* Ensure handle is up to date */
smp_wmb();

@@ -1694,7 +1684,7 @@ int scmi_notification_init(struct scmi_handle *handle)

err:
dev_warn(handle->dev, "Initialization Failed.\n");
- devres_release_group(handle->dev, NULL);
+ devres_release_group(handle->dev, gid);
return -ENOMEM;
}

@@ -1706,15 +1696,10 @@ void scmi_notification_exit(struct scmi_handle *handle)
{
struct scmi_notify_instance *ni;

- /* Ensure notify_priv is updated */
- smp_rmb();
- if (!handle->notify_priv)
+ ni = scmi_notification_instance_data_get(handle);
+ if (!ni)
return;
- ni = handle->notify_priv;
-
- handle->notify_priv = NULL;
- /* Ensure handle is up to date */
- smp_wmb();
+ scmi_notification_instance_data_set(handle, NULL);

/* Destroy while letting pending work complete */
destroy_workqueue(ni->notify_wq);
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 284dda52006e..114890bd7af0 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -609,8 +609,6 @@ struct scmi_notify_ops {
* operations and a dedicated protocol handler
* @devm_protocol_put: devres managed method to release a protocol
* @notify_ops: pointer to set of notifications related operations
- * @notify_priv: pointer to private data structure specific to notifications
- * (for internal use only)
*/
struct scmi_handle {
struct device *dev;
@@ -622,7 +620,6 @@ struct scmi_handle {
void (*devm_protocol_put)(struct scmi_device *sdev, u8 proto);

const struct scmi_notify_ops *notify_ops;
- void *notify_priv;
};

enum scmi_std_protocol {
--
2.17.1

2021-03-16 20:05:20

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 33/38] firmware: arm_scmi: cleanup unused core xfer wrappers

Remove unused core scmi_xfer wrappers now that we have migrated all
protocols to the new interface based on protocol handles.

Signed-off-by: Cristian Marussi <[email protected]>
---
drivers/firmware/arm_scmi/common.h | 15 -----
drivers/firmware/arm_scmi/driver.c | 91 ------------------------------
2 files changed, 106 deletions(-)

diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 378e9d713ec7..c4a1262fb18d 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -143,15 +143,6 @@ struct scmi_xfer {
struct completion *async_done;
};

-void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
-int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
-int scmi_do_xfer_with_response(const struct scmi_handle *h,
- struct scmi_xfer *xfer);
-int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
- size_t tx_size, size_t rx_size, struct scmi_xfer **p);
-void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle,
- struct scmi_xfer *xfer);
-
struct scmi_xfer_ops;

/**
@@ -181,11 +172,6 @@ struct scmi_protocol_handle {
void *(*get_priv)(const struct scmi_protocol_handle *ph);
};

-const struct scmi_protocol_handle *
-scmi_map_protocol_handle(const struct scmi_handle *handle, u8 prot_id);
-
-struct scmi_handle *scmi_map_scmi_handle(const struct scmi_protocol_handle *ph);
-
/**
* struct scmi_xfer_ops - References to the core SCMI xfer operations.
* @version_get: Get this version protocol.
@@ -220,7 +206,6 @@ scmi_revision_area_get(const struct scmi_protocol_handle *ph);
int scmi_handle_put(const struct scmi_handle *handle);
struct scmi_handle *scmi_handle_get(struct device *dev);
void scmi_set_handle(struct scmi_device *scmi_dev);
-int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version);
void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph,
u8 *prot_imp);

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index eb1276d8026e..27213bf768c0 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -349,28 +349,6 @@ void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
}
}

-/* Transient code wrapper to ease API migration */
-const struct scmi_protocol_handle *
-scmi_map_protocol_handle(const struct scmi_handle *handle, u8 prot_id)
-{
- struct scmi_info *info = handle_to_scmi_info(handle);
- const struct scmi_protocol_instance *pi;
-
- mutex_lock(&info->protocols_mtx);
- pi = idr_find(&info->protocols, prot_id);
- mutex_unlock(&info->protocols_mtx);
-
- return pi ? &pi->ph : NULL;
-}
-
-/* Transient code wrapper to ease API migration */
-struct scmi_handle *scmi_map_scmi_handle(const struct scmi_protocol_handle *ph)
-{
- const struct scmi_protocol_instance *pi = ph_to_pi(ph);
-
- return (struct scmi_handle *)pi->handle;
-}
-
/**
* xfer_put() - Release a transmit message
*
@@ -386,17 +364,6 @@ static void xfer_put(const struct scmi_protocol_handle *ph,
__scmi_xfer_put(&info->tx_minfo, xfer);
}

-void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer)
-{
- const struct scmi_protocol_handle *ph;
-
- ph = scmi_map_protocol_handle(h, xfer->hdr.protocol_id);
- if (!ph)
- return;
-
- return xfer_put(ph, xfer);
-}
-
#define SCMI_MAX_POLL_TO_NS (100 * NSEC_PER_USEC)

static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
@@ -480,17 +447,6 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
return ret;
}

-int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer)
-{
- const struct scmi_protocol_handle *ph;
-
- ph = scmi_map_protocol_handle(h, xfer->hdr.protocol_id);
- if (!ph)
- return -EINVAL;
-
- return do_xfer(ph, xfer);
-}
-
static void reset_rx_to_maxsz(const struct scmi_protocol_handle *ph,
struct scmi_xfer *xfer)
{
@@ -500,18 +456,6 @@ static void reset_rx_to_maxsz(const struct scmi_protocol_handle *ph,
xfer->rx.len = info->desc->max_msg_size;
}

-void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle,
- struct scmi_xfer *xfer)
-{
- const struct scmi_protocol_handle *ph;
-
- ph = scmi_map_protocol_handle(handle, xfer->hdr.protocol_id);
- if (!ph)
- return;
-
- return reset_rx_to_maxsz(ph, xfer);
-}
-
#define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC)

/**
@@ -543,18 +487,6 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph,
return ret;
}

-int scmi_do_xfer_with_response(const struct scmi_handle *h,
- struct scmi_xfer *xfer)
-{
- const struct scmi_protocol_handle *ph;
-
- ph = scmi_map_protocol_handle(h, xfer->hdr.protocol_id);
- if (!ph)
- return -EINVAL;
-
- return do_xfer_with_response(ph, xfer);
-}
-
/**
* xfer_get_init() - Allocate and initialise one message for transmit
*
@@ -604,18 +536,6 @@ static int xfer_get_init(const struct scmi_protocol_handle *ph,
return 0;
}

-int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
- size_t tx_size, size_t rx_size, struct scmi_xfer **p)
-{
- const struct scmi_protocol_handle *ph;
-
- ph = scmi_map_protocol_handle(h, prot_id);
- if (!ph)
- return -EINVAL;
-
- return xfer_get_init(ph, msg_id, tx_size, rx_size, p);
-}
-
/**
* version_get() - command to get the revision of the SCMI entity
*
@@ -646,17 +566,6 @@ static int version_get(const struct scmi_protocol_handle *ph, u32 *version)
return ret;
}

-int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version)
-{
- const struct scmi_protocol_handle *ph;
-
- ph = scmi_map_protocol_handle(h, protocol);
- if (!ph)
- return -EINVAL;
-
- return version_get(ph, version);
-}
-
/**
* scmi_set_protocol_priv - Set protocol specific data at init time
*
--
2.17.1

2021-03-16 20:05:36

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 37/38] firmware: arm_scmi: add protocol modularization support

Extend SCMI protocols accounting mechanism to address possible module
usage and add the support to possibly define new protocols as loadable
modules.

Keep Standard protocols built into the SCMI core.

Signed-off-by: Cristian Marussi <[email protected]>
---
v6 --> v7
- rename used IDR scmi_available_protocols => scmi_protocols
- reworks to fit into refactored scmi_get_protocol_instance()
- renamed non-static function to fit scmi_<OBJ>_<ACTION> naming pattern
- added missing .owner to voltage.c
---
drivers/firmware/arm_scmi/base.c | 2 ++
drivers/firmware/arm_scmi/bus.c | 11 ++++++++++-
drivers/firmware/arm_scmi/clock.c | 2 ++
drivers/firmware/arm_scmi/common.h | 4 ++++
drivers/firmware/arm_scmi/driver.c | 17 +++++++++++++----
drivers/firmware/arm_scmi/perf.c | 2 ++
drivers/firmware/arm_scmi/power.c | 2 ++
drivers/firmware/arm_scmi/reset.c | 2 ++
drivers/firmware/arm_scmi/sensors.c | 2 ++
drivers/firmware/arm_scmi/system.c | 2 ++
drivers/firmware/arm_scmi/voltage.c | 2 ++
include/linux/scmi_protocol.h | 12 ++++++++++++
12 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
index 0d28f0f825b6..de416f9e7921 100644
--- a/drivers/firmware/arm_scmi/base.c
+++ b/drivers/firmware/arm_scmi/base.c
@@ -7,6 +7,7 @@

#define pr_fmt(fmt) "SCMI Notifications BASE - " fmt

+#include <linux/module.h>
#include <linux/scmi_protocol.h>

#include "common.h"
@@ -373,6 +374,7 @@ static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)

static const struct scmi_protocol scmi_base = {
.id = SCMI_PROTOCOL_BASE,
+ .owner = NULL,
.instance_init = &scmi_base_protocol_init,
.ops = NULL,
.events = &base_protocol_events,
diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 992d50e10111..aadf2da21561 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -56,7 +56,7 @@ const struct scmi_protocol *scmi_protocol_get(int protocol_id)
const struct scmi_protocol *proto;

proto = idr_find(&scmi_protocols, protocol_id);
- if (!proto) {
+ if (!proto || !try_module_get(proto->owner)) {
pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id);
return NULL;
}
@@ -66,6 +66,15 @@ const struct scmi_protocol *scmi_protocol_get(int protocol_id)
return proto;
}

+void scmi_protocol_put(int protocol_id)
+{
+ const struct scmi_protocol *proto;
+
+ proto = idr_find(&scmi_protocols, protocol_id);
+ if (proto)
+ module_put(proto->owner);
+}
+
static int scmi_dev_probe(struct device *dev)
{
struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index 827cf25fc122..35b56c8ba0c0 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -5,6 +5,7 @@
* Copyright (C) 2018-2021 ARM Ltd.
*/

+#include <linux/module.h>
#include <linux/sort.h>

#include "common.h"
@@ -367,6 +368,7 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)

static const struct scmi_protocol scmi_clock = {
.id = SCMI_PROTOCOL_CLOCK,
+ .owner = THIS_MODULE,
.instance_init = &scmi_clock_protocol_init,
.ops = &clk_proto_ops,
};
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index c093f332cdcd..762dd5419700 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -14,6 +14,7 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/scmi_protocol.h>
#include <linux/types.h>

@@ -214,6 +215,7 @@ typedef int (*scmi_prot_init_ph_fn_t)(const struct scmi_protocol_handle *);
/**
* struct scmi_protocol - Protocol descriptor
* @id: Protocol ID.
+ * @owner: Module reference if any.
* @instance_init: Mandatory protocol initialization function.
* @instance_deinit: Optional protocol de-initialization function.
* @ops: Optional reference to the operations provided by the protocol and
@@ -222,6 +224,7 @@ typedef int (*scmi_prot_init_ph_fn_t)(const struct scmi_protocol_handle *);
*/
struct scmi_protocol {
const u8 id;
+ struct module *owner;
const scmi_prot_init_ph_fn_t instance_init;
const scmi_prot_init_ph_fn_t instance_deinit;
const void *ops;
@@ -257,6 +260,7 @@ void __exit scmi_##name##_unregister(void) \
}

const struct scmi_protocol *scmi_protocol_get(int protocol_id);
+void scmi_protocol_put(int protocol_id);

int scmi_protocol_acquire(const struct scmi_handle *handle, u8 protocol_id);
void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 563a64131035..c25c20c150dc 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -660,7 +660,8 @@ scmi_revision_area_get(const struct scmi_protocol_handle *ph)
*
* Context: Assumes to be called with @protocols_mtx already acquired.
* Return: A reference to a freshly allocated and initialized protocol instance
- * or ERR_PTR on failure.
+ * or ERR_PTR on failure. On failure the @proto reference is at first
+ * put using @scmi_protocol_put() before releasing all the devres group.
*/
static struct scmi_protocol_instance *
scmi_alloc_init_protocol_instance(struct scmi_info *info,
@@ -673,8 +674,10 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,

/* Protocol specific devres group */
gid = devres_open_group(handle->dev, NULL, GFP_KERNEL);
- if (!gid)
+ if (!gid) {
+ scmi_protocol_put(proto->id);
goto out;
+ }

pi = devm_kzalloc(handle->dev, sizeof(*pi), GFP_KERNEL);
if (!pi)
@@ -718,6 +721,8 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
return pi;

clean:
+ /* Take care to put the protocol module's owner before releasing all */
+ scmi_protocol_put(proto->id);
devres_release_group(handle->dev, gid);
out:
return ERR_PTR(ret);
@@ -732,7 +737,9 @@ scmi_alloc_init_protocol_instance(struct scmi_info *info,
* instance, allocate and initialize all the needed structures while handling
* resource allocation with a dedicated per-protocol devres subgroup.
*
- * Return: A reference to an initialized protocol instance or error on failure.
+ * Return: A reference to an initialized protocol instance or error on failure:
+ * in particular returns -EPROBE_DEFER when the desired protocol could
+ * NOT be found.
*/
static struct scmi_protocol_instance * __must_check
scmi_get_protocol_instance(const struct scmi_handle *handle, u8 protocol_id)
@@ -753,7 +760,7 @@ scmi_get_protocol_instance(const struct scmi_handle *handle, u8 protocol_id)
if (proto)
pi = scmi_alloc_init_protocol_instance(info, proto);
else
- pi = ERR_PTR(-ENODEV);
+ pi = ERR_PTR(-EPROBE_DEFER);
}
mutex_unlock(&info->protocols_mtx);

@@ -804,6 +811,8 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id)

idr_remove(&info->protocols, protocol_id);

+ scmi_protocol_put(protocol_id);
+
devres_release_group(handle->dev, gid);
dev_dbg(handle->dev, "De-Initialized protocol: 0x%X\n",
protocol_id);
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 059d6214f93b..f4cd5193b961 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/io.h>
#include <linux/io-64-nonatomic-hi-lo.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/scmi_protocol.h>
@@ -909,6 +910,7 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)

static const struct scmi_protocol scmi_perf = {
.id = SCMI_PROTOCOL_PERF,
+ .owner = THIS_MODULE,
.instance_init = &scmi_perf_protocol_init,
.ops = &perf_proto_ops,
.events = &perf_protocol_events,
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index e0987f0a8fb2..ad2ab080f344 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -7,6 +7,7 @@

#define pr_fmt(fmt) "SCMI Notifications POWER - " fmt

+#include <linux/module.h>
#include <linux/scmi_protocol.h>

#include "common.h"
@@ -312,6 +313,7 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph)

static const struct scmi_protocol scmi_power = {
.id = SCMI_PROTOCOL_POWER,
+ .owner = THIS_MODULE,
.instance_init = &scmi_power_protocol_init,
.ops = &power_proto_ops,
.events = &power_protocol_events,
diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 48b487302db8..9bf2478ec6d1 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -7,6 +7,7 @@

#define pr_fmt(fmt) "SCMI Notifications RESET - " fmt

+#include <linux/module.h>
#include <linux/scmi_protocol.h>

#include "common.h"
@@ -324,6 +325,7 @@ static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)

static const struct scmi_protocol scmi_reset = {
.id = SCMI_PROTOCOL_RESET,
+ .owner = THIS_MODULE,
.instance_init = &scmi_reset_protocol_init,
.ops = &reset_proto_ops,
.events = &reset_protocol_events,
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index 935c4b08829d..2c88aa221559 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -8,6 +8,7 @@
#define pr_fmt(fmt) "SCMI Notifications SENSOR - " fmt

#include <linux/bitfield.h>
+#include <linux/module.h>
#include <linux/scmi_protocol.h>

#include "common.h"
@@ -990,6 +991,7 @@ static int scmi_sensors_protocol_init(const struct scmi_protocol_handle *ph)

static const struct scmi_protocol scmi_sensors = {
.id = SCMI_PROTOCOL_SENSOR,
+ .owner = THIS_MODULE,
.instance_init = &scmi_sensors_protocol_init,
.ops = &sensor_proto_ops,
.events = &sensor_protocol_events,
diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c
index 3631a9f94d27..e5175ef73b40 100644
--- a/drivers/firmware/arm_scmi/system.c
+++ b/drivers/firmware/arm_scmi/system.c
@@ -7,6 +7,7 @@

#define pr_fmt(fmt) "SCMI Notifications SYSTEM - " fmt

+#include <linux/module.h>
#include <linux/scmi_protocol.h>

#include "common.h"
@@ -130,6 +131,7 @@ static int scmi_system_protocol_init(const struct scmi_protocol_handle *ph)

static const struct scmi_protocol scmi_system = {
.id = SCMI_PROTOCOL_SYSTEM,
+ .owner = THIS_MODULE,
.instance_init = &scmi_system_protocol_init,
.ops = NULL,
.events = &system_protocol_events,
diff --git a/drivers/firmware/arm_scmi/voltage.c b/drivers/firmware/arm_scmi/voltage.c
index 364bc14aa5fe..a5048956a0be 100644
--- a/drivers/firmware/arm_scmi/voltage.c
+++ b/drivers/firmware/arm_scmi/voltage.c
@@ -5,6 +5,7 @@
* Copyright (C) 2020-2021 ARM Ltd.
*/

+#include <linux/module.h>
#include <linux/scmi_protocol.h>

#include "common.h"
@@ -371,6 +372,7 @@ static int scmi_voltage_protocol_init(const struct scmi_protocol_handle *ph)

static const struct scmi_protocol scmi_voltage = {
.id = SCMI_PROTOCOL_VOLTAGE,
+ .owner = THIS_MODULE,
.instance_init = &scmi_voltage_protocol_init,
.ops = &voltage_proto_ops,
};
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index b80496d519f3..79d0a1237e6c 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -704,6 +704,18 @@ static inline void scmi_driver_unregister(struct scmi_driver *driver) {}
#define module_scmi_driver(__scmi_driver) \
module_driver(__scmi_driver, scmi_register, scmi_unregister)

+/**
+ * module_scmi_protocol() - Helper macro for registering a scmi protocol
+ * @__scmi_protocol: scmi_protocol structure
+ *
+ * Helper macro for scmi drivers to set up proper module init / exit
+ * functions. Replaces module_init() and module_exit() and keeps people from
+ * printing pointless things to the kernel log when their driver is loaded.
+ */
+#define module_scmi_protocol(__scmi_protocol) \
+ module_driver(__scmi_protocol, \
+ scmi_protocol_register, scmi_protocol_unregister)
+
struct scmi_protocol;
int scmi_protocol_register(const struct scmi_protocol *proto);
void scmi_protocol_unregister(const struct scmi_protocol *proto);
--
2.17.1

2021-03-16 20:06:58

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v7 38/38] firmware: arm_scmi: add dynamic scmi devices creation

Having added the support for SCMI protocols as modules in order to let
vendors extend the SCMI core with their own additions it seems odd to
then force SCMI drivers built on top to use a static device table to
declare their devices since this way any new SCMI drivers addition
would need the core SCMI device table to be updated too.

Remove the static core device table and let SCMI drivers to simply declare
which device/protocol pair they need at initialization time: the core will
then take care to generate such devices dynamically during platform
initialization or at module loading time, as long as the requested
underlying protocol is defined in the DT.

Signed-off-by: Cristian Marussi <[email protected]>
---
v6 --> v7
- renamed non-static function to fit scmi_<OBJ>_<ACTION> naming pattern
v4 --> v5
- using klist instead of custom lists
v3 --> v4
- add a few comments
---
drivers/firmware/arm_scmi/bus.c | 30 +++
drivers/firmware/arm_scmi/common.h | 5 +
drivers/firmware/arm_scmi/driver.c | 310 +++++++++++++++++++++++++----
3 files changed, 311 insertions(+), 34 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index aadf2da21561..784cf0027da3 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -51,6 +51,31 @@ static int scmi_dev_match(struct device *dev, struct device_driver *drv)
return 0;
}

+static int scmi_match_by_id_table(struct device *dev, void *data)
+{
+ struct scmi_device *sdev = to_scmi_dev(dev);
+ struct scmi_device_id *id_table = data;
+
+ return sdev->protocol_id == id_table->protocol_id &&
+ !strcmp(sdev->name, id_table->name);
+}
+
+struct scmi_device *scmi_child_dev_find(struct device *parent,
+ int prot_id, const char *name)
+{
+ struct scmi_device_id id_table;
+ struct device *dev;
+
+ id_table.protocol_id = prot_id;
+ id_table.name = name;
+
+ dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
+ if (!dev)
+ return NULL;
+
+ return to_scmi_dev(dev);
+}
+
const struct scmi_protocol *scmi_protocol_get(int protocol_id)
{
const struct scmi_protocol *proto;
@@ -114,6 +139,10 @@ int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
{
int retval;

+ retval = scmi_protocol_device_request(driver->id_table);
+ if (retval)
+ return retval;
+
driver->driver.bus = &scmi_bus_type;
driver->driver.name = driver->name;
driver->driver.owner = owner;
@@ -130,6 +159,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);
}
EXPORT_SYMBOL_GPL(scmi_driver_unregister);

diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 762dd5419700..228bf4a71d23 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -309,6 +309,11 @@ 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);
+struct scmi_device *scmi_child_dev_find(struct device *parent,
+ int prot_id, const char *name);
+
/**
* struct scmi_desc - Description of SoC integration
*
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index c25c20c150dc..66eb3f0e5daf 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/ktime.h>
+#include <linux/list.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
@@ -56,6 +57,14 @@ static DEFINE_MUTEX(scmi_list_mutex);
/* Track the unique id for the transfers for debug & profiling purpose */
static atomic_t transfer_last_id;

+static DEFINE_IDR(scmi_requested_devices);
+static DEFINE_MUTEX(scmi_requested_devices_mtx);
+
+struct scmi_requested_dev {
+ const struct scmi_device_id *id_table;
+ struct list_head node;
+};
+
/**
* struct scmi_xfers_info - Structure to manage transfer information
*
@@ -113,6 +122,8 @@ struct scmi_protocol_instance {
* @protocols_mtx: A mutex to protect protocols instances initialization.
* @protocols_imp: List of protocols implemented, currently maximum of
* MAX_PROTOCOLS_IMP elements allocated by the base protocol
+ * @active_protocols: IDR storing device_nodes for protocols actually defined
+ * in the DT and confirmed as implemented by fw.
* @notify_priv: Pointer to private data structure specific to notifications.
* @node: List head
* @users: Number of users of this instance
@@ -130,6 +141,7 @@ struct scmi_info {
/* Ensure mutual exclusive access to protocols instance array */
struct mutex protocols_mtx;
u8 *protocols_imp;
+ struct idr active_protocols;
void *notify_priv;
struct list_head node;
int users;
@@ -935,6 +947,13 @@ static void scmi_devm_protocol_put(struct scmi_device *sdev, u8 protocol_id)
WARN_ON(ret);
}

+static inline
+struct scmi_handle *scmi_handle_get_from_info_unlocked(struct scmi_info *info)
+{
+ info->users++;
+ return &info->handle;
+}
+
/**
* scmi_handle_get() - Get the SCMI handle for a device
*
@@ -956,8 +975,7 @@ struct scmi_handle *scmi_handle_get(struct device *dev)
list_for_each(p, &scmi_list) {
info = list_entry(p, struct scmi_info, node);
if (dev->parent == info->dev) {
- handle = &info->handle;
- info->users++;
+ handle = scmi_handle_get_from_info_unlocked(info);
break;
}
}
@@ -1100,63 +1118,268 @@ scmi_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)
return ret;
}

-static inline void
-scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
- int prot_id, const char *name)
+/**
+ * scmi_get_protocol_device - Helper to get/create an SCMI device.
+ *
+ * @np: A device node representing a valid active protocols for the referred
+ * SCMI instance.
+ * @info: The referred SCMI instance for which we are getting/creating this
+ * device.
+ * @prot_id: The protocol ID.
+ * @name: The device name.
+ *
+ * Referring to the specific SCMI instance identified by @info, this helper
+ * takes care to return a properly initialized device matching the requested
+ * @proto_id and @name: if device was still not existent it is created as a
+ * child of the specified SCMI instance @info and its transport properly
+ * initialized as usual.
+ */
+static inline struct scmi_device *
+scmi_get_protocol_device(struct device_node *np, struct scmi_info *info,
+ int prot_id, const char *name)
{
struct scmi_device *sdev;

+ /* Already created for this parent SCMI instance ? */
+ sdev = scmi_child_dev_find(info->dev, prot_id, name);
+ if (sdev)
+ return sdev;
+
+ pr_debug("Creating SCMI device (%s) for protocol %x\n", name, prot_id);
+
sdev = scmi_device_create(np, info->dev, prot_id, name);
if (!sdev) {
dev_err(info->dev, "failed to create %d protocol device\n",
prot_id);
- return;
+ return NULL;
}

if (scmi_txrx_setup(info, &sdev->dev, prot_id)) {
dev_err(&sdev->dev, "failed to setup transport\n");
scmi_device_destroy(sdev);
- return;
+ return NULL;
}

+ return sdev;
+}
+
+static inline void
+scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
+ int prot_id, const char *name)
+{
+ struct scmi_device *sdev;
+
+ sdev = scmi_get_protocol_device(np, info, prot_id, name);
+ if (!sdev)
+ return;
+
/* setup handle now as the transport is ready */
scmi_set_handle(sdev);
}

-#define MAX_SCMI_DEV_PER_PROTOCOL 2
-struct scmi_prot_devnames {
- int protocol_id;
- char *names[MAX_SCMI_DEV_PER_PROTOCOL];
-};
+/**
+ * scmi_create_protocol_devices - Create devices for all pending requests for
+ * this SCMI instance.
+ *
+ * @np: The device node describing the protocol
+ * @info: The SCMI instance descriptor
+ * @prot_id: The protocol ID
+ *
+ * All devices previously requested for this instance (if any) are found and
+ * created by scanning the proper @&scmi_requested_devices entry.
+ */
+static void scmi_create_protocol_devices(struct device_node *np,
+ struct scmi_info *info, int prot_id)
+{
+ struct list_head *phead;

-static struct scmi_prot_devnames devnames[] = {
- { SCMI_PROTOCOL_POWER, { "genpd" },},
- { SCMI_PROTOCOL_SYSTEM, { "syspower" },},
- { SCMI_PROTOCOL_PERF, { "cpufreq" },},
- { SCMI_PROTOCOL_CLOCK, { "clocks" },},
- { SCMI_PROTOCOL_SENSOR, { "hwmon", "iiodev" },},
- { SCMI_PROTOCOL_RESET, { "reset" },},
- { SCMI_PROTOCOL_VOLTAGE, { "regulator" },},
-};
+ mutex_lock(&scmi_requested_devices_mtx);
+ phead = idr_find(&scmi_requested_devices, prot_id);
+ if (phead) {
+ struct scmi_requested_dev *rdev;

-static inline void
-scmi_create_protocol_devices(struct device_node *np, struct scmi_info *info,
- int prot_id)
+ list_for_each_entry(rdev, phead, node)
+ scmi_create_protocol_device(np, info, prot_id,
+ rdev->id_table->name);
+ }
+ mutex_unlock(&scmi_requested_devices_mtx);
+}
+
+/**
+ * scmi_protocol_device_request - Helper to request a device
+ *
+ * @id_table: A protocol/name pair descriptor for the device to be created.
+ *
+ * This helper let an SCMI driver request specific devices identified by the
+ * @id_table to be created for each active SCMI instance.
+ *
+ * The requested device name MUST NOT be already existent for any protocol;
+ * at first the freshly requested @id_table is annotated in the IDR table
+ * @scmi_requested_devices, then a matching device is created for each already
+ * active SCMI instance. (if any)
+ *
+ * This way the requested device is created straight-away for all the already
+ * initialized(probed) SCMI instances (handles) and it remains also annotated
+ * as pending creation if the requesting SCMI driver was loaded before some
+ * SCMI instance and related transports were available: when such late instance
+ * is probed, its probe will take care to scan the list of pending requested
+ * devices and create those on its own (see @scmi_create_protocol_devices and
+ * its enclosing loop)
+ *
+ * Return: 0 on Success
+ */
+int scmi_protocol_device_request(const struct scmi_device_id *id_table)
{
- int loop, cnt;
+ int ret = 0;
+ unsigned int id = 0;
+ struct list_head *head, *phead = NULL;
+ struct scmi_requested_dev *rdev;
+ struct scmi_info *info;

- for (loop = 0; loop < ARRAY_SIZE(devnames); loop++) {
- if (devnames[loop].protocol_id != prot_id)
- continue;
+ pr_debug("Requesting SCMI device (%s) for protocol %x\n",
+ id_table->name, id_table->protocol_id);
+
+ /*
+ * Search for the matching protocol rdev list and then search
+ * of any existent equally named device...fails if any duplicate found.
+ */
+ mutex_lock(&scmi_requested_devices_mtx);
+ idr_for_each_entry(&scmi_requested_devices, head, id) {
+ if (!phead) {
+ /* A list found registered in the IDR is never empty */
+ rdev = list_first_entry(head, struct scmi_requested_dev,
+ node);
+ if (rdev->id_table->protocol_id ==
+ id_table->protocol_id)
+ phead = head;
+ }
+ list_for_each_entry(rdev, head, node) {
+ if (!strcmp(rdev->id_table->name, id_table->name)) {
+ pr_err("Ignoring duplicate request [%d] %s\n",
+ rdev->id_table->protocol_id,
+ rdev->id_table->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+ }
+
+ /*
+ * No duplicate found for requested id_table, so let's create a new
+ * requested device entry for this new valid request.
+ */
+ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
+ if (!rdev) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ rdev->id_table = id_table;
+
+ /*
+ * Append the new requested device table descriptor to the head of the
+ * related protocol list, eventually creating such head if not already
+ * there.
+ */
+ if (!phead) {
+ phead = kzalloc(sizeof(*phead), GFP_KERNEL);
+ if (!phead) {
+ kfree(rdev);
+ ret = -ENOMEM;
+ goto out;
+ }
+ INIT_LIST_HEAD(phead);
+
+ ret = idr_alloc(&scmi_requested_devices, (void *)phead,
+ id_table->protocol_id,
+ id_table->protocol_id + 1, GFP_KERNEL);
+ if (ret != id_table->protocol_id) {
+ pr_err("Failed to save SCMI device - ret:%d\n", ret);
+ kfree(rdev);
+ kfree(phead);
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = 0;
+ }
+ list_add(&rdev->node, phead);
+
+ /*
+ * Now effectively create and initialize the requested device for every
+ * already initialized SCMI instance which has registered the requested
+ * protocol as a valid active one: i.e. defined in DT and supported by
+ * current platform FW.
+ */
+ mutex_lock(&scmi_list_mutex);
+ list_for_each_entry(info, &scmi_list, node) {
+ struct device_node *child;
+
+ child = idr_find(&info->active_protocols,
+ id_table->protocol_id);
+ if (child) {
+ struct scmi_device *sdev;
+
+ sdev = scmi_get_protocol_device(child, info,
+ id_table->protocol_id,
+ id_table->name);
+ /* Set handle if not already set: device existed */
+ if (sdev && !sdev->handle)
+ sdev->handle =
+ scmi_handle_get_from_info_unlocked(info);
+ } else {
+ dev_err(info->dev,
+ "Failed. SCMI protocol %d not active.\n",
+ id_table->protocol_id);
+ }
+ }
+ mutex_unlock(&scmi_list_mutex);
+
+out:
+ mutex_unlock(&scmi_requested_devices_mtx);

- for (cnt = 0; cnt < ARRAY_SIZE(devnames[loop].names); cnt++) {
- const char *name = devnames[loop].names[cnt];
+ return ret;
+}

- if (name)
- scmi_create_protocol_device(np, info, prot_id,
- name);
+/**
+ * scmi_protocol_device_unrequest - Helper to unrequest a device
+ *
+ * @id_table: A protocol/name pair descriptor for the device to be unrequested.
+ *
+ * An helper to let an SCMI driver release its request about devices; note that
+ * devices are created and initialized once the first SCMI driver request them
+ * but they destroyed only on SCMI core unloading/unbinding.
+ *
+ * The current SCMI transport layer uses such devices as internal references and
+ * as such they could be shared as same transport between multiple drivers so
+ * 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)
+{
+ struct list_head *phead;
+
+ pr_debug("Unrequesting SCMI device (%s) for protocol %x\n",
+ id_table->name, id_table->protocol_id);
+
+ mutex_lock(&scmi_requested_devices_mtx);
+ phead = idr_find(&scmi_requested_devices, id_table->protocol_id);
+ if (phead) {
+ struct scmi_requested_dev *victim, *tmp;
+
+ list_for_each_entry_safe(victim, tmp, phead, node) {
+ if (!strcmp(victim->id_table->name, id_table->name)) {
+ list_del(&victim->node);
+ kfree(victim);
+ break;
+ }
+ }
+
+ if (list_empty(phead)) {
+ idr_remove(&scmi_requested_devices,
+ id_table->protocol_id);
+ kfree(phead);
}
}
+ mutex_unlock(&scmi_requested_devices_mtx);
}

static int scmi_probe(struct platform_device *pdev)
@@ -1181,6 +1404,7 @@ static int scmi_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&info->node);
idr_init(&info->protocols);
mutex_init(&info->protocols_mtx);
+ idr_init(&info->active_protocols);

platform_set_drvdata(pdev, info);
idr_init(&info->tx_idr);
@@ -1233,6 +1457,19 @@ static int scmi_probe(struct platform_device *pdev)
continue;
}

+ /*
+ * Save this valid DT protocol descriptor amongst
+ * @active_protocols for this SCMI instance/
+ */
+ ret = idr_alloc(&info->active_protocols, child,
+ prot_id, prot_id + 1, GFP_KERNEL);
+ if (ret != prot_id) {
+ dev_err(dev, "SCMI protocol %d already activated. Skip\n",
+ prot_id);
+ continue;
+ }
+
+ of_node_get(child);
scmi_create_protocol_devices(child, info, prot_id);
}

@@ -1246,9 +1483,10 @@ void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id)

static int scmi_remove(struct platform_device *pdev)
{
- int ret = 0;
+ int ret = 0, id;
struct scmi_info *info = platform_get_drvdata(pdev);
struct idr *idr = &info->tx_idr;
+ struct device_node *child;

mutex_lock(&scmi_list_mutex);
if (info->users)
@@ -1266,6 +1504,10 @@ static int scmi_remove(struct platform_device *pdev)
idr_destroy(&info->protocols);
mutex_unlock(&info->protocols_mtx);

+ idr_for_each_entry(&info->active_protocols, child, id)
+ of_node_put(child);
+ idr_destroy(&info->active_protocols);
+
/* Safe to free channels since no more users */
ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
idr_destroy(&info->tx_idr);
--
2.17.1

2021-03-16 21:16:50

by Jyoti Bhayana

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

Hi Christian,

Thanks for porting this driver to the new interface. I have two questions:

1) In the following code snippet, can the sensor_ops be made as part
of struct scmi_iio_priv as scmi_protocol_handle is also part of that
struct. Not sure if there are any particular reasons for having the
protocol handle as part of the struct but the sensor_ops as global?

> +static const struct scmi_sensor_proto_ops *sensor_ops;
>+
>.struct scmi_iio_priv {
>- struct scmi_handle *handle;
>+ struct scmi_protocol_handle *ph;
> const struct scmi_sensor_info *sensor_info;
> struct iio_dev *indio_dev;

2) Looks like the event notifier registration is SCMI device managed
and that's why there is no call to unregister. I am assuming that you
have tested the logic of inserting the module, removing it and then
again inserting it to make sure that when the event is registered a
second time , the logic is all good.

> ret = handle->notify_ops->devm_event_notifier_register(sdev,

Thanks,
Jyoti

On Tue, Mar 16, 2021 at 5:50 AM Cristian Marussi
<[email protected]> wrote:
>
> Port driver to the new SCMI Sensor interface based on protocol handles
> and common devm_get_ops().
>
> Cc: Jyoti Bhayana <[email protected]>
> Cc: Jonathan Cameron <[email protected]>
> Signed-off-by: Cristian Marussi <[email protected]>
> ---
> drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++++++++++------------
> 1 file changed, 41 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
> index 872d87ca6256..b4bdc3f3a946 100644
> --- a/drivers/iio/common/scmi_sensors/scmi_iio.c
> +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
> @@ -21,8 +21,10 @@
>
> #define SCMI_IIO_NUM_OF_AXIS 3
>
> +static const struct scmi_sensor_proto_ops *sensor_ops;
> +
> struct scmi_iio_priv {
> - struct scmi_handle *handle;
> + struct scmi_protocol_handle *ph;
> const struct scmi_sensor_info *sensor_info;
> struct iio_dev *indio_dev;
> /* adding one additional channel for timestamp */
> @@ -82,7 +84,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
> static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> {
> struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> - u32 sensor_id = sensor->sensor_info->id;
> u32 sensor_config = 0;
> int err;
>
> @@ -92,27 +93,11 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
>
> sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> SCMI_SENS_CFG_SENSOR_ENABLE);
> -
> - err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
> - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> - &sensor_id, &sensor->sensor_update_nb);
> - if (err) {
> - dev_err(&iio_dev->dev,
> - "Error in registering sensor update notifier for sensor %s err %d",
> - sensor->sensor_info->name, err);
> - return err;
> - }
> -
> - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> - sensor->sensor_info->id, sensor_config);
> - if (err) {
> - sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> - SCMI_PROTOCOL_SENSOR,
> - SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
> - &sensor->sensor_update_nb);
> + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> + sensor_config);
> + if (err)
> dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
> sensor->sensor_info->name, err);
> - }
>
> return err;
> }
> @@ -120,25 +105,13 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
> {
> struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> - u32 sensor_id = sensor->sensor_info->id;
> u32 sensor_config = 0;
> int err;
>
> sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> SCMI_SENS_CFG_SENSOR_DISABLE);
> -
> - err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> - &sensor_id, &sensor->sensor_update_nb);
> - if (err) {
> - dev_err(&iio_dev->dev,
> - "Error in unregistering sensor update notifier for sensor %s err %d",
> - sensor->sensor_info->name, err);
> - return err;
> - }
> -
> - err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
> - sensor_config);
> + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> + sensor_config);
> if (err) {
> dev_err(&iio_dev->dev,
> "Error in disabling sensor %s with err %d",
> @@ -161,8 +134,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> u32 sensor_config;
> char buf[32];
>
> - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> - sensor->sensor_info->id, &sensor_config);
> + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> + &sensor_config);
> if (err) {
> dev_err(&iio_dev->dev,
> "Error in getting sensor config for sensor %s err %d",
> @@ -208,8 +181,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> sensor_config |=
> FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);
>
> - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> - sensor->sensor_info->id, sensor_config);
> + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> + sensor_config);
> if (err)
> dev_err(&iio_dev->dev,
> "Error in setting sensor update interval for sensor %s value %u err %d",
> @@ -274,8 +247,8 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
> u32 sensor_config;
> int mult;
>
> - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> - sensor->sensor_info->id, &sensor_config);
> + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> + &sensor_config);
> if (err) {
> dev_err(&iio_dev->dev,
> "Error in getting sensor config for sensor %s err %d",
> @@ -542,15 +515,17 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
> return 0;
> }
>
> -static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> - struct scmi_handle *handle,
> - const struct scmi_sensor_info *sensor_info)
> +static struct iio_dev *
> +scmi_alloc_iiodev(struct scmi_device *sdev, struct scmi_protocol_handle *ph,
> + const struct scmi_sensor_info *sensor_info)
> {
> struct iio_chan_spec *iio_channels;
> struct scmi_iio_priv *sensor;
> enum iio_modifier modifier;
> enum iio_chan_type type;
> struct iio_dev *iiodev;
> + struct device *dev = &sdev->dev;
> + const struct scmi_handle *handle = sdev->handle;
> int i, ret;
>
> iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
> @@ -560,7 +535,7 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> iiodev->modes = INDIO_DIRECT_MODE;
> iiodev->dev.parent = dev;
> sensor = iio_priv(iiodev);
> - sensor->handle = handle;
> + sensor->ph = ph;
> sensor->sensor_info = sensor_info;
> sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
> sensor->indio_dev = iiodev;
> @@ -595,6 +570,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> sensor_info->axis[i].id);
> }
>
> + ret = handle->notify_ops->devm_event_notifier_register(sdev,
> + SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> + &sensor->sensor_info->id,
> + &sensor->sensor_update_nb);
> + if (ret) {
> + dev_err(&iiodev->dev,
> + "Error in registering sensor update notifier for sensor %s err %d",
> + sensor->sensor_info->name, ret);
> + return ERR_PTR(ret);
> + }
> +
> scmi_iio_set_timestamp_channel(&iio_channels[i], i);
> iiodev->channels = iio_channels;
> return iiodev;
> @@ -604,24 +590,29 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> {
> const struct scmi_sensor_info *sensor_info;
> struct scmi_handle *handle = sdev->handle;
> + struct scmi_protocol_handle *ph;
> struct device *dev = &sdev->dev;
> struct iio_dev *scmi_iio_dev;
> u16 nr_sensors;
> int err = -ENODEV, i;
>
> - if (!handle || !handle->sensor_ops) {
> + if (!handle)
> + return -ENODEV;
> +
> + sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
> + if (IS_ERR(sensor_ops)) {
> dev_err(dev, "SCMI device has no sensor interface\n");
> - return -EINVAL;
> + return PTR_ERR(sensor_ops);
> }
>
> - nr_sensors = handle->sensor_ops->count_get(handle);
> + nr_sensors = sensor_ops->count_get(ph);
> if (!nr_sensors) {
> dev_dbg(dev, "0 sensors found via SCMI bus\n");
> return -ENODEV;
> }
>
> for (i = 0; i < nr_sensors; i++) {
> - sensor_info = handle->sensor_ops->info_get(handle, i);
> + sensor_info = sensor_ops->info_get(ph, i);
> if (!sensor_info) {
> dev_err(dev, "SCMI sensor %d has missing info\n", i);
> return -EINVAL;
> @@ -636,7 +627,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> sensor_info->axis[0].type != RADIANS_SEC)
> continue;
>
> - scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
> + scmi_iio_dev = scmi_alloc_iiodev(sdev, ph, sensor_info);
> if (IS_ERR(scmi_iio_dev)) {
> dev_err(dev,
> "failed to allocate IIO device for sensor %s: %ld\n",
> --
> 2.17.1
>

2021-03-16 22:58:20

by Cristian Marussi

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

Hi Jyoti,

On Tue, Mar 16, 2021 at 10:51:48AM -0700, Jyoti Bhayana wrote:
> Hi Christian,
>
> Thanks for porting this driver to the new interface. I have two questions:
>
> 1) In the following code snippet, can the sensor_ops be made as part
> of struct scmi_iio_priv as scmi_protocol_handle is also part of that
> struct. Not sure if there are any particular reasons for having the
> protocol handle as part of the struct but the sensor_ops as global?
>
> > +static const struct scmi_sensor_proto_ops *sensor_ops;
> >+
> >.struct scmi_iio_priv {
> >- struct scmi_handle *handle;
> >+ struct scmi_protocol_handle *ph;
> > const struct scmi_sensor_info *sensor_info;
> > struct iio_dev *indio_dev;
>

So, the protocol_handle represents a reference to an instance of
the sensor protocol initialized against the specific SCMI platform
instance referred by the handle provided in the probe: so that if you
should have multiple SCMI platforms defined in the DT, this driver
(as all SCMI drivers) would be probed multiple times each time with a
different handle and it would obtain a different protocol_handle each
time it issued a probe() => devm_protocol_get().
For this reason the obtained protocol_handle cannot be kept as a global
and it seemed a good fit to stay in the existent scmi_iio_priv.

On the other side, the sensor_ops are just plain function pointers (as
they were before), so on any possible probe they are returned the same
(for the same proto): it is indeed the specified protocol_handle used
at invocation time that determines against which instance they actually
operates (if multiple instances present at all); so the sensor_ops seemed
a good fit for a global, also because that way tehy are more easily
accessible throughout the driver.

Does it make sense ?

> 2) Looks like the event notifier registration is SCMI device managed
> and that's why there is no call to unregister. I am assuming that you
> have tested the logic of inserting the module, removing it and then
> again inserting it to make sure that when the event is registered a
> second time , the logic is all good.
>
> > ret = handle->notify_ops->devm_event_notifier_register(sdev,
>

Sure, I tested load/unload in general for also other SCMI drivers just
to be sure not to have broken completely the world with this series.

Please find below a load/unload/load sequence for scmi_iio.ko.
(there are 2 emulated sensors, only one is timestamped)

Thanks

Cristian

---

(debian-arm64)root@debarm64:~# ls /sys/bus/iio/devices/
(debian-arm64)root@debarm64:~# insmod ./scmi_iio.ko
(debian-arm64)root@debarm64:~# ls /sys/bus/iio/devices/
iio:device0 iio:device1
(debian-arm64)root@debarm64:~# cat /sys/bus/iio/devices/iio\:device0/name
emu8_accel
(debian-arm64)root@debarm64:~# cat /sys/bus/iio/devices/iio\:device1/name
emu9_gyro
(debian-arm64)root@debarm64:~# /root/iio_generic_buffer -a -c -1 -g -l 100 -N 0
iio device number being used is 0
trigger-less mode selected
Enabling all channels
Enabling: in_accel_x_en
Enabling: in_accel_z_en
Enabling: in_timestamp_en
Enabling: in_accel_y_en
-7737 -7729 -7721 16725578467193651200.000000
-7736 -7728 -7720 16725578467193651200.000000
-7735 -7727 -7719 16725578467193651200.000000
-7734 -7726 -7718 16725578467193651200.000000
-7733 -7725 -7717 16725578467193651200.000000
-7732 -7724 -7716 16725578467193651200.000000
-7731 -7723 -7715 16725578467193651200.000000
-7730 -7722 -7714 17725578795097784320.000000
-7729 -7721 -7713 17725578795097784320.000000
-7728 -7720 -7712 17725578795097784320.000000
-7727 -7719 -7711 17725578795097784320.000000
-7726 -7718 -7710 17725578795097784320.000000
-7725 -7717 -7709 17725578795097784320.000000
-7724 -7716 -7708 17725578795097784320.000000
-7723 -7715 -7707 17725578795097784320.000000
-7722 -7714 -7706 17725578795097784320.000000
-7721 -7713 -7705 17725578795097784320.000000
^CCaught signal 2
Disabling: in_accel_x_en
Disabling: in_accel_z_en
Disabling: in_timestamp_en
Disabling: in_accel_y_en
(debian-arm64)root@debarm64:~# /root/iio_generic_buffer -a -c -1 -g -l 100 -N 1
iio device number being used is 1
trigger-less mode selected
Enabling all channels
Enabling: in_accel_x_en
Enabling: in_accel_z_en
Enabling: in_timestamp_en
Enabling: in_accel_y_en
-3583 -3574 -3565 270679244800.000000
-3582 -3573 -3564 270780203008.000000
-3581 -3572 -3563 270880358400.000000
-3580 -3571 -3562 270980431872.000000
-3579 -3570 -3561 271080521728.000000
-3578 -3569 -3560 271180611584.000000
-3577 -3568 -3559 271280685056.000000
-3576 -3567 -3558 271380774912.000000
-3575 -3566 -3557 271480848384.000000
-3574 -3565 -3556 271580938240.000000
-3573 -3564 -3555 271681028096.000000
-3572 -3563 -3554 271781101568.000000
-3571 -3562 -3553 271881191424.000000
-3570 -3561 -3552 271981264896.000000
-3569 -3560 -3551 272081354752.000000
^CCaught signal 2
Disabling: in_accel_x_en
Disabling: in_accel_z_en
Disabling: in_timestamp_en
Disabling: in_accel_y_en
(debian-arm64)root@debarm64:~#
(debian-arm64)root@debarm64:~# rmmod ./scmi_iio.ko
(debian-arm64)root@debarm64:~# ls /sys/bus/iio/devices/
(debian-arm64)root@debarm64:~# insmod ./scmi_iio.ko
(debian-arm64)root@debarm64:~# ls /sys/bus/iio/devices/
iio:device0 iio:device1
(debian-arm64)root@debarm64:~# /root/iio_generic_buffer -a -c -1 -g -l 100 -N 0
iio device number being used is 0
trigger-less mode selected
Enabling all channels
Enabling: in_accel_x_en
Enabling: in_accel_z_en
Enabling: in_timestamp_en
Enabling: in_accel_y_en
-7308 -7300 -7292 4385346052291559424.000000
-7307 -7299 -7291 4385346052291559424.000000
-7306 -7298 -7290 4385346052291559424.000000
-7305 -7297 -7289 4385346052291559424.000000
-7304 -7296 -7288 4385346052291559424.000000
-7303 -7295 -7287 4385346052291559424.000000
-7302 -7294 -7286 4385346052291559424.000000
-7301 -7293 -7285 5385346380195692544.000000
-7300 -7292 -7284 5385346380195692544.000000
-7299 -7291 -7283 5385346380195692544.000000
-7298 -7290 -7282 5385346380195692544.000000
-7297 -7289 -7281 5385346380195692544.000000
-7296 -7288 -7280 5385346380195692544.000000
^CCaught signal 2
Disabling: in_accel_x_en
Disabling: in_accel_z_en
Disabling: in_timestamp_en
Disabling: in_accel_y_en
(debian-arm64)root@debarm64:~# /root/iio_generic_buffer -a -c -1 -g -l 100 -N 1
iio device number being used is 1
trigger-less mode selected
Enabling all channels
Enabling: in_accel_x_en
Enabling: in_accel_z_en
Enabling: in_timestamp_en
Enabling: in_accel_y_en
-3161 -3152 -3143 312944197632.000000
-3160 -3151 -3142 313044303872.000000
-3159 -3150 -3141 313144377344.000000
-3158 -3149 -3140 313244483584.000000
-3157 -3148 -3139 313344851968.000000
-3156 -3147 -3138 313445023744.000000
-3155 -3146 -3137 313545097216.000000
-3154 -3145 -3136 313645465600.000000
-3153 -3144 -3135 313745604608.000000
-3152 -3143 -3134 313845710848.000000
-3151 -3142 -3133 313945784320.000000
-3150 -3141 -3132 314045890560.000000
-3149 -3140 -3131 314145964032.000000
-3148 -3139 -3130 314246070272.000000
-3147 -3138 -3129 314346143744.000000
-3146 -3137 -3128 314446249984.000000
-3145 -3136 -3127 314546618368.000000
-3144 -3135 -3126 314647052288.000000
^CCaught signal 2
Disabling: in_accel_x_en
Disabling: in_accel_z_en
Disabling: in_timestamp_en
Disabling: in_accel_y_en

> Thanks,
> Jyoti
>
> On Tue, Mar 16, 2021 at 5:50 AM Cristian Marussi
> <[email protected]> wrote:
> >
> > Port driver to the new SCMI Sensor interface based on protocol handles
> > and common devm_get_ops().
> >
> > Cc: Jyoti Bhayana <[email protected]>
> > Cc: Jonathan Cameron <[email protected]>
> > Signed-off-by: Cristian Marussi <[email protected]>
> > ---
> > drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++++++++++------------
> > 1 file changed, 41 insertions(+), 50 deletions(-)
> >
> > diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > index 872d87ca6256..b4bdc3f3a946 100644
> > --- a/drivers/iio/common/scmi_sensors/scmi_iio.c
> > +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > @@ -21,8 +21,10 @@
> >
> > #define SCMI_IIO_NUM_OF_AXIS 3
> >
> > +static const struct scmi_sensor_proto_ops *sensor_ops;
> > +
> > struct scmi_iio_priv {
> > - struct scmi_handle *handle;
> > + struct scmi_protocol_handle *ph;
> > const struct scmi_sensor_info *sensor_info;
> > struct iio_dev *indio_dev;
> > /* adding one additional channel for timestamp */
> > @@ -82,7 +84,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
> > static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > {
> > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > - u32 sensor_id = sensor->sensor_info->id;
> > u32 sensor_config = 0;
> > int err;
> >
> > @@ -92,27 +93,11 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> >
> > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > SCMI_SENS_CFG_SENSOR_ENABLE);
> > -
> > - err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
> > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > - &sensor_id, &sensor->sensor_update_nb);
> > - if (err) {
> > - dev_err(&iio_dev->dev,
> > - "Error in registering sensor update notifier for sensor %s err %d",
> > - sensor->sensor_info->name, err);
> > - return err;
> > - }
> > -
> > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > - sensor->sensor_info->id, sensor_config);
> > - if (err) {
> > - sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > - SCMI_PROTOCOL_SENSOR,
> > - SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
> > - &sensor->sensor_update_nb);
> > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > + sensor_config);
> > + if (err)
> > dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
> > sensor->sensor_info->name, err);
> > - }
> >
> > return err;
> > }
> > @@ -120,25 +105,13 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
> > {
> > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > - u32 sensor_id = sensor->sensor_info->id;
> > u32 sensor_config = 0;
> > int err;
> >
> > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > SCMI_SENS_CFG_SENSOR_DISABLE);
> > -
> > - err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > - &sensor_id, &sensor->sensor_update_nb);
> > - if (err) {
> > - dev_err(&iio_dev->dev,
> > - "Error in unregistering sensor update notifier for sensor %s err %d",
> > - sensor->sensor_info->name, err);
> > - return err;
> > - }
> > -
> > - err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
> > - sensor_config);
> > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > + sensor_config);
> > if (err) {
> > dev_err(&iio_dev->dev,
> > "Error in disabling sensor %s with err %d",
> > @@ -161,8 +134,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > u32 sensor_config;
> > char buf[32];
> >
> > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > - sensor->sensor_info->id, &sensor_config);
> > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > + &sensor_config);
> > if (err) {
> > dev_err(&iio_dev->dev,
> > "Error in getting sensor config for sensor %s err %d",
> > @@ -208,8 +181,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > sensor_config |=
> > FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);
> >
> > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > - sensor->sensor_info->id, sensor_config);
> > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > + sensor_config);
> > if (err)
> > dev_err(&iio_dev->dev,
> > "Error in setting sensor update interval for sensor %s value %u err %d",
> > @@ -274,8 +247,8 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
> > u32 sensor_config;
> > int mult;
> >
> > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > - sensor->sensor_info->id, &sensor_config);
> > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > + &sensor_config);
> > if (err) {
> > dev_err(&iio_dev->dev,
> > "Error in getting sensor config for sensor %s err %d",
> > @@ -542,15 +515,17 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
> > return 0;
> > }
> >
> > -static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > - struct scmi_handle *handle,
> > - const struct scmi_sensor_info *sensor_info)
> > +static struct iio_dev *
> > +scmi_alloc_iiodev(struct scmi_device *sdev, struct scmi_protocol_handle *ph,
> > + const struct scmi_sensor_info *sensor_info)
> > {
> > struct iio_chan_spec *iio_channels;
> > struct scmi_iio_priv *sensor;
> > enum iio_modifier modifier;
> > enum iio_chan_type type;
> > struct iio_dev *iiodev;
> > + struct device *dev = &sdev->dev;
> > + const struct scmi_handle *handle = sdev->handle;
> > int i, ret;
> >
> > iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
> > @@ -560,7 +535,7 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > iiodev->modes = INDIO_DIRECT_MODE;
> > iiodev->dev.parent = dev;
> > sensor = iio_priv(iiodev);
> > - sensor->handle = handle;
> > + sensor->ph = ph;
> > sensor->sensor_info = sensor_info;
> > sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
> > sensor->indio_dev = iiodev;
> > @@ -595,6 +570,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > sensor_info->axis[i].id);
> > }
> >
> > + ret = handle->notify_ops->devm_event_notifier_register(sdev,
> > + SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > + &sensor->sensor_info->id,
> > + &sensor->sensor_update_nb);
> > + if (ret) {
> > + dev_err(&iiodev->dev,
> > + "Error in registering sensor update notifier for sensor %s err %d",
> > + sensor->sensor_info->name, ret);
> > + return ERR_PTR(ret);
> > + }
> > +
> > scmi_iio_set_timestamp_channel(&iio_channels[i], i);
> > iiodev->channels = iio_channels;
> > return iiodev;
> > @@ -604,24 +590,29 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > {
> > const struct scmi_sensor_info *sensor_info;
> > struct scmi_handle *handle = sdev->handle;
> > + struct scmi_protocol_handle *ph;
> > struct device *dev = &sdev->dev;
> > struct iio_dev *scmi_iio_dev;
> > u16 nr_sensors;
> > int err = -ENODEV, i;
> >
> > - if (!handle || !handle->sensor_ops) {
> > + if (!handle)
> > + return -ENODEV;
> > +
> > + sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
> > + if (IS_ERR(sensor_ops)) {
> > dev_err(dev, "SCMI device has no sensor interface\n");
> > - return -EINVAL;
> > + return PTR_ERR(sensor_ops);
> > }
> >
> > - nr_sensors = handle->sensor_ops->count_get(handle);
> > + nr_sensors = sensor_ops->count_get(ph);
> > if (!nr_sensors) {
> > dev_dbg(dev, "0 sensors found via SCMI bus\n");
> > return -ENODEV;
> > }
> >
> > for (i = 0; i < nr_sensors; i++) {
> > - sensor_info = handle->sensor_ops->info_get(handle, i);
> > + sensor_info = sensor_ops->info_get(ph, i);
> > if (!sensor_info) {
> > dev_err(dev, "SCMI sensor %d has missing info\n", i);
> > return -EINVAL;
> > @@ -636,7 +627,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > sensor_info->axis[0].type != RADIANS_SEC)
> > continue;
> >
> > - scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
> > + scmi_iio_dev = scmi_alloc_iiodev(sdev, ph, sensor_info);
> > if (IS_ERR(scmi_iio_dev)) {
> > dev_err(dev,
> > "failed to allocate IIO device for sensor %s: %ld\n",
> > --
> > 2.17.1
> >

2021-03-17 05:42:20

by Jyoti Bhayana

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

Hi Christian,

Thanks for the detailed explanation. Sounds good to me.

Thanks,
Jyoti

On Tue, Mar 16, 2021 at 3:22 PM Cristian Marussi
<[email protected]> wrote:
>
> Hi Jyoti,
>
> On Tue, Mar 16, 2021 at 10:51:48AM -0700, Jyoti Bhayana wrote:
> > Hi Christian,
> >
> > Thanks for porting this driver to the new interface. I have two questions:
> >
> > 1) In the following code snippet, can the sensor_ops be made as part
> > of struct scmi_iio_priv as scmi_protocol_handle is also part of that
> > struct. Not sure if there are any particular reasons for having the
> > protocol handle as part of the struct but the sensor_ops as global?
> >
> > > +static const struct scmi_sensor_proto_ops *sensor_ops;
> > >+
> > >.struct scmi_iio_priv {
> > >- struct scmi_handle *handle;
> > >+ struct scmi_protocol_handle *ph;
> > > const struct scmi_sensor_info *sensor_info;
> > > struct iio_dev *indio_dev;
> >
>
> So, the protocol_handle represents a reference to an instance of
> the sensor protocol initialized against the specific SCMI platform
> instance referred by the handle provided in the probe: so that if you
> should have multiple SCMI platforms defined in the DT, this driver
> (as all SCMI drivers) would be probed multiple times each time with a
> different handle and it would obtain a different protocol_handle each
> time it issued a probe() => devm_protocol_get().
> For this reason the obtained protocol_handle cannot be kept as a global
> and it seemed a good fit to stay in the existent scmi_iio_priv.
>
> On the other side, the sensor_ops are just plain function pointers (as
> they were before), so on any possible probe they are returned the same
> (for the same proto): it is indeed the specified protocol_handle used
> at invocation time that determines against which instance they actually
> operates (if multiple instances present at all); so the sensor_ops seemed
> a good fit for a global, also because that way tehy are more easily
> accessible throughout the driver.
>
> Does it make sense ?
>
> > 2) Looks like the event notifier registration is SCMI device managed
> > and that's why there is no call to unregister. I am assuming that you
> > have tested the logic of inserting the module, removing it and then
> > again inserting it to make sure that when the event is registered a
> > second time , the logic is all good.
> >
> > > ret = handle->notify_ops->devm_event_notifier_register(sdev,
> >
>
> Sure, I tested load/unload in general for also other SCMI drivers just
> to be sure not to have broken completely the world with this series.
>
> Please find below a load/unload/load sequence for scmi_iio.ko.
> (there are 2 emulated sensors, only one is timestamped)
>
> Thanks
>
> Cristian
>
> ---
>
> (debian-arm64)root@debarm64:~# ls /sys/bus/iio/devices/
> (debian-arm64)root@debarm64:~# insmod ./scmi_iio.ko
> (debian-arm64)root@debarm64:~# ls /sys/bus/iio/devices/
> iio:device0 iio:device1
> (debian-arm64)root@debarm64:~# cat /sys/bus/iio/devices/iio\:device0/name
> emu8_accel
> (debian-arm64)root@debarm64:~# cat /sys/bus/iio/devices/iio\:device1/name
> emu9_gyro
> (debian-arm64)root@debarm64:~# /root/iio_generic_buffer -a -c -1 -g -l 100 -N 0
> iio device number being used is 0
> trigger-less mode selected
> Enabling all channels
> Enabling: in_accel_x_en
> Enabling: in_accel_z_en
> Enabling: in_timestamp_en
> Enabling: in_accel_y_en
> -7737 -7729 -7721 16725578467193651200.000000
> -7736 -7728 -7720 16725578467193651200.000000
> -7735 -7727 -7719 16725578467193651200.000000
> -7734 -7726 -7718 16725578467193651200.000000
> -7733 -7725 -7717 16725578467193651200.000000
> -7732 -7724 -7716 16725578467193651200.000000
> -7731 -7723 -7715 16725578467193651200.000000
> -7730 -7722 -7714 17725578795097784320.000000
> -7729 -7721 -7713 17725578795097784320.000000
> -7728 -7720 -7712 17725578795097784320.000000
> -7727 -7719 -7711 17725578795097784320.000000
> -7726 -7718 -7710 17725578795097784320.000000
> -7725 -7717 -7709 17725578795097784320.000000
> -7724 -7716 -7708 17725578795097784320.000000
> -7723 -7715 -7707 17725578795097784320.000000
> -7722 -7714 -7706 17725578795097784320.000000
> -7721 -7713 -7705 17725578795097784320.000000
> ^CCaught signal 2
> Disabling: in_accel_x_en
> Disabling: in_accel_z_en
> Disabling: in_timestamp_en
> Disabling: in_accel_y_en
> (debian-arm64)root@debarm64:~# /root/iio_generic_buffer -a -c -1 -g -l 100 -N 1
> iio device number being used is 1
> trigger-less mode selected
> Enabling all channels
> Enabling: in_accel_x_en
> Enabling: in_accel_z_en
> Enabling: in_timestamp_en
> Enabling: in_accel_y_en
> -3583 -3574 -3565 270679244800.000000
> -3582 -3573 -3564 270780203008.000000
> -3581 -3572 -3563 270880358400.000000
> -3580 -3571 -3562 270980431872.000000
> -3579 -3570 -3561 271080521728.000000
> -3578 -3569 -3560 271180611584.000000
> -3577 -3568 -3559 271280685056.000000
> -3576 -3567 -3558 271380774912.000000
> -3575 -3566 -3557 271480848384.000000
> -3574 -3565 -3556 271580938240.000000
> -3573 -3564 -3555 271681028096.000000
> -3572 -3563 -3554 271781101568.000000
> -3571 -3562 -3553 271881191424.000000
> -3570 -3561 -3552 271981264896.000000
> -3569 -3560 -3551 272081354752.000000
> ^CCaught signal 2
> Disabling: in_accel_x_en
> Disabling: in_accel_z_en
> Disabling: in_timestamp_en
> Disabling: in_accel_y_en
> (debian-arm64)root@debarm64:~#
> (debian-arm64)root@debarm64:~# rmmod ./scmi_iio.ko
> (debian-arm64)root@debarm64:~# ls /sys/bus/iio/devices/
> (debian-arm64)root@debarm64:~# insmod ./scmi_iio.ko
> (debian-arm64)root@debarm64:~# ls /sys/bus/iio/devices/
> iio:device0 iio:device1
> (debian-arm64)root@debarm64:~# /root/iio_generic_buffer -a -c -1 -g -l 100 -N 0
> iio device number being used is 0
> trigger-less mode selected
> Enabling all channels
> Enabling: in_accel_x_en
> Enabling: in_accel_z_en
> Enabling: in_timestamp_en
> Enabling: in_accel_y_en
> -7308 -7300 -7292 4385346052291559424.000000
> -7307 -7299 -7291 4385346052291559424.000000
> -7306 -7298 -7290 4385346052291559424.000000
> -7305 -7297 -7289 4385346052291559424.000000
> -7304 -7296 -7288 4385346052291559424.000000
> -7303 -7295 -7287 4385346052291559424.000000
> -7302 -7294 -7286 4385346052291559424.000000
> -7301 -7293 -7285 5385346380195692544.000000
> -7300 -7292 -7284 5385346380195692544.000000
> -7299 -7291 -7283 5385346380195692544.000000
> -7298 -7290 -7282 5385346380195692544.000000
> -7297 -7289 -7281 5385346380195692544.000000
> -7296 -7288 -7280 5385346380195692544.000000
> ^CCaught signal 2
> Disabling: in_accel_x_en
> Disabling: in_accel_z_en
> Disabling: in_timestamp_en
> Disabling: in_accel_y_en
> (debian-arm64)root@debarm64:~# /root/iio_generic_buffer -a -c -1 -g -l 100 -N 1
> iio device number being used is 1
> trigger-less mode selected
> Enabling all channels
> Enabling: in_accel_x_en
> Enabling: in_accel_z_en
> Enabling: in_timestamp_en
> Enabling: in_accel_y_en
> -3161 -3152 -3143 312944197632.000000
> -3160 -3151 -3142 313044303872.000000
> -3159 -3150 -3141 313144377344.000000
> -3158 -3149 -3140 313244483584.000000
> -3157 -3148 -3139 313344851968.000000
> -3156 -3147 -3138 313445023744.000000
> -3155 -3146 -3137 313545097216.000000
> -3154 -3145 -3136 313645465600.000000
> -3153 -3144 -3135 313745604608.000000
> -3152 -3143 -3134 313845710848.000000
> -3151 -3142 -3133 313945784320.000000
> -3150 -3141 -3132 314045890560.000000
> -3149 -3140 -3131 314145964032.000000
> -3148 -3139 -3130 314246070272.000000
> -3147 -3138 -3129 314346143744.000000
> -3146 -3137 -3128 314446249984.000000
> -3145 -3136 -3127 314546618368.000000
> -3144 -3135 -3126 314647052288.000000
> ^CCaught signal 2
> Disabling: in_accel_x_en
> Disabling: in_accel_z_en
> Disabling: in_timestamp_en
> Disabling: in_accel_y_en
>
> > Thanks,
> > Jyoti
> >
> > On Tue, Mar 16, 2021 at 5:50 AM Cristian Marussi
> > <[email protected]> wrote:
> > >
> > > Port driver to the new SCMI Sensor interface based on protocol handles
> > > and common devm_get_ops().
> > >
> > > Cc: Jyoti Bhayana <[email protected]>
> > > Cc: Jonathan Cameron <[email protected]>
> > > Signed-off-by: Cristian Marussi <[email protected]>
> > > ---
> > > drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++++++++++------------
> > > 1 file changed, 41 insertions(+), 50 deletions(-)
> > >
> > > diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > index 872d87ca6256..b4bdc3f3a946 100644
> > > --- a/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > @@ -21,8 +21,10 @@
> > >
> > > #define SCMI_IIO_NUM_OF_AXIS 3
> > >
> > > +static const struct scmi_sensor_proto_ops *sensor_ops;
> > > +
> > > struct scmi_iio_priv {
> > > - struct scmi_handle *handle;
> > > + struct scmi_protocol_handle *ph;
> > > const struct scmi_sensor_info *sensor_info;
> > > struct iio_dev *indio_dev;
> > > /* adding one additional channel for timestamp */
> > > @@ -82,7 +84,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
> > > static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > {
> > > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > > - u32 sensor_id = sensor->sensor_info->id;
> > > u32 sensor_config = 0;
> > > int err;
> > >
> > > @@ -92,27 +93,11 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > >
> > > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > > SCMI_SENS_CFG_SENSOR_ENABLE);
> > > -
> > > - err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
> > > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > - &sensor_id, &sensor->sensor_update_nb);
> > > - if (err) {
> > > - dev_err(&iio_dev->dev,
> > > - "Error in registering sensor update notifier for sensor %s err %d",
> > > - sensor->sensor_info->name, err);
> > > - return err;
> > > - }
> > > -
> > > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > > - sensor->sensor_info->id, sensor_config);
> > > - if (err) {
> > > - sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > > - SCMI_PROTOCOL_SENSOR,
> > > - SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
> > > - &sensor->sensor_update_nb);
> > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > + sensor_config);
> > > + if (err)
> > > dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
> > > sensor->sensor_info->name, err);
> > > - }
> > >
> > > return err;
> > > }
> > > @@ -120,25 +105,13 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
> > > {
> > > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > > - u32 sensor_id = sensor->sensor_info->id;
> > > u32 sensor_config = 0;
> > > int err;
> > >
> > > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > > SCMI_SENS_CFG_SENSOR_DISABLE);
> > > -
> > > - err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > - &sensor_id, &sensor->sensor_update_nb);
> > > - if (err) {
> > > - dev_err(&iio_dev->dev,
> > > - "Error in unregistering sensor update notifier for sensor %s err %d",
> > > - sensor->sensor_info->name, err);
> > > - return err;
> > > - }
> > > -
> > > - err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
> > > - sensor_config);
> > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > + sensor_config);
> > > if (err) {
> > > dev_err(&iio_dev->dev,
> > > "Error in disabling sensor %s with err %d",
> > > @@ -161,8 +134,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > > u32 sensor_config;
> > > char buf[32];
> > >
> > > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > > - sensor->sensor_info->id, &sensor_config);
> > > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > > + &sensor_config);
> > > if (err) {
> > > dev_err(&iio_dev->dev,
> > > "Error in getting sensor config for sensor %s err %d",
> > > @@ -208,8 +181,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > > sensor_config |=
> > > FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);
> > >
> > > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > > - sensor->sensor_info->id, sensor_config);
> > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > + sensor_config);
> > > if (err)
> > > dev_err(&iio_dev->dev,
> > > "Error in setting sensor update interval for sensor %s value %u err %d",
> > > @@ -274,8 +247,8 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
> > > u32 sensor_config;
> > > int mult;
> > >
> > > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > > - sensor->sensor_info->id, &sensor_config);
> > > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > > + &sensor_config);
> > > if (err) {
> > > dev_err(&iio_dev->dev,
> > > "Error in getting sensor config for sensor %s err %d",
> > > @@ -542,15 +515,17 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
> > > return 0;
> > > }
> > >
> > > -static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > - struct scmi_handle *handle,
> > > - const struct scmi_sensor_info *sensor_info)
> > > +static struct iio_dev *
> > > +scmi_alloc_iiodev(struct scmi_device *sdev, struct scmi_protocol_handle *ph,
> > > + const struct scmi_sensor_info *sensor_info)
> > > {
> > > struct iio_chan_spec *iio_channels;
> > > struct scmi_iio_priv *sensor;
> > > enum iio_modifier modifier;
> > > enum iio_chan_type type;
> > > struct iio_dev *iiodev;
> > > + struct device *dev = &sdev->dev;
> > > + const struct scmi_handle *handle = sdev->handle;
> > > int i, ret;
> > >
> > > iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
> > > @@ -560,7 +535,7 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > iiodev->modes = INDIO_DIRECT_MODE;
> > > iiodev->dev.parent = dev;
> > > sensor = iio_priv(iiodev);
> > > - sensor->handle = handle;
> > > + sensor->ph = ph;
> > > sensor->sensor_info = sensor_info;
> > > sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
> > > sensor->indio_dev = iiodev;
> > > @@ -595,6 +570,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > sensor_info->axis[i].id);
> > > }
> > >
> > > + ret = handle->notify_ops->devm_event_notifier_register(sdev,
> > > + SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > + &sensor->sensor_info->id,
> > > + &sensor->sensor_update_nb);
> > > + if (ret) {
> > > + dev_err(&iiodev->dev,
> > > + "Error in registering sensor update notifier for sensor %s err %d",
> > > + sensor->sensor_info->name, ret);
> > > + return ERR_PTR(ret);
> > > + }
> > > +
> > > scmi_iio_set_timestamp_channel(&iio_channels[i], i);
> > > iiodev->channels = iio_channels;
> > > return iiodev;
> > > @@ -604,24 +590,29 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > > {
> > > const struct scmi_sensor_info *sensor_info;
> > > struct scmi_handle *handle = sdev->handle;
> > > + struct scmi_protocol_handle *ph;
> > > struct device *dev = &sdev->dev;
> > > struct iio_dev *scmi_iio_dev;
> > > u16 nr_sensors;
> > > int err = -ENODEV, i;
> > >
> > > - if (!handle || !handle->sensor_ops) {
> > > + if (!handle)
> > > + return -ENODEV;
> > > +
> > > + sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
> > > + if (IS_ERR(sensor_ops)) {
> > > dev_err(dev, "SCMI device has no sensor interface\n");
> > > - return -EINVAL;
> > > + return PTR_ERR(sensor_ops);
> > > }
> > >
> > > - nr_sensors = handle->sensor_ops->count_get(handle);
> > > + nr_sensors = sensor_ops->count_get(ph);
> > > if (!nr_sensors) {
> > > dev_dbg(dev, "0 sensors found via SCMI bus\n");
> > > return -ENODEV;
> > > }
> > >
> > > for (i = 0; i < nr_sensors; i++) {
> > > - sensor_info = handle->sensor_ops->info_get(handle, i);
> > > + sensor_info = sensor_ops->info_get(ph, i);
> > > if (!sensor_info) {
> > > dev_err(dev, "SCMI sensor %d has missing info\n", i);
> > > return -EINVAL;
> > > @@ -636,7 +627,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > > sensor_info->axis[0].type != RADIANS_SEC)
> > > continue;
> > >
> > > - scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
> > > + scmi_iio_dev = scmi_alloc_iiodev(sdev, ph, sensor_info);
> > > if (IS_ERR(scmi_iio_dev)) {
> > > dev_err(dev,
> > > "failed to allocate IIO device for sensor %s: %ld\n",
> > > --
> > > 2.17.1
> > >

2021-03-18 12:14:01

by Sudeep Holla

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

On Tue, Mar 16, 2021 at 10:38:43PM -0700, Jyoti Bhayana wrote:
> Hi Christian,
>
> Thanks for the detailed explanation. Sounds good to me.
>

Can I get official Reviewed-by or Acked-by please if you are fine with the
change ?

I definitely need one from Jonathan to merge this and one from Jyoti is
added bonus ????.

--
Regards,
Sudeep

2021-03-19 17:05:19

by Jyoti Bhayana

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

iio/scmi: port driver to the new scmi_sensor_proto_ops interface

Port driver to the new SCMI Sensor interface based on protocol handles
and common devm_get_ops().

Cc: Jyoti Bhayana <[email protected]>
Cc: Jonathan Cameron <[email protected]>
Acked-by: Jyoti Bhayana <[email protected]>
Signed-off-by: Cristian Marussi <[email protected]>



On Thu, Mar 18, 2021 at 5:12 AM Sudeep Holla <[email protected]> wrote:
>
> On Tue, Mar 16, 2021 at 10:38:43PM -0700, Jyoti Bhayana wrote:
> > Hi Christian,
> >
> > Thanks for the detailed explanation. Sounds good to me.
> >
>
> Can I get official Reviewed-by or Acked-by please if you are fine with the
> change ?
>
> I definitely need one from Jonathan to merge this and one from Jyoti is
> added bonus .
>
> --
> Regards,
> Sudeep

2021-03-23 09:52:24

by Sudeep Holla

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

Hi Jonathan,

On Thu, Mar 18, 2021 at 12:12:02PM +0000, Sudeep Holla wrote:
> On Tue, Mar 16, 2021 at 10:38:43PM -0700, Jyoti Bhayana wrote:
> > Hi Christian,
> >
> > Thanks for the detailed explanation. Sounds good to me.
> >
>
> Can I get official Reviewed-by or Acked-by please if you are fine with the
> change ?
>

I need your ack to this via arm-soc.

--
Regards,
Sudeep

2021-03-26 04:14:51

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH v7 00/38] SCMI vendor protocols and modularization



On 3/16/2021 5:48 AM, Cristian Marussi wrote:
> Hi all,
>
> The current SCMI implementation does not provide an interface to easily
> develop and include a custom vendor protocol implementation as prescribed
> by the SCMI standard, also because, there is not currently any custom
> protocol in the upstream to justify the development of a custom interface
> and its maintenance.
>
> Moreover the current interface exposes protocol operations to the SCMI
> driver users attaching per-protocol operations directly to the handle
> structure, which, in this way, tends to grow indefinitely for each new
> protocol addition.
>
> Beside this, protocols private data are also exposed via handle *_priv
> pointers, making such private data accessible also to the SCMI drivers
> even if neither really needed nor advisable.
>
> This series wants to address this by simplifying the SCMI protocols
> interface and reducing it, roughly, to these common generic operations:
>
> - handle->devm_protocol_get()
> - handle->devm_protocol_put()
> - handle->notify_ops->*
>
> All protocols' private data pointers are removed from handle too and made
> accessible only to the protocols code through dedicated internal helpers.
>
> The concept of protocol handle is also introduced in the SCMI protocol code
> to represent a protocol instance initialized against a specific SCMI
> instance (handle), so that all the new protocol code uses such protocol
> handles wherever previously SCMI handle was used: this enable tighter
> control of what is exposed to the protocol code vs the SCMI drivers.
>
> Moreover protocol initialization is moved away from device probe and now
> happens on demand when the first user shows up (first .protocol_get), while
> de-initialization is performed once the last user of the protocol, even in
> terms of registered notifications callback, is gone, with the SCMI core
> taking care to perform all the needed underlying resource accounting.
>
> This way any new future standard or custom protocol implementation will
> expose a common unified interface which does not need to be extended
> endlessly: no need to maintain a custom interface only for vendor protos.
> SCMI drivers written on top of standard or custom protocols will use this
> same common interface to access any protocol operations.
>
> All existent upstream SCMI drivers are converted to this new interface.
>
> In order to make this migration painless and to avoid the need of a big
> un-mergeable jumbo patch touching all over the protocols and drivers (like
> it was in v2), since v3 the migration process has been heavily split with a
> bit of transient code added along the way (to preserve bisectability) and
> finally removed towards the ends of the series.
> Protocols and SCMI drivers migration to the new interface happens along
> patches 10->30.
>
> Leveraging this new centralized and common initialization flow we took
> care also to refactor and simplify protocol-events registration and remove
> *notify_priv from the handle interface making it accessible only to the
> notification core.
>
> Patch 37 builds on top of this new interface and introduces a mechanism to
> define an SCMI protocol as a full blown module (possibly loadable) while
> leaving the core dealing with proper resource accounting.
> Standard protocols are still kept as builtins in this series, though.
>
> Finally, patch 38 introduces dynamic SCMI devices creation to avoid having
> to update the static module device table in the core each time a new driver
> is added.
>
> The whole SCMI stack can still be built alternatively as a module, with all
> the standard protocols included in scmi-module.ko in such a case.
>
> On top of this series an example SCMI Custom protocol 0x99 and related
> SCMI Custom Dummy driver has been built and it is available at [1] as a
> series of DEBUG patches on top this same series.
>
> The series is currently based on sudeep/for-next/scmi [2] on top of:
>
> commit 908a4f778dc7 ("Merge branch 'ib-iio-scmi-5.12-rc2-take3' of
> git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into
> for-next/scmi")
>
> Any feedback welcome.

You copied me on each round and thanks for doing that, I did not have
time to go look at each change, but sensors, clocks and cpufreq still
worked on ARCH_BRCMSTB with both 32-bit and 64-bit kernels, so:

Tested-by: Florian Fainelli <[email protected]>

Thanks!
--
Florian

2021-03-26 11:06:47

by Cristian Marussi

[permalink] [raw]
Subject: Re: [PATCH v7 00/38] SCMI vendor protocols and modularization

On Thu, Mar 25, 2021 at 09:09:52PM -0700, Florian Fainelli wrote:
>
>
> On 3/16/2021 5:48 AM, Cristian Marussi wrote:
> > Hi all,
> >
> > The current SCMI implementation does not provide an interface to easily
> > develop and include a custom vendor protocol implementation as prescribed
> > by the SCMI standard, also because, there is not currently any custom
> > protocol in the upstream to justify the development of a custom interface
> > and its maintenance.
> >
> > Moreover the current interface exposes protocol operations to the SCMI
> > driver users attaching per-protocol operations directly to the handle
> > structure, which, in this way, tends to grow indefinitely for each new
> > protocol addition.
> >
> > Beside this, protocols private data are also exposed via handle *_priv
> > pointers, making such private data accessible also to the SCMI drivers
> > even if neither really needed nor advisable.
> >
> > This series wants to address this by simplifying the SCMI protocols
> > interface and reducing it, roughly, to these common generic operations:
> >
> > - handle->devm_protocol_get()
> > - handle->devm_protocol_put()
> > - handle->notify_ops->*
> >
> > All protocols' private data pointers are removed from handle too and made
> > accessible only to the protocols code through dedicated internal helpers.
> >
> > The concept of protocol handle is also introduced in the SCMI protocol code
> > to represent a protocol instance initialized against a specific SCMI
> > instance (handle), so that all the new protocol code uses such protocol
> > handles wherever previously SCMI handle was used: this enable tighter
> > control of what is exposed to the protocol code vs the SCMI drivers.
> >
> > Moreover protocol initialization is moved away from device probe and now
> > happens on demand when the first user shows up (first .protocol_get), while
> > de-initialization is performed once the last user of the protocol, even in
> > terms of registered notifications callback, is gone, with the SCMI core
> > taking care to perform all the needed underlying resource accounting.
> >
> > This way any new future standard or custom protocol implementation will
> > expose a common unified interface which does not need to be extended
> > endlessly: no need to maintain a custom interface only for vendor protos.
> > SCMI drivers written on top of standard or custom protocols will use this
> > same common interface to access any protocol operations.
> >
> > All existent upstream SCMI drivers are converted to this new interface.
> >
> > In order to make this migration painless and to avoid the need of a big
> > un-mergeable jumbo patch touching all over the protocols and drivers (like
> > it was in v2), since v3 the migration process has been heavily split with a
> > bit of transient code added along the way (to preserve bisectability) and
> > finally removed towards the ends of the series.
> > Protocols and SCMI drivers migration to the new interface happens along
> > patches 10->30.
> >
> > Leveraging this new centralized and common initialization flow we took
> > care also to refactor and simplify protocol-events registration and remove
> > *notify_priv from the handle interface making it accessible only to the
> > notification core.
> >
> > Patch 37 builds on top of this new interface and introduces a mechanism to
> > define an SCMI protocol as a full blown module (possibly loadable) while
> > leaving the core dealing with proper resource accounting.
> > Standard protocols are still kept as builtins in this series, though.
> >
> > Finally, patch 38 introduces dynamic SCMI devices creation to avoid having
> > to update the static module device table in the core each time a new driver
> > is added.
> >
> > The whole SCMI stack can still be built alternatively as a module, with all
> > the standard protocols included in scmi-module.ko in such a case.
> >
> > On top of this series an example SCMI Custom protocol 0x99 and related
> > SCMI Custom Dummy driver has been built and it is available at [1] as a
> > series of DEBUG patches on top this same series.
> >
> > The series is currently based on sudeep/for-next/scmi [2] on top of:
> >
> > commit 908a4f778dc7 ("Merge branch 'ib-iio-scmi-5.12-rc2-take3' of
> > git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into
> > for-next/scmi")
> >
> > Any feedback welcome.
>
> You copied me on each round and thanks for doing that, I did not have
> time to go look at each change, but sensors, clocks and cpufreq still
> worked on ARCH_BRCMSTB with both 32-bit and 64-bit kernels, so:
>
> Tested-by: Florian Fainelli <[email protected]>
>
Great, thanks for taking time to test this !

And btw, thanks for your initial feedback anyway, it spawned a lot of
needed rework across this series.

Thanks

Cristian
> Thanks!
> --
> Florian

2021-03-30 11:27:18

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

On Tue, 23 Mar 2021 09:48:28 +0000
Sudeep Holla <[email protected]> wrote:

> Hi Jonathan,
>
> On Thu, Mar 18, 2021 at 12:12:02PM +0000, Sudeep Holla wrote:
> > On Tue, Mar 16, 2021 at 10:38:43PM -0700, Jyoti Bhayana wrote:
> > > Hi Christian,
> > >
> > > Thanks for the detailed explanation. Sounds good to me.
> > >
> >
> > Can I get official Reviewed-by or Acked-by please if you are fine with the
> > change ?
> >
>
> I need your ack to this via arm-soc.
>
Sorry, missed it until now as wasn't cc'd to [email protected] so
my filters didn't sweep it to the right place and it got lost in the flood.

Will take a look now.

Jonathan

2021-03-30 11:38:21

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

On Tue, 16 Mar 2021 12:48:50 +0000
Cristian Marussi <[email protected]> wrote:

> Port driver to the new SCMI Sensor interface based on protocol handles
> and common devm_get_ops().
>
> Cc: Jyoti Bhayana <[email protected]>
> Cc: Jonathan Cameron <[email protected]>
> Signed-off-by: Cristian Marussi <[email protected]>

+CC [email protected]

Rule of thumb if it doesn't go there it ends up in randomly location based
on other lists and I might not see it for a few weeks :(

> ---
> drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++++++++++------------
> 1 file changed, 41 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
> index 872d87ca6256..b4bdc3f3a946 100644
> --- a/drivers/iio/common/scmi_sensors/scmi_iio.c
> +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
> @@ -21,8 +21,10 @@
>
> #define SCMI_IIO_NUM_OF_AXIS 3
>
> +static const struct scmi_sensor_proto_ops *sensor_ops;

Hmm. I'm not keen on globals when they really should not be necessary.
They just result in lifetimes being out of sync. Here you are fine because
you set it to an appropriate value as the first thing you do in probe, and
I assume the function only ever returns on answer on repeated calls.

Why not put a copy of that pointer inside the struct scmi_iio_priv structures?

Otherwise this all looks like straight forward refactoring so given the
above is more a 'bad smell' than a bug and I'm rather late to the game.

Acked-by: Jonathan Cameron <[email protected]>


> +
> struct scmi_iio_priv {
> - struct scmi_handle *handle;
> + struct scmi_protocol_handle *ph;
> const struct scmi_sensor_info *sensor_info;
> struct iio_dev *indio_dev;
> /* adding one additional channel for timestamp */
> @@ -82,7 +84,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
> static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> {
> struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> - u32 sensor_id = sensor->sensor_info->id;
> u32 sensor_config = 0;
> int err;
>
> @@ -92,27 +93,11 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
>
> sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> SCMI_SENS_CFG_SENSOR_ENABLE);
> -
> - err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
> - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> - &sensor_id, &sensor->sensor_update_nb);
> - if (err) {
> - dev_err(&iio_dev->dev,
> - "Error in registering sensor update notifier for sensor %s err %d",
> - sensor->sensor_info->name, err);
> - return err;
> - }
> -
> - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> - sensor->sensor_info->id, sensor_config);
> - if (err) {
> - sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> - SCMI_PROTOCOL_SENSOR,
> - SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
> - &sensor->sensor_update_nb);
> + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> + sensor_config);
> + if (err)
> dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
> sensor->sensor_info->name, err);
> - }
>
> return err;
> }
> @@ -120,25 +105,13 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
> {
> struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> - u32 sensor_id = sensor->sensor_info->id;
> u32 sensor_config = 0;
> int err;
>
> sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> SCMI_SENS_CFG_SENSOR_DISABLE);
> -
> - err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> - &sensor_id, &sensor->sensor_update_nb);
> - if (err) {
> - dev_err(&iio_dev->dev,
> - "Error in unregistering sensor update notifier for sensor %s err %d",
> - sensor->sensor_info->name, err);
> - return err;
> - }
> -
> - err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
> - sensor_config);
> + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> + sensor_config);
> if (err) {
> dev_err(&iio_dev->dev,
> "Error in disabling sensor %s with err %d",
> @@ -161,8 +134,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> u32 sensor_config;
> char buf[32];
>
> - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> - sensor->sensor_info->id, &sensor_config);
> + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> + &sensor_config);
> if (err) {
> dev_err(&iio_dev->dev,
> "Error in getting sensor config for sensor %s err %d",
> @@ -208,8 +181,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> sensor_config |=
> FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);
>
> - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> - sensor->sensor_info->id, sensor_config);
> + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> + sensor_config);
> if (err)
> dev_err(&iio_dev->dev,
> "Error in setting sensor update interval for sensor %s value %u err %d",
> @@ -274,8 +247,8 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
> u32 sensor_config;
> int mult;
>
> - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> - sensor->sensor_info->id, &sensor_config);
> + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> + &sensor_config);
> if (err) {
> dev_err(&iio_dev->dev,
> "Error in getting sensor config for sensor %s err %d",
> @@ -542,15 +515,17 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
> return 0;
> }
>
> -static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> - struct scmi_handle *handle,
> - const struct scmi_sensor_info *sensor_info)
> +static struct iio_dev *
> +scmi_alloc_iiodev(struct scmi_device *sdev, struct scmi_protocol_handle *ph,
> + const struct scmi_sensor_info *sensor_info)
> {
> struct iio_chan_spec *iio_channels;
> struct scmi_iio_priv *sensor;
> enum iio_modifier modifier;
> enum iio_chan_type type;
> struct iio_dev *iiodev;
> + struct device *dev = &sdev->dev;
> + const struct scmi_handle *handle = sdev->handle;
> int i, ret;
>
> iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
> @@ -560,7 +535,7 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> iiodev->modes = INDIO_DIRECT_MODE;
> iiodev->dev.parent = dev;
> sensor = iio_priv(iiodev);
> - sensor->handle = handle;
> + sensor->ph = ph;
> sensor->sensor_info = sensor_info;
> sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
> sensor->indio_dev = iiodev;
> @@ -595,6 +570,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> sensor_info->axis[i].id);
> }
>
> + ret = handle->notify_ops->devm_event_notifier_register(sdev,
> + SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> + &sensor->sensor_info->id,
> + &sensor->sensor_update_nb);
> + if (ret) {
> + dev_err(&iiodev->dev,
> + "Error in registering sensor update notifier for sensor %s err %d",
> + sensor->sensor_info->name, ret);
> + return ERR_PTR(ret);
> + }
> +
> scmi_iio_set_timestamp_channel(&iio_channels[i], i);
> iiodev->channels = iio_channels;
> return iiodev;
> @@ -604,24 +590,29 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> {
> const struct scmi_sensor_info *sensor_info;
> struct scmi_handle *handle = sdev->handle;
> + struct scmi_protocol_handle *ph;
> struct device *dev = &sdev->dev;
> struct iio_dev *scmi_iio_dev;
> u16 nr_sensors;
> int err = -ENODEV, i;
>
> - if (!handle || !handle->sensor_ops) {
> + if (!handle)
> + return -ENODEV;
> +
> + sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
> + if (IS_ERR(sensor_ops)) {
> dev_err(dev, "SCMI device has no sensor interface\n");
> - return -EINVAL;
> + return PTR_ERR(sensor_ops);
> }
>
> - nr_sensors = handle->sensor_ops->count_get(handle);
> + nr_sensors = sensor_ops->count_get(ph);
> if (!nr_sensors) {
> dev_dbg(dev, "0 sensors found via SCMI bus\n");
> return -ENODEV;
> }
>
> for (i = 0; i < nr_sensors; i++) {
> - sensor_info = handle->sensor_ops->info_get(handle, i);
> + sensor_info = sensor_ops->info_get(ph, i);
> if (!sensor_info) {
> dev_err(dev, "SCMI sensor %d has missing info\n", i);
> return -EINVAL;
> @@ -636,7 +627,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> sensor_info->axis[0].type != RADIANS_SEC)
> continue;
>
> - scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
> + scmi_iio_dev = scmi_alloc_iiodev(sdev, ph, sensor_info);
> if (IS_ERR(scmi_iio_dev)) {
> dev_err(dev,
> "failed to allocate IIO device for sensor %s: %ld\n",

2021-03-30 12:53:37

by Cristian Marussi

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

Hi Jonathan,

On Tue, Mar 30, 2021 at 12:33:25PM +0100, Jonathan Cameron wrote:
> On Tue, 16 Mar 2021 12:48:50 +0000
> Cristian Marussi <[email protected]> wrote:
>
> > Port driver to the new SCMI Sensor interface based on protocol handles
> > and common devm_get_ops().
> >
> > Cc: Jyoti Bhayana <[email protected]>
> > Cc: Jonathan Cameron <[email protected]>
> > Signed-off-by: Cristian Marussi <[email protected]>
>
> +CC [email protected]
>
> Rule of thumb if it doesn't go there it ends up in randomly location based
> on other lists and I might not see it for a few weeks :(
>

Ah sorry, I thought the direct CC was enough.

> > ---
> > drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++++++++++------------
> > 1 file changed, 41 insertions(+), 50 deletions(-)
> >
> > diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > index 872d87ca6256..b4bdc3f3a946 100644
> > --- a/drivers/iio/common/scmi_sensors/scmi_iio.c
> > +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > @@ -21,8 +21,10 @@
> >
> > #define SCMI_IIO_NUM_OF_AXIS 3
> >
> > +static const struct scmi_sensor_proto_ops *sensor_ops;
>
> Hmm. I'm not keen on globals when they really should not be necessary.
> They just result in lifetimes being out of sync. Here you are fine because
> you set it to an appropriate value as the first thing you do in probe, and
> I assume the function only ever returns on answer on repeated calls.
>
> Why not put a copy of that pointer inside the struct scmi_iio_priv structures?
>

The reason for this, as I said to Jyoyi who made the same comment indeed,
from my point of view (maybe wrong..) was that while the protocol_handle,
and previously the handle, are 'per-instance data' (so that you get a
different one each time this driver is possibly probed against a different
platform-handle) and as such are stored in scmi_iio_priv, the _ops are
just plain code pointers and are returned always the same for the same
protocol no matter how many times you probe this driver: you just end up
calling them against the proper different saved protocol_handle; so it
seemed to me an unneeded duplication to stick a copy of the same _ops
inside each per-instance scmi_iio_priv, and at the same time it seemed
also more straigthforward to access them without too many indirections
from inside the scmi_iio_priv struct).

But if these are not valid points I can change this in IIO now, and in
the future also in all the other SCMI drivers that currently use this
same API and pattern of usage with global ops. (..at least because I'd
have to collect again all the other ACks agains and it's a bit later for
that now)

Thanks

Cristian

> Otherwise this all looks like straight forward refactoring so given the
> above is more a 'bad smell' than a bug and I'm rather late to the game.
>
> Acked-by: Jonathan Cameron <[email protected]>
>
>
> > +
> > struct scmi_iio_priv {
> > - struct scmi_handle *handle;
> > + struct scmi_protocol_handle *ph;
> > const struct scmi_sensor_info *sensor_info;
> > struct iio_dev *indio_dev;
> > /* adding one additional channel for timestamp */
> > @@ -82,7 +84,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
> > static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > {
> > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > - u32 sensor_id = sensor->sensor_info->id;
> > u32 sensor_config = 0;
> > int err;
> >
> > @@ -92,27 +93,11 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> >
> > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > SCMI_SENS_CFG_SENSOR_ENABLE);
> > -
> > - err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
> > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > - &sensor_id, &sensor->sensor_update_nb);
> > - if (err) {
> > - dev_err(&iio_dev->dev,
> > - "Error in registering sensor update notifier for sensor %s err %d",
> > - sensor->sensor_info->name, err);
> > - return err;
> > - }
> > -
> > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > - sensor->sensor_info->id, sensor_config);
> > - if (err) {
> > - sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > - SCMI_PROTOCOL_SENSOR,
> > - SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
> > - &sensor->sensor_update_nb);
> > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > + sensor_config);
> > + if (err)
> > dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
> > sensor->sensor_info->name, err);
> > - }
> >
> > return err;
> > }
> > @@ -120,25 +105,13 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
> > {
> > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > - u32 sensor_id = sensor->sensor_info->id;
> > u32 sensor_config = 0;
> > int err;
> >
> > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > SCMI_SENS_CFG_SENSOR_DISABLE);
> > -
> > - err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > - &sensor_id, &sensor->sensor_update_nb);
> > - if (err) {
> > - dev_err(&iio_dev->dev,
> > - "Error in unregistering sensor update notifier for sensor %s err %d",
> > - sensor->sensor_info->name, err);
> > - return err;
> > - }
> > -
> > - err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
> > - sensor_config);
> > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > + sensor_config);
> > if (err) {
> > dev_err(&iio_dev->dev,
> > "Error in disabling sensor %s with err %d",
> > @@ -161,8 +134,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > u32 sensor_config;
> > char buf[32];
> >
> > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > - sensor->sensor_info->id, &sensor_config);
> > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > + &sensor_config);
> > if (err) {
> > dev_err(&iio_dev->dev,
> > "Error in getting sensor config for sensor %s err %d",
> > @@ -208,8 +181,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > sensor_config |=
> > FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);
> >
> > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > - sensor->sensor_info->id, sensor_config);
> > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > + sensor_config);
> > if (err)
> > dev_err(&iio_dev->dev,
> > "Error in setting sensor update interval for sensor %s value %u err %d",
> > @@ -274,8 +247,8 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
> > u32 sensor_config;
> > int mult;
> >
> > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > - sensor->sensor_info->id, &sensor_config);
> > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > + &sensor_config);
> > if (err) {
> > dev_err(&iio_dev->dev,
> > "Error in getting sensor config for sensor %s err %d",
> > @@ -542,15 +515,17 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
> > return 0;
> > }
> >
> > -static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > - struct scmi_handle *handle,
> > - const struct scmi_sensor_info *sensor_info)
> > +static struct iio_dev *
> > +scmi_alloc_iiodev(struct scmi_device *sdev, struct scmi_protocol_handle *ph,
> > + const struct scmi_sensor_info *sensor_info)
> > {
> > struct iio_chan_spec *iio_channels;
> > struct scmi_iio_priv *sensor;
> > enum iio_modifier modifier;
> > enum iio_chan_type type;
> > struct iio_dev *iiodev;
> > + struct device *dev = &sdev->dev;
> > + const struct scmi_handle *handle = sdev->handle;
> > int i, ret;
> >
> > iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
> > @@ -560,7 +535,7 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > iiodev->modes = INDIO_DIRECT_MODE;
> > iiodev->dev.parent = dev;
> > sensor = iio_priv(iiodev);
> > - sensor->handle = handle;
> > + sensor->ph = ph;
> > sensor->sensor_info = sensor_info;
> > sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
> > sensor->indio_dev = iiodev;
> > @@ -595,6 +570,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > sensor_info->axis[i].id);
> > }
> >
> > + ret = handle->notify_ops->devm_event_notifier_register(sdev,
> > + SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > + &sensor->sensor_info->id,
> > + &sensor->sensor_update_nb);
> > + if (ret) {
> > + dev_err(&iiodev->dev,
> > + "Error in registering sensor update notifier for sensor %s err %d",
> > + sensor->sensor_info->name, ret);
> > + return ERR_PTR(ret);
> > + }
> > +
> > scmi_iio_set_timestamp_channel(&iio_channels[i], i);
> > iiodev->channels = iio_channels;
> > return iiodev;
> > @@ -604,24 +590,29 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > {
> > const struct scmi_sensor_info *sensor_info;
> > struct scmi_handle *handle = sdev->handle;
> > + struct scmi_protocol_handle *ph;
> > struct device *dev = &sdev->dev;
> > struct iio_dev *scmi_iio_dev;
> > u16 nr_sensors;
> > int err = -ENODEV, i;
> >
> > - if (!handle || !handle->sensor_ops) {
> > + if (!handle)
> > + return -ENODEV;
> > +
> > + sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
> > + if (IS_ERR(sensor_ops)) {
> > dev_err(dev, "SCMI device has no sensor interface\n");
> > - return -EINVAL;
> > + return PTR_ERR(sensor_ops);
> > }
> >
> > - nr_sensors = handle->sensor_ops->count_get(handle);
> > + nr_sensors = sensor_ops->count_get(ph);
> > if (!nr_sensors) {
> > dev_dbg(dev, "0 sensors found via SCMI bus\n");
> > return -ENODEV;
> > }
> >
> > for (i = 0; i < nr_sensors; i++) {
> > - sensor_info = handle->sensor_ops->info_get(handle, i);
> > + sensor_info = sensor_ops->info_get(ph, i);
> > if (!sensor_info) {
> > dev_err(dev, "SCMI sensor %d has missing info\n", i);
> > return -EINVAL;
> > @@ -636,7 +627,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > sensor_info->axis[0].type != RADIANS_SEC)
> > continue;
> >
> > - scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
> > + scmi_iio_dev = scmi_alloc_iiodev(sdev, ph, sensor_info);
> > if (IS_ERR(scmi_iio_dev)) {
> > dev_err(dev,
> > "failed to allocate IIO device for sensor %s: %ld\n",
>

2021-03-30 13:50:03

by Cristian Marussi

[permalink] [raw]
Subject: [PATCH v8 25/38] iio/scmi: Port driver to the new scmi_sensor_proto_ops interface

Port the scmi iio driver to the new SCMI sensor interface based on
protocol handles and common devm_get_ops().

Link: https://lore.kernel.org/r/[email protected]
Cc: Jyoti Bhayana <[email protected]>
Cc: Jonathan Cameron <[email protected]>
Cc: [email protected]
Tested-by: Florian Fainelli <[email protected]>
Acked-by: Jonathan Cameron <[email protected]>
Signed-off-by: Cristian Marussi <[email protected]>
Signed-off-by: Sudeep Holla <[email protected]>
----
v7 --> v8
- make sensor_ops NON global
---
drivers/iio/common/scmi_sensors/scmi_iio.c | 100 ++++++++++-----------
1 file changed, 50 insertions(+), 50 deletions(-)

diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
index 872d87ca6256..8f4154d92c68 100644
--- a/drivers/iio/common/scmi_sensors/scmi_iio.c
+++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
@@ -22,7 +22,8 @@
#define SCMI_IIO_NUM_OF_AXIS 3

struct scmi_iio_priv {
- struct scmi_handle *handle;
+ const struct scmi_sensor_proto_ops *sensor_ops;
+ struct scmi_protocol_handle *ph;
const struct scmi_sensor_info *sensor_info;
struct iio_dev *indio_dev;
/* adding one additional channel for timestamp */
@@ -82,7 +83,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
{
struct scmi_iio_priv *sensor = iio_priv(iio_dev);
- u32 sensor_id = sensor->sensor_info->id;
u32 sensor_config = 0;
int err;

@@ -92,27 +92,12 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)

sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
SCMI_SENS_CFG_SENSOR_ENABLE);
-
- err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
- SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
- &sensor_id, &sensor->sensor_update_nb);
- if (err) {
- dev_err(&iio_dev->dev,
- "Error in registering sensor update notifier for sensor %s err %d",
- sensor->sensor_info->name, err);
- return err;
- }
-
- err = sensor->handle->sensor_ops->config_set(sensor->handle,
- sensor->sensor_info->id, sensor_config);
- if (err) {
- sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
- SCMI_PROTOCOL_SENSOR,
- SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
- &sensor->sensor_update_nb);
+ err = sensor->sensor_ops->config_set(sensor->ph,
+ sensor->sensor_info->id,
+ sensor_config);
+ if (err)
dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
sensor->sensor_info->name, err);
- }

return err;
}
@@ -120,25 +105,14 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
{
struct scmi_iio_priv *sensor = iio_priv(iio_dev);
- u32 sensor_id = sensor->sensor_info->id;
u32 sensor_config = 0;
int err;

sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
SCMI_SENS_CFG_SENSOR_DISABLE);
-
- err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
- SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
- &sensor_id, &sensor->sensor_update_nb);
- if (err) {
- dev_err(&iio_dev->dev,
- "Error in unregistering sensor update notifier for sensor %s err %d",
- sensor->sensor_info->name, err);
- return err;
- }
-
- err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
- sensor_config);
+ err = sensor->sensor_ops->config_set(sensor->ph,
+ sensor->sensor_info->id,
+ sensor_config);
if (err) {
dev_err(&iio_dev->dev,
"Error in disabling sensor %s with err %d",
@@ -161,8 +135,9 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
u32 sensor_config;
char buf[32];

- int err = sensor->handle->sensor_ops->config_get(sensor->handle,
- sensor->sensor_info->id, &sensor_config);
+ int err = sensor->sensor_ops->config_get(sensor->ph,
+ sensor->sensor_info->id,
+ &sensor_config);
if (err) {
dev_err(&iio_dev->dev,
"Error in getting sensor config for sensor %s err %d",
@@ -208,8 +183,9 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
sensor_config |=
FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);

- err = sensor->handle->sensor_ops->config_set(sensor->handle,
- sensor->sensor_info->id, sensor_config);
+ err = sensor->sensor_ops->config_set(sensor->ph,
+ sensor->sensor_info->id,
+ sensor_config);
if (err)
dev_err(&iio_dev->dev,
"Error in setting sensor update interval for sensor %s value %u err %d",
@@ -274,8 +250,9 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
u32 sensor_config;
int mult;

- int err = sensor->handle->sensor_ops->config_get(sensor->handle,
- sensor->sensor_info->id, &sensor_config);
+ int err = sensor->sensor_ops->config_get(sensor->ph,
+ sensor->sensor_info->id,
+ &sensor_config);
if (err) {
dev_err(&iio_dev->dev,
"Error in getting sensor config for sensor %s err %d",
@@ -542,15 +519,19 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
return 0;
}

-static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
- struct scmi_handle *handle,
- const struct scmi_sensor_info *sensor_info)
+static struct iio_dev *
+scmi_alloc_iiodev(struct scmi_device *sdev,
+ const struct scmi_sensor_proto_ops *ops,
+ struct scmi_protocol_handle *ph,
+ const struct scmi_sensor_info *sensor_info)
{
struct iio_chan_spec *iio_channels;
struct scmi_iio_priv *sensor;
enum iio_modifier modifier;
enum iio_chan_type type;
struct iio_dev *iiodev;
+ struct device *dev = &sdev->dev;
+ const struct scmi_handle *handle = sdev->handle;
int i, ret;

iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
@@ -560,7 +541,8 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
iiodev->modes = INDIO_DIRECT_MODE;
iiodev->dev.parent = dev;
sensor = iio_priv(iiodev);
- sensor->handle = handle;
+ sensor->sensor_ops = ops;
+ sensor->ph = ph;
sensor->sensor_info = sensor_info;
sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
sensor->indio_dev = iiodev;
@@ -595,6 +577,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
sensor_info->axis[i].id);
}

+ ret = handle->notify_ops->devm_event_notifier_register(sdev,
+ SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
+ &sensor->sensor_info->id,
+ &sensor->sensor_update_nb);
+ if (ret) {
+ dev_err(&iiodev->dev,
+ "Error in registering sensor update notifier for sensor %s err %d",
+ sensor->sensor_info->name, ret);
+ return ERR_PTR(ret);
+ }
+
scmi_iio_set_timestamp_channel(&iio_channels[i], i);
iiodev->channels = iio_channels;
return iiodev;
@@ -604,24 +597,30 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
{
const struct scmi_sensor_info *sensor_info;
struct scmi_handle *handle = sdev->handle;
+ const struct scmi_sensor_proto_ops *sensor_ops;
+ struct scmi_protocol_handle *ph;
struct device *dev = &sdev->dev;
struct iio_dev *scmi_iio_dev;
u16 nr_sensors;
int err = -ENODEV, i;

- if (!handle || !handle->sensor_ops) {
+ if (!handle)
+ return -ENODEV;
+
+ sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
+ if (IS_ERR(sensor_ops)) {
dev_err(dev, "SCMI device has no sensor interface\n");
- return -EINVAL;
+ return PTR_ERR(sensor_ops);
}

- nr_sensors = handle->sensor_ops->count_get(handle);
+ nr_sensors = sensor_ops->count_get(ph);
if (!nr_sensors) {
dev_dbg(dev, "0 sensors found via SCMI bus\n");
return -ENODEV;
}

for (i = 0; i < nr_sensors; i++) {
- sensor_info = handle->sensor_ops->info_get(handle, i);
+ sensor_info = sensor_ops->info_get(ph, i);
if (!sensor_info) {
dev_err(dev, "SCMI sensor %d has missing info\n", i);
return -EINVAL;
@@ -636,7 +635,8 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
sensor_info->axis[0].type != RADIANS_SEC)
continue;

- scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
+ scmi_iio_dev = scmi_alloc_iiodev(sdev, sensor_ops, ph,
+ sensor_info);
if (IS_ERR(scmi_iio_dev)) {
dev_err(dev,
"failed to allocate IIO device for sensor %s: %ld\n",
--
2.17.1

2021-03-30 17:37:12

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

On Tue, 30 Mar 2021 13:51:13 +0100
Cristian Marussi <[email protected]> wrote:

> Hi Jonathan,
>
> On Tue, Mar 30, 2021 at 12:33:25PM +0100, Jonathan Cameron wrote:
> > On Tue, 16 Mar 2021 12:48:50 +0000
> > Cristian Marussi <[email protected]> wrote:
> >
> > > Port driver to the new SCMI Sensor interface based on protocol handles
> > > and common devm_get_ops().
> > >
> > > Cc: Jyoti Bhayana <[email protected]>
> > > Cc: Jonathan Cameron <[email protected]>
> > > Signed-off-by: Cristian Marussi <[email protected]>
> >
> > +CC [email protected]
> >
> > Rule of thumb if it doesn't go there it ends up in randomly location based
> > on other lists and I might not see it for a few weeks :(
> >
>
> Ah sorry, I thought the direct CC was enough.

No problem. Too much email :)

>
> > > ---
> > > drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++++++++++------------
> > > 1 file changed, 41 insertions(+), 50 deletions(-)
> > >
> > > diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > index 872d87ca6256..b4bdc3f3a946 100644
> > > --- a/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > @@ -21,8 +21,10 @@
> > >
> > > #define SCMI_IIO_NUM_OF_AXIS 3
> > >
> > > +static const struct scmi_sensor_proto_ops *sensor_ops;
> >
> > Hmm. I'm not keen on globals when they really should not be necessary.
> > They just result in lifetimes being out of sync. Here you are fine because
> > you set it to an appropriate value as the first thing you do in probe, and
> > I assume the function only ever returns on answer on repeated calls.
> >
> > Why not put a copy of that pointer inside the struct scmi_iio_priv structures?
> >
>
> The reason for this, as I said to Jyoyi who made the same comment indeed,
> from my point of view (maybe wrong..) was that while the protocol_handle,
> and previously the handle, are 'per-instance data' (so that you get a
> different one each time this driver is possibly probed against a different
> platform-handle) and as such are stored in scmi_iio_priv, the _ops are
> just plain code pointers and are returned always the same for the same
> protocol no matter how many times you probe this driver:

As that's the case, I'm a little confused to why you have added the complexity
of a query interface in the first place? Why not just export the ops and
have the various drivers access them directly? If there is only
one set of scmi_sensor_ops etc, then let drivers at it directly, or
indeed export the functions that make up the ops structure directly.

This sounds like a bit of abstraction that only serves to make the
code harder to read.

> you just end up
> calling them against the proper different saved protocol_handle; so it
> seemed to me an unneeded duplication to stick a copy of the same _ops
> inside each per-instance scmi_iio_priv, and at the same time it seemed
> also more straigthforward to access them without too many indirections
> from inside the scmi_iio_priv struct).
>
> But if these are not valid points I can change this in IIO now, and in
> the future also in all the other SCMI drivers that currently use this
> same API and pattern of usage with global ops. (..at least because I'd
> have to collect again all the other ACks agains and it's a bit later for
> that now)

I'm fine with leaving it as is. There's no fundamental issue, it's just
a little bit ugly and I'm fussy :)

>
> Thanks
>
> Cristian
>
> > Otherwise this all looks like straight forward refactoring so given the
> > above is more a 'bad smell' than a bug and I'm rather late to the game.
> >
> > Acked-by: Jonathan Cameron <[email protected]>
> >
> >
> > > +
> > > struct scmi_iio_priv {
> > > - struct scmi_handle *handle;
> > > + struct scmi_protocol_handle *ph;
> > > const struct scmi_sensor_info *sensor_info;
> > > struct iio_dev *indio_dev;
> > > /* adding one additional channel for timestamp */
> > > @@ -82,7 +84,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
> > > static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > {
> > > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > > - u32 sensor_id = sensor->sensor_info->id;
> > > u32 sensor_config = 0;
> > > int err;
> > >
> > > @@ -92,27 +93,11 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > >
> > > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > > SCMI_SENS_CFG_SENSOR_ENABLE);
> > > -
> > > - err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
> > > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > - &sensor_id, &sensor->sensor_update_nb);
> > > - if (err) {
> > > - dev_err(&iio_dev->dev,
> > > - "Error in registering sensor update notifier for sensor %s err %d",
> > > - sensor->sensor_info->name, err);
> > > - return err;
> > > - }
> > > -
> > > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > > - sensor->sensor_info->id, sensor_config);
> > > - if (err) {
> > > - sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > > - SCMI_PROTOCOL_SENSOR,
> > > - SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
> > > - &sensor->sensor_update_nb);
> > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > + sensor_config);
> > > + if (err)
> > > dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
> > > sensor->sensor_info->name, err);
> > > - }
> > >
> > > return err;
> > > }
> > > @@ -120,25 +105,13 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
> > > {
> > > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > > - u32 sensor_id = sensor->sensor_info->id;
> > > u32 sensor_config = 0;
> > > int err;
> > >
> > > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > > SCMI_SENS_CFG_SENSOR_DISABLE);
> > > -
> > > - err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > - &sensor_id, &sensor->sensor_update_nb);
> > > - if (err) {
> > > - dev_err(&iio_dev->dev,
> > > - "Error in unregistering sensor update notifier for sensor %s err %d",
> > > - sensor->sensor_info->name, err);
> > > - return err;
> > > - }
> > > -
> > > - err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
> > > - sensor_config);
> > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > + sensor_config);
> > > if (err) {
> > > dev_err(&iio_dev->dev,
> > > "Error in disabling sensor %s with err %d",
> > > @@ -161,8 +134,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > > u32 sensor_config;
> > > char buf[32];
> > >
> > > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > > - sensor->sensor_info->id, &sensor_config);
> > > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > > + &sensor_config);
> > > if (err) {
> > > dev_err(&iio_dev->dev,
> > > "Error in getting sensor config for sensor %s err %d",
> > > @@ -208,8 +181,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > > sensor_config |=
> > > FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);
> > >
> > > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > > - sensor->sensor_info->id, sensor_config);
> > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > + sensor_config);
> > > if (err)
> > > dev_err(&iio_dev->dev,
> > > "Error in setting sensor update interval for sensor %s value %u err %d",
> > > @@ -274,8 +247,8 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
> > > u32 sensor_config;
> > > int mult;
> > >
> > > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > > - sensor->sensor_info->id, &sensor_config);
> > > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > > + &sensor_config);
> > > if (err) {
> > > dev_err(&iio_dev->dev,
> > > "Error in getting sensor config for sensor %s err %d",
> > > @@ -542,15 +515,17 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
> > > return 0;
> > > }
> > >
> > > -static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > - struct scmi_handle *handle,
> > > - const struct scmi_sensor_info *sensor_info)
> > > +static struct iio_dev *
> > > +scmi_alloc_iiodev(struct scmi_device *sdev, struct scmi_protocol_handle *ph,
> > > + const struct scmi_sensor_info *sensor_info)
> > > {
> > > struct iio_chan_spec *iio_channels;
> > > struct scmi_iio_priv *sensor;
> > > enum iio_modifier modifier;
> > > enum iio_chan_type type;
> > > struct iio_dev *iiodev;
> > > + struct device *dev = &sdev->dev;
> > > + const struct scmi_handle *handle = sdev->handle;
> > > int i, ret;
> > >
> > > iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
> > > @@ -560,7 +535,7 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > iiodev->modes = INDIO_DIRECT_MODE;
> > > iiodev->dev.parent = dev;
> > > sensor = iio_priv(iiodev);
> > > - sensor->handle = handle;
> > > + sensor->ph = ph;
> > > sensor->sensor_info = sensor_info;
> > > sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
> > > sensor->indio_dev = iiodev;
> > > @@ -595,6 +570,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > sensor_info->axis[i].id);
> > > }
> > >
> > > + ret = handle->notify_ops->devm_event_notifier_register(sdev,
> > > + SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > + &sensor->sensor_info->id,
> > > + &sensor->sensor_update_nb);
> > > + if (ret) {
> > > + dev_err(&iiodev->dev,
> > > + "Error in registering sensor update notifier for sensor %s err %d",
> > > + sensor->sensor_info->name, ret);
> > > + return ERR_PTR(ret);
> > > + }
> > > +
> > > scmi_iio_set_timestamp_channel(&iio_channels[i], i);
> > > iiodev->channels = iio_channels;
> > > return iiodev;
> > > @@ -604,24 +590,29 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > > {
> > > const struct scmi_sensor_info *sensor_info;
> > > struct scmi_handle *handle = sdev->handle;
> > > + struct scmi_protocol_handle *ph;
> > > struct device *dev = &sdev->dev;
> > > struct iio_dev *scmi_iio_dev;
> > > u16 nr_sensors;
> > > int err = -ENODEV, i;
> > >
> > > - if (!handle || !handle->sensor_ops) {
> > > + if (!handle)
> > > + return -ENODEV;
> > > +
> > > + sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
> > > + if (IS_ERR(sensor_ops)) {
> > > dev_err(dev, "SCMI device has no sensor interface\n");
> > > - return -EINVAL;
> > > + return PTR_ERR(sensor_ops);
> > > }
> > >
> > > - nr_sensors = handle->sensor_ops->count_get(handle);
> > > + nr_sensors = sensor_ops->count_get(ph);
> > > if (!nr_sensors) {
> > > dev_dbg(dev, "0 sensors found via SCMI bus\n");
> > > return -ENODEV;
> > > }
> > >
> > > for (i = 0; i < nr_sensors; i++) {
> > > - sensor_info = handle->sensor_ops->info_get(handle, i);
> > > + sensor_info = sensor_ops->info_get(ph, i);
> > > if (!sensor_info) {
> > > dev_err(dev, "SCMI sensor %d has missing info\n", i);
> > > return -EINVAL;
> > > @@ -636,7 +627,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > > sensor_info->axis[0].type != RADIANS_SEC)
> > > continue;
> > >
> > > - scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
> > > + scmi_iio_dev = scmi_alloc_iiodev(sdev, ph, sensor_info);
> > > if (IS_ERR(scmi_iio_dev)) {
> > > dev_err(dev,
> > > "failed to allocate IIO device for sensor %s: %ld\n",
> >

2021-03-30 17:43:37

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v8 25/38] iio/scmi: Port driver to the new scmi_sensor_proto_ops interface

On Tue, 30 Mar 2021 14:47:11 +0100
Cristian Marussi <[email protected]> wrote:

> Port the scmi iio driver to the new SCMI sensor interface based on
> protocol handles and common devm_get_ops().
>
> Link: https://lore.kernel.org/r/[email protected]
> Cc: Jyoti Bhayana <[email protected]>
> Cc: Jonathan Cameron <[email protected]>
> Cc: [email protected]
> Tested-by: Florian Fainelli <[email protected]>
> Acked-by: Jonathan Cameron <[email protected]>
> Signed-off-by: Cristian Marussi <[email protected]>
> Signed-off-by: Sudeep Holla <[email protected]>

Thanks for doing this, but beyond the more general question I put
in the reply to v7 of why we have this abstraction in the first place,
I'm fine with either version (v7 or v8).

I 'slightly' prefer this one I guess, but it actually hides the
more interesting question of whether the use of a protocol
related function to get access to functions that could just have
been exported from the original module actually makes sense?

Ah well. Let's go with the perfect not being the enemy of good and
all that.

Acked-by: Jonathan Cameron <[email protected]>

for this one as well. Take your pick ;)

Jonathan

> ----
> v7 --> v8
> - make sensor_ops NON global
> ---
> drivers/iio/common/scmi_sensors/scmi_iio.c | 100 ++++++++++-----------
> 1 file changed, 50 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
> index 872d87ca6256..8f4154d92c68 100644
> --- a/drivers/iio/common/scmi_sensors/scmi_iio.c
> +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
> @@ -22,7 +22,8 @@
> #define SCMI_IIO_NUM_OF_AXIS 3
>
> struct scmi_iio_priv {
> - struct scmi_handle *handle;
> + const struct scmi_sensor_proto_ops *sensor_ops;
> + struct scmi_protocol_handle *ph;
> const struct scmi_sensor_info *sensor_info;
> struct iio_dev *indio_dev;
> /* adding one additional channel for timestamp */
> @@ -82,7 +83,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
> static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> {
> struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> - u32 sensor_id = sensor->sensor_info->id;
> u32 sensor_config = 0;
> int err;
>
> @@ -92,27 +92,12 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
>
> sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> SCMI_SENS_CFG_SENSOR_ENABLE);
> -
> - err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
> - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> - &sensor_id, &sensor->sensor_update_nb);
> - if (err) {
> - dev_err(&iio_dev->dev,
> - "Error in registering sensor update notifier for sensor %s err %d",
> - sensor->sensor_info->name, err);
> - return err;
> - }
> -
> - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> - sensor->sensor_info->id, sensor_config);
> - if (err) {
> - sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> - SCMI_PROTOCOL_SENSOR,
> - SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
> - &sensor->sensor_update_nb);
> + err = sensor->sensor_ops->config_set(sensor->ph,
> + sensor->sensor_info->id,
> + sensor_config);
> + if (err)
> dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
> sensor->sensor_info->name, err);
> - }
>
> return err;
> }
> @@ -120,25 +105,14 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
> {
> struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> - u32 sensor_id = sensor->sensor_info->id;
> u32 sensor_config = 0;
> int err;
>
> sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> SCMI_SENS_CFG_SENSOR_DISABLE);
> -
> - err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> - &sensor_id, &sensor->sensor_update_nb);
> - if (err) {
> - dev_err(&iio_dev->dev,
> - "Error in unregistering sensor update notifier for sensor %s err %d",
> - sensor->sensor_info->name, err);
> - return err;
> - }
> -
> - err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
> - sensor_config);
> + err = sensor->sensor_ops->config_set(sensor->ph,
> + sensor->sensor_info->id,
> + sensor_config);
> if (err) {
> dev_err(&iio_dev->dev,
> "Error in disabling sensor %s with err %d",
> @@ -161,8 +135,9 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> u32 sensor_config;
> char buf[32];
>
> - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> - sensor->sensor_info->id, &sensor_config);
> + int err = sensor->sensor_ops->config_get(sensor->ph,
> + sensor->sensor_info->id,
> + &sensor_config);
> if (err) {
> dev_err(&iio_dev->dev,
> "Error in getting sensor config for sensor %s err %d",
> @@ -208,8 +183,9 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> sensor_config |=
> FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);
>
> - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> - sensor->sensor_info->id, sensor_config);
> + err = sensor->sensor_ops->config_set(sensor->ph,
> + sensor->sensor_info->id,
> + sensor_config);
> if (err)
> dev_err(&iio_dev->dev,
> "Error in setting sensor update interval for sensor %s value %u err %d",
> @@ -274,8 +250,9 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
> u32 sensor_config;
> int mult;
>
> - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> - sensor->sensor_info->id, &sensor_config);
> + int err = sensor->sensor_ops->config_get(sensor->ph,
> + sensor->sensor_info->id,
> + &sensor_config);
> if (err) {
> dev_err(&iio_dev->dev,
> "Error in getting sensor config for sensor %s err %d",
> @@ -542,15 +519,19 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
> return 0;
> }
>
> -static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> - struct scmi_handle *handle,
> - const struct scmi_sensor_info *sensor_info)
> +static struct iio_dev *
> +scmi_alloc_iiodev(struct scmi_device *sdev,
> + const struct scmi_sensor_proto_ops *ops,
> + struct scmi_protocol_handle *ph,
> + const struct scmi_sensor_info *sensor_info)
> {
> struct iio_chan_spec *iio_channels;
> struct scmi_iio_priv *sensor;
> enum iio_modifier modifier;
> enum iio_chan_type type;
> struct iio_dev *iiodev;
> + struct device *dev = &sdev->dev;
> + const struct scmi_handle *handle = sdev->handle;
> int i, ret;
>
> iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
> @@ -560,7 +541,8 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> iiodev->modes = INDIO_DIRECT_MODE;
> iiodev->dev.parent = dev;
> sensor = iio_priv(iiodev);
> - sensor->handle = handle;
> + sensor->sensor_ops = ops;
> + sensor->ph = ph;
> sensor->sensor_info = sensor_info;
> sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
> sensor->indio_dev = iiodev;
> @@ -595,6 +577,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> sensor_info->axis[i].id);
> }
>
> + ret = handle->notify_ops->devm_event_notifier_register(sdev,
> + SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> + &sensor->sensor_info->id,
> + &sensor->sensor_update_nb);
> + if (ret) {
> + dev_err(&iiodev->dev,
> + "Error in registering sensor update notifier for sensor %s err %d",
> + sensor->sensor_info->name, ret);
> + return ERR_PTR(ret);
> + }
> +
> scmi_iio_set_timestamp_channel(&iio_channels[i], i);
> iiodev->channels = iio_channels;
> return iiodev;
> @@ -604,24 +597,30 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> {
> const struct scmi_sensor_info *sensor_info;
> struct scmi_handle *handle = sdev->handle;
> + const struct scmi_sensor_proto_ops *sensor_ops;
> + struct scmi_protocol_handle *ph;
> struct device *dev = &sdev->dev;
> struct iio_dev *scmi_iio_dev;
> u16 nr_sensors;
> int err = -ENODEV, i;
>
> - if (!handle || !handle->sensor_ops) {
> + if (!handle)
> + return -ENODEV;
> +
> + sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
> + if (IS_ERR(sensor_ops)) {
> dev_err(dev, "SCMI device has no sensor interface\n");
> - return -EINVAL;
> + return PTR_ERR(sensor_ops);
> }
>
> - nr_sensors = handle->sensor_ops->count_get(handle);
> + nr_sensors = sensor_ops->count_get(ph);
> if (!nr_sensors) {
> dev_dbg(dev, "0 sensors found via SCMI bus\n");
> return -ENODEV;
> }
>
> for (i = 0; i < nr_sensors; i++) {
> - sensor_info = handle->sensor_ops->info_get(handle, i);
> + sensor_info = sensor_ops->info_get(ph, i);
> if (!sensor_info) {
> dev_err(dev, "SCMI sensor %d has missing info\n", i);
> return -EINVAL;
> @@ -636,7 +635,8 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> sensor_info->axis[0].type != RADIANS_SEC)
> continue;
>
> - scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
> + scmi_iio_dev = scmi_alloc_iiodev(sdev, sensor_ops, ph,
> + sensor_info);
> if (IS_ERR(scmi_iio_dev)) {
> dev_err(dev,
> "failed to allocate IIO device for sensor %s: %ld\n",

2021-03-31 08:24:47

by Sudeep Holla

[permalink] [raw]
Subject: Re: [PATCH v7 00/38] SCMI vendor protocols and modularization

On Tue, 16 Mar 2021 12:48:25 +0000, Cristian Marussi wrote:
> The current SCMI implementation does not provide an interface to easily
> develop and include a custom vendor protocol implementation as prescribed
> by the SCMI standard, also because, there is not currently any custom
> protocol in the upstream to justify the development of a custom interface
> and its maintenance.
>
> Moreover the current interface exposes protocol operations to the SCMI
> driver users attaching per-protocol operations directly to the handle
> structure, which, in this way, tends to grow indefinitely for each new
> protocol addition.
>
> [...]


Applied to sudeep.holla/linux (for-next/scmi), thanks!

[01/38] firmware: arm_scmi: review protocol registration interface
https://git.kernel.org/sudeep.holla/c/48dc16e2e5
[02/38] firmware: arm_scmi: introduce protocol handle definitions
https://git.kernel.org/sudeep.holla/c/d7b6cc563a
[03/38] firmware: arm_scmi: introduce devres get/put protocols operations
https://git.kernel.org/sudeep.holla/c/23934efe37
[04/38] firmware: arm_scmi: make notifications aware of protocols users
https://git.kernel.org/sudeep.holla/c/3dd2c81475
[05/38] firmware: arm_scmi: introduce new devres notification ops
https://git.kernel.org/sudeep.holla/c/5ad3d1cf7d
[06/38] firmware: arm_scmi: refactor events registration
https://git.kernel.org/sudeep.holla/c/533c7095b1
[07/38] firmware: arm_scmi: convert events registration to protocol handles
https://git.kernel.org/sudeep.holla/c/b9f7fd907c
[08/38] firmware: arm_scmi: add new protocol handle core xfer ops
https://git.kernel.org/sudeep.holla/c/a4a20b0975
[09/38] firmware: arm_scmi: add helper to access revision area memory
https://git.kernel.org/sudeep.holla/c/3d5d6e84ea
[10/38] firmware: arm_scmi: port Base protocol to new interface
https://git.kernel.org/sudeep.holla/c/8d3581c252
[11/38] firmware: arm_scmi: port Perf protocol to new protocols interface
https://git.kernel.org/sudeep.holla/c/1fec5e6b52
[12/38] cpufreq: scmi: port driver to the new scmi_perf_proto_ops interface
https://git.kernel.org/sudeep.holla/c/eb1d35c6e3
[13/38] firmware: arm_scmi: remove legacy scmi_perf_ops protocol interface
https://git.kernel.org/sudeep.holla/c/f58315a49c
[14/38] firmware: arm_scmi: port Power protocol to new protocols interface
https://git.kernel.org/sudeep.holla/c/9bc8069c85
[15/38] firmware: arm_scmi: port GenPD driver to the new scmi_power_proto_ops interface
https://git.kernel.org/sudeep.holla/c/26f19496a9
[16/38] firmware: arm_scmi: remove legacy scmi_power_ops protocol interface
https://git.kernel.org/sudeep.holla/c/0f84576a62
[17/38] firmware: arm_scmi: port Clock protocol to new protocols interface
https://git.kernel.org/sudeep.holla/c/887281c751
[18/38] clk: scmi: port driver to the new scmi_clk_proto_ops interface
https://git.kernel.org/sudeep.holla/c/beb076bb18
[19/38] firmware: arm_scmi: remove legacy scmi_clk_ops protocol interface
https://git.kernel.org/sudeep.holla/c/137e68659e
[20/38] firmware: arm_scmi: port Reset protocol to new protocols interface
https://git.kernel.org/sudeep.holla/c/7e02934422
[21/38] reset: reset-scmi: port driver to the new scmi_reset_proto_ops interface
https://git.kernel.org/sudeep.holla/c/35cc263062
[22/38] firmware: arm_scmi: remove legacy scmi_reset_ops protocol interface
https://git.kernel.org/sudeep.holla/c/497ef0cbc6
[23/38] firmware: arm_scmi: port Sensor protocol to new protocols interface
https://git.kernel.org/sudeep.holla/c/9694a7f623
[24/38] hwmon: (scmi) port driver to the new scmi_sensor_proto_ops interface
https://git.kernel.org/sudeep.holla/c/987bae41e9
[25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface
https://git.kernel.org/sudeep.holla/c/25cbdd4609
[26/38] firmware: arm_scmi: remove legacy scmi_sensor_ops protocol interface
https://git.kernel.org/sudeep.holla/c/f3690d9729
[27/38] firmware: arm_scmi: port SystemPower protocol to new protocols interface
https://git.kernel.org/sudeep.holla/c/b46d852718
[28/38] firmware: arm_scmi: port Voltage protocol to new protocols interface
https://git.kernel.org/sudeep.holla/c/fe4894d968
[29/38] regulator: scmi: port driver to the new scmi_voltage_proto_ops interface
https://git.kernel.org/sudeep.holla/c/59046d157d
[30/38] firmware: arm_scmi: remove legacy scmi_voltage_ops protocol interface
https://git.kernel.org/sudeep.holla/c/c3ed5e953e
[31/38] firmware: arm_scmi: make references to handle const
https://git.kernel.org/sudeep.holla/c/f0e73cee26
[32/38] firmware: arm_scmi: cleanup legacy protocol init code
https://git.kernel.org/sudeep.holla/c/51fe1b154e
[33/38] firmware: arm_scmi: cleanup unused core xfer wrappers
https://git.kernel.org/sudeep.holla/c/9162afa2ae
[34/38] firmware: arm_scmi: cleanup events registration transient code
https://git.kernel.org/sudeep.holla/c/3cb8c95f4b
[35/38] firmware: arm_scmi: make notify_priv really private
https://git.kernel.org/sudeep.holla/c/a02d7c93c1
[36/38] firmware: arm_scmi: rename non devres notify_ops
https://git.kernel.org/sudeep.holla/c/aa1fd3e4cb
[37/38] firmware: arm_scmi: add protocol modularization support
https://git.kernel.org/sudeep.holla/c/f5800e0bf6
[38/38] firmware: arm_scmi: add dynamic scmi devices creation
https://git.kernel.org/sudeep.holla/c/d4f9dddd21

--
Regards,
Sudeep

2021-03-31 08:34:31

by Cristian Marussi

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

Hi Jonathan

On Tue, Mar 30, 2021 at 06:34:04PM +0100, Jonathan Cameron wrote:
> On Tue, 30 Mar 2021 13:51:13 +0100
> Cristian Marussi <[email protected]> wrote:
>
> > Hi Jonathan,
> >
> > On Tue, Mar 30, 2021 at 12:33:25PM +0100, Jonathan Cameron wrote:
> > > On Tue, 16 Mar 2021 12:48:50 +0000
> > > Cristian Marussi <[email protected]> wrote:
> > >
> > > > Port driver to the new SCMI Sensor interface based on protocol handles
> > > > and common devm_get_ops().
> > > >
> > > > Cc: Jyoti Bhayana <[email protected]>
> > > > Cc: Jonathan Cameron <[email protected]>
> > > > Signed-off-by: Cristian Marussi <[email protected]>
> > >
> > > +CC [email protected]
> > >
> > > Rule of thumb if it doesn't go there it ends up in randomly location based
> > > on other lists and I might not see it for a few weeks :(
> > >
> >
> > Ah sorry, I thought the direct CC was enough.
>
> No problem. Too much email :)
>
> >
> > > > ---
> > > > drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++++++++++------------
> > > > 1 file changed, 41 insertions(+), 50 deletions(-)
> > > >
> > > > diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > > index 872d87ca6256..b4bdc3f3a946 100644
> > > > --- a/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > > +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > > @@ -21,8 +21,10 @@
> > > >
> > > > #define SCMI_IIO_NUM_OF_AXIS 3
> > > >
> > > > +static const struct scmi_sensor_proto_ops *sensor_ops;
> > >
> > > Hmm. I'm not keen on globals when they really should not be necessary.
> > > They just result in lifetimes being out of sync. Here you are fine because
> > > you set it to an appropriate value as the first thing you do in probe, and
> > > I assume the function only ever returns on answer on repeated calls.
> > >
> > > Why not put a copy of that pointer inside the struct scmi_iio_priv structures?
> > >
> >
> > The reason for this, as I said to Jyoyi who made the same comment indeed,
> > from my point of view (maybe wrong..) was that while the protocol_handle,
> > and previously the handle, are 'per-instance data' (so that you get a
> > different one each time this driver is possibly probed against a different
> > platform-handle) and as such are stored in scmi_iio_priv, the _ops are
> > just plain code pointers and are returned always the same for the same
> > protocol no matter how many times you probe this driver:
>
> As that's the case, I'm a little confused to why you have added the complexity
> of a query interface in the first place? Why not just export the ops and
> have the various drivers access them directly? If there is only
> one set of scmi_sensor_ops etc, then let drivers at it directly, or
> indeed export the functions that make up the ops structure directly.
>
> This sounds like a bit of abstraction that only serves to make the
> code harder to read.
>

Thanks for your comments, let me explain a bit.

While the ops are indeed per-protocol common code available to SCMI drivers,
the protocol handle, which you also obtain with devm_protocol_get(), is
instead an opaque reference bound to the specific protocol instance
associated to the platform handle you're using, so that, in case there are
multiple SCMI platforms defined on the system, you'll get, at each probe a
specific and distinct protocol_handle to use with your ops: this way
you'll act upon a completely distinct initialized protocol stack, using
a distinct underlying transport layer toward your platform of choice.

Since this series wanted to unify SCMI standard and custom protocol interfaces
and enable modularization too, the get/put abstraction is there indeed to be
able to track internally protocol users and do resource accounting so that an
SCMI driver has to explicitly ask to use a protocol: the protocols instances are
then initialized on demand only when the first user shows up and more importantly
a hold is put on the protocol module refs avoiding its possible unloading
while still in use (even though only custom protocol are allowed as loadable
modules as of now...)

Coming to the ops instead, the reason not to simply export them was...well...
...not to export new symbols, and not just to stick to the old handle->ops()
interface way of non-exporting ops, or because I'm pavid at exporting new symbols
(I am :D), but because the idea was that in this way it would also have been
easier for vendors writing custom protocol modules to be able to just use them
in their own SCMI driver without the need to export also their new custom ops.
(and same goes generally for any new possible future standard protocol
which will not require endlessly further exports)

Just for these reasons I attached the ops retrieval the same protocol_get()
interface already introduced to handle all of the above.

> > you just end up
> > calling them against the proper different saved protocol_handle; so it
> > seemed to me an unneeded duplication to stick a copy of the same _ops
> > inside each per-instance scmi_iio_priv, and at the same time it seemed
> > also more straigthforward to access them without too many indirections
> > from inside the scmi_iio_priv struct).
> >
> > But if these are not valid points I can change this in IIO now, and in
> > the future also in all the other SCMI drivers that currently use this
> > same API and pattern of usage with global ops. (..at least because I'd
> > have to collect again all the other ACks agains and it's a bit later for
> > that now)
>
> I'm fine with leaving it as is. There's no fundamental issue, it's just
> a little bit ugly and I'm fussy :)
>

I'm not fullly liking it too, but it was the best I could come up to cope
with the above reqs (and the limited amount of my grey-matter :D)

But if in the future we can come up with something better, or some reqs
are dropped/revisited I'll be happy to flood the list with another
jumbo-series.

Thanks

Cristian

> >
> > Thanks
> >
> > Cristian
> >
> > > Otherwise this all looks like straight forward refactoring so given the
> > > above is more a 'bad smell' than a bug and I'm rather late to the game.
> > >
> > > Acked-by: Jonathan Cameron <[email protected]>
> > >
> > >
> > > > +
> > > > struct scmi_iio_priv {
> > > > - struct scmi_handle *handle;
> > > > + struct scmi_protocol_handle *ph;
> > > > const struct scmi_sensor_info *sensor_info;
> > > > struct iio_dev *indio_dev;
> > > > /* adding one additional channel for timestamp */
> > > > @@ -82,7 +84,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
> > > > static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > > {
> > > > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > > > - u32 sensor_id = sensor->sensor_info->id;
> > > > u32 sensor_config = 0;
> > > > int err;
> > > >
> > > > @@ -92,27 +93,11 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > >
> > > > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > > > SCMI_SENS_CFG_SENSOR_ENABLE);
> > > > -
> > > > - err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
> > > > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > > - &sensor_id, &sensor->sensor_update_nb);
> > > > - if (err) {
> > > > - dev_err(&iio_dev->dev,
> > > > - "Error in registering sensor update notifier for sensor %s err %d",
> > > > - sensor->sensor_info->name, err);
> > > > - return err;
> > > > - }
> > > > -
> > > > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > > > - sensor->sensor_info->id, sensor_config);
> > > > - if (err) {
> > > > - sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > > > - SCMI_PROTOCOL_SENSOR,
> > > > - SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
> > > > - &sensor->sensor_update_nb);
> > > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > > + sensor_config);
> > > > + if (err)
> > > > dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
> > > > sensor->sensor_info->name, err);
> > > > - }
> > > >
> > > > return err;
> > > > }
> > > > @@ -120,25 +105,13 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > > static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
> > > > {
> > > > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > > > - u32 sensor_id = sensor->sensor_info->id;
> > > > u32 sensor_config = 0;
> > > > int err;
> > > >
> > > > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > > > SCMI_SENS_CFG_SENSOR_DISABLE);
> > > > -
> > > > - err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > > > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > > - &sensor_id, &sensor->sensor_update_nb);
> > > > - if (err) {
> > > > - dev_err(&iio_dev->dev,
> > > > - "Error in unregistering sensor update notifier for sensor %s err %d",
> > > > - sensor->sensor_info->name, err);
> > > > - return err;
> > > > - }
> > > > -
> > > > - err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
> > > > - sensor_config);
> > > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > > + sensor_config);
> > > > if (err) {
> > > > dev_err(&iio_dev->dev,
> > > > "Error in disabling sensor %s with err %d",
> > > > @@ -161,8 +134,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > > > u32 sensor_config;
> > > > char buf[32];
> > > >
> > > > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > > > - sensor->sensor_info->id, &sensor_config);
> > > > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > > > + &sensor_config);
> > > > if (err) {
> > > > dev_err(&iio_dev->dev,
> > > > "Error in getting sensor config for sensor %s err %d",
> > > > @@ -208,8 +181,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > > > sensor_config |=
> > > > FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);
> > > >
> > > > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > > > - sensor->sensor_info->id, sensor_config);
> > > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > > + sensor_config);
> > > > if (err)
> > > > dev_err(&iio_dev->dev,
> > > > "Error in setting sensor update interval for sensor %s value %u err %d",
> > > > @@ -274,8 +247,8 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
> > > > u32 sensor_config;
> > > > int mult;
> > > >
> > > > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > > > - sensor->sensor_info->id, &sensor_config);
> > > > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > > > + &sensor_config);
> > > > if (err) {
> > > > dev_err(&iio_dev->dev,
> > > > "Error in getting sensor config for sensor %s err %d",
> > > > @@ -542,15 +515,17 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
> > > > return 0;
> > > > }
> > > >
> > > > -static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > > - struct scmi_handle *handle,
> > > > - const struct scmi_sensor_info *sensor_info)
> > > > +static struct iio_dev *
> > > > +scmi_alloc_iiodev(struct scmi_device *sdev, struct scmi_protocol_handle *ph,
> > > > + const struct scmi_sensor_info *sensor_info)
> > > > {
> > > > struct iio_chan_spec *iio_channels;
> > > > struct scmi_iio_priv *sensor;
> > > > enum iio_modifier modifier;
> > > > enum iio_chan_type type;
> > > > struct iio_dev *iiodev;
> > > > + struct device *dev = &sdev->dev;
> > > > + const struct scmi_handle *handle = sdev->handle;
> > > > int i, ret;
> > > >
> > > > iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
> > > > @@ -560,7 +535,7 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > > iiodev->modes = INDIO_DIRECT_MODE;
> > > > iiodev->dev.parent = dev;
> > > > sensor = iio_priv(iiodev);
> > > > - sensor->handle = handle;
> > > > + sensor->ph = ph;
> > > > sensor->sensor_info = sensor_info;
> > > > sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
> > > > sensor->indio_dev = iiodev;
> > > > @@ -595,6 +570,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > > sensor_info->axis[i].id);
> > > > }
> > > >
> > > > + ret = handle->notify_ops->devm_event_notifier_register(sdev,
> > > > + SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > > + &sensor->sensor_info->id,
> > > > + &sensor->sensor_update_nb);
> > > > + if (ret) {
> > > > + dev_err(&iiodev->dev,
> > > > + "Error in registering sensor update notifier for sensor %s err %d",
> > > > + sensor->sensor_info->name, ret);
> > > > + return ERR_PTR(ret);
> > > > + }
> > > > +
> > > > scmi_iio_set_timestamp_channel(&iio_channels[i], i);
> > > > iiodev->channels = iio_channels;
> > > > return iiodev;
> > > > @@ -604,24 +590,29 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > > > {
> > > > const struct scmi_sensor_info *sensor_info;
> > > > struct scmi_handle *handle = sdev->handle;
> > > > + struct scmi_protocol_handle *ph;
> > > > struct device *dev = &sdev->dev;
> > > > struct iio_dev *scmi_iio_dev;
> > > > u16 nr_sensors;
> > > > int err = -ENODEV, i;
> > > >
> > > > - if (!handle || !handle->sensor_ops) {
> > > > + if (!handle)
> > > > + return -ENODEV;
> > > > +
> > > > + sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
> > > > + if (IS_ERR(sensor_ops)) {
> > > > dev_err(dev, "SCMI device has no sensor interface\n");
> > > > - return -EINVAL;
> > > > + return PTR_ERR(sensor_ops);
> > > > }
> > > >
> > > > - nr_sensors = handle->sensor_ops->count_get(handle);
> > > > + nr_sensors = sensor_ops->count_get(ph);
> > > > if (!nr_sensors) {
> > > > dev_dbg(dev, "0 sensors found via SCMI bus\n");
> > > > return -ENODEV;
> > > > }
> > > >
> > > > for (i = 0; i < nr_sensors; i++) {
> > > > - sensor_info = handle->sensor_ops->info_get(handle, i);
> > > > + sensor_info = sensor_ops->info_get(ph, i);
> > > > if (!sensor_info) {
> > > > dev_err(dev, "SCMI sensor %d has missing info\n", i);
> > > > return -EINVAL;
> > > > @@ -636,7 +627,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > > > sensor_info->axis[0].type != RADIANS_SEC)
> > > > continue;
> > > >
> > > > - scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
> > > > + scmi_iio_dev = scmi_alloc_iiodev(sdev, ph, sensor_info);
> > > > if (IS_ERR(scmi_iio_dev)) {
> > > > dev_err(dev,
> > > > "failed to allocate IIO device for sensor %s: %ld\n",
> > >
>

2021-03-31 12:30:39

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v7 25/38] iio/scmi: port driver to the new scmi_sensor_proto_ops interface

On Wed, 31 Mar 2021 09:32:19 +0100
Cristian Marussi <[email protected]> wrote:

> Hi Jonathan
>
> On Tue, Mar 30, 2021 at 06:34:04PM +0100, Jonathan Cameron wrote:
> > On Tue, 30 Mar 2021 13:51:13 +0100
> > Cristian Marussi <[email protected]> wrote:
> >
> > > Hi Jonathan,
> > >
> > > On Tue, Mar 30, 2021 at 12:33:25PM +0100, Jonathan Cameron wrote:
> > > > On Tue, 16 Mar 2021 12:48:50 +0000
> > > > Cristian Marussi <[email protected]> wrote:
> > > >
> > > > > Port driver to the new SCMI Sensor interface based on protocol handles
> > > > > and common devm_get_ops().
> > > > >
> > > > > Cc: Jyoti Bhayana <[email protected]>
> > > > > Cc: Jonathan Cameron <[email protected]>
> > > > > Signed-off-by: Cristian Marussi <[email protected]>
> > > >
> > > > +CC [email protected]
> > > >
> > > > Rule of thumb if it doesn't go there it ends up in randomly location based
> > > > on other lists and I might not see it for a few weeks :(
> > > >
> > >
> > > Ah sorry, I thought the direct CC was enough.
> >
> > No problem. Too much email :)
> >
> > >
> > > > > ---
> > > > > drivers/iio/common/scmi_sensors/scmi_iio.c | 91 ++++++++++------------
> > > > > 1 file changed, 41 insertions(+), 50 deletions(-)
> > > > >
> > > > > diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > > > index 872d87ca6256..b4bdc3f3a946 100644
> > > > > --- a/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > > > +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c
> > > > > @@ -21,8 +21,10 @@
> > > > >
> > > > > #define SCMI_IIO_NUM_OF_AXIS 3
> > > > >
> > > > > +static const struct scmi_sensor_proto_ops *sensor_ops;
> > > >
> > > > Hmm. I'm not keen on globals when they really should not be necessary.
> > > > They just result in lifetimes being out of sync. Here you are fine because
> > > > you set it to an appropriate value as the first thing you do in probe, and
> > > > I assume the function only ever returns on answer on repeated calls.
> > > >
> > > > Why not put a copy of that pointer inside the struct scmi_iio_priv structures?
> > > >
> > >
> > > The reason for this, as I said to Jyoyi who made the same comment indeed,
> > > from my point of view (maybe wrong..) was that while the protocol_handle,
> > > and previously the handle, are 'per-instance data' (so that you get a
> > > different one each time this driver is possibly probed against a different
> > > platform-handle) and as such are stored in scmi_iio_priv, the _ops are
> > > just plain code pointers and are returned always the same for the same
> > > protocol no matter how many times you probe this driver:
> >
> > As that's the case, I'm a little confused to why you have added the complexity
> > of a query interface in the first place? Why not just export the ops and
> > have the various drivers access them directly? If there is only
> > one set of scmi_sensor_ops etc, then let drivers at it directly, or
> > indeed export the functions that make up the ops structure directly.
> >
> > This sounds like a bit of abstraction that only serves to make the
> > code harder to read.
> >
>
> Thanks for your comments, let me explain a bit.
>
> While the ops are indeed per-protocol common code available to SCMI drivers,
> the protocol handle, which you also obtain with devm_protocol_get(), is
> instead an opaque reference bound to the specific protocol instance
> associated to the platform handle you're using, so that, in case there are
> multiple SCMI platforms defined on the system, you'll get, at each probe a
> specific and distinct protocol_handle to use with your ops: this way
> you'll act upon a completely distinct initialized protocol stack, using
> a distinct underlying transport layer toward your platform of choice.
>
> Since this series wanted to unify SCMI standard and custom protocol interfaces
> and enable modularization too, the get/put abstraction is there indeed to be
> able to track internally protocol users and do resource accounting so that an
> SCMI driver has to explicitly ask to use a protocol: the protocols instances are
> then initialized on demand only when the first user shows up and more importantly
> a hold is put on the protocol module refs avoiding its possible unloading
> while still in use (even though only custom protocol are allowed as loadable
> modules as of now...)
>
> Coming to the ops instead, the reason not to simply export them was...well...
> ...not to export new symbols, and not just to stick to the old handle->ops()
> interface way of non-exporting ops, or because I'm pavid at exporting new symbols
> (I am :D), but because the idea was that in this way it would also have been
> easier for vendors writing custom protocol modules to be able to just use them
> in their own SCMI driver without the need to export also their new custom ops.
> (and same goes generally for any new possible future standard protocol
> which will not require endlessly further exports)

I'll let this rest, but I'm unconvinced. This smacks of reinventing the wheel
and a false layer of abstraction + unnecessary indirection. Current interface
strongly hints that those ops structure pointers are decided at runtime.

For a custom protocol, you will need a header that defines the signatures of
those functions anyway. So you are only one step from just exporting them
and relying on the existing nice module dependency tracking and loading etc.
The only difference is that loading the SCMI driver module would require the
protocol module to be loaded rather than it being based on an instantiation.
(however, I'd hope that the SCMI driver modules are only loaded if we think
there is something there for them to use!)

Now if there was a chance that different providers of a protocols could provide
different _ops structures then this interface might make sense, but then putting
them in a global pointer is the wrong approach because of lifetimes being
mismatched.

Meh, it's your problem to maintain it not mine :)

Jonathan

>
> Just for these reasons I attached the ops retrieval the same protocol_get()
> interface already introduced to handle all of the above.
>
> > > you just end up
> > > calling them against the proper different saved protocol_handle; so it
> > > seemed to me an unneeded duplication to stick a copy of the same _ops
> > > inside each per-instance scmi_iio_priv, and at the same time it seemed
> > > also more straigthforward to access them without too many indirections
> > > from inside the scmi_iio_priv struct).
> > >
> > > But if these are not valid points I can change this in IIO now, and in
> > > the future also in all the other SCMI drivers that currently use this
> > > same API and pattern of usage with global ops. (..at least because I'd
> > > have to collect again all the other ACks agains and it's a bit later for
> > > that now)
> >
> > I'm fine with leaving it as is. There's no fundamental issue, it's just
> > a little bit ugly and I'm fussy :)
> >
>
> I'm not fullly liking it too, but it was the best I could come up to cope
> with the above reqs (and the limited amount of my grey-matter :D)
>
> But if in the future we can come up with something better, or some reqs
> are dropped/revisited I'll be happy to flood the list with another
> jumbo-series.
>
> Thanks
>
> Cristian
>
> > >
> > > Thanks
> > >
> > > Cristian
> > >
> > > > Otherwise this all looks like straight forward refactoring so given the
> > > > above is more a 'bad smell' than a bug and I'm rather late to the game.
> > > >
> > > > Acked-by: Jonathan Cameron <[email protected]>
> > > >
> > > >
> > > > > +
> > > > > struct scmi_iio_priv {
> > > > > - struct scmi_handle *handle;
> > > > > + struct scmi_protocol_handle *ph;
> > > > > const struct scmi_sensor_info *sensor_info;
> > > > > struct iio_dev *indio_dev;
> > > > > /* adding one additional channel for timestamp */
> > > > > @@ -82,7 +84,6 @@ static int scmi_iio_sensor_update_cb(struct notifier_block *nb,
> > > > > static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > > > {
> > > > > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > > > > - u32 sensor_id = sensor->sensor_info->id;
> > > > > u32 sensor_config = 0;
> > > > > int err;
> > > > >
> > > > > @@ -92,27 +93,11 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > > >
> > > > > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > > > > SCMI_SENS_CFG_SENSOR_ENABLE);
> > > > > -
> > > > > - err = sensor->handle->notify_ops->register_event_notifier(sensor->handle,
> > > > > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > > > - &sensor_id, &sensor->sensor_update_nb);
> > > > > - if (err) {
> > > > > - dev_err(&iio_dev->dev,
> > > > > - "Error in registering sensor update notifier for sensor %s err %d",
> > > > > - sensor->sensor_info->name, err);
> > > > > - return err;
> > > > > - }
> > > > > -
> > > > > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > > > > - sensor->sensor_info->id, sensor_config);
> > > > > - if (err) {
> > > > > - sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > > > > - SCMI_PROTOCOL_SENSOR,
> > > > > - SCMI_EVENT_SENSOR_UPDATE, &sensor_id,
> > > > > - &sensor->sensor_update_nb);
> > > > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > > > + sensor_config);
> > > > > + if (err)
> > > > > dev_err(&iio_dev->dev, "Error in enabling sensor %s err %d",
> > > > > sensor->sensor_info->name, err);
> > > > > - }
> > > > >
> > > > > return err;
> > > > > }
> > > > > @@ -120,25 +105,13 @@ static int scmi_iio_buffer_preenable(struct iio_dev *iio_dev)
> > > > > static int scmi_iio_buffer_postdisable(struct iio_dev *iio_dev)
> > > > > {
> > > > > struct scmi_iio_priv *sensor = iio_priv(iio_dev);
> > > > > - u32 sensor_id = sensor->sensor_info->id;
> > > > > u32 sensor_config = 0;
> > > > > int err;
> > > > >
> > > > > sensor_config |= FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
> > > > > SCMI_SENS_CFG_SENSOR_DISABLE);
> > > > > -
> > > > > - err = sensor->handle->notify_ops->unregister_event_notifier(sensor->handle,
> > > > > - SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > > > - &sensor_id, &sensor->sensor_update_nb);
> > > > > - if (err) {
> > > > > - dev_err(&iio_dev->dev,
> > > > > - "Error in unregistering sensor update notifier for sensor %s err %d",
> > > > > - sensor->sensor_info->name, err);
> > > > > - return err;
> > > > > - }
> > > > > -
> > > > > - err = sensor->handle->sensor_ops->config_set(sensor->handle, sensor_id,
> > > > > - sensor_config);
> > > > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > > > + sensor_config);
> > > > > if (err) {
> > > > > dev_err(&iio_dev->dev,
> > > > > "Error in disabling sensor %s with err %d",
> > > > > @@ -161,8 +134,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > > > > u32 sensor_config;
> > > > > char buf[32];
> > > > >
> > > > > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > > > > - sensor->sensor_info->id, &sensor_config);
> > > > > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > > > > + &sensor_config);
> > > > > if (err) {
> > > > > dev_err(&iio_dev->dev,
> > > > > "Error in getting sensor config for sensor %s err %d",
> > > > > @@ -208,8 +181,8 @@ static int scmi_iio_set_odr_val(struct iio_dev *iio_dev, int val, int val2)
> > > > > sensor_config |=
> > > > > FIELD_PREP(SCMI_SENS_CFG_ROUND_MASK, SCMI_SENS_CFG_ROUND_AUTO);
> > > > >
> > > > > - err = sensor->handle->sensor_ops->config_set(sensor->handle,
> > > > > - sensor->sensor_info->id, sensor_config);
> > > > > + err = sensor_ops->config_set(sensor->ph, sensor->sensor_info->id,
> > > > > + sensor_config);
> > > > > if (err)
> > > > > dev_err(&iio_dev->dev,
> > > > > "Error in setting sensor update interval for sensor %s value %u err %d",
> > > > > @@ -274,8 +247,8 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
> > > > > u32 sensor_config;
> > > > > int mult;
> > > > >
> > > > > - int err = sensor->handle->sensor_ops->config_get(sensor->handle,
> > > > > - sensor->sensor_info->id, &sensor_config);
> > > > > + int err = sensor_ops->config_get(sensor->ph, sensor->sensor_info->id,
> > > > > + &sensor_config);
> > > > > if (err) {
> > > > > dev_err(&iio_dev->dev,
> > > > > "Error in getting sensor config for sensor %s err %d",
> > > > > @@ -542,15 +515,17 @@ static int scmi_iio_buffers_setup(struct iio_dev *scmi_iiodev)
> > > > > return 0;
> > > > > }
> > > > >
> > > > > -static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > > > - struct scmi_handle *handle,
> > > > > - const struct scmi_sensor_info *sensor_info)
> > > > > +static struct iio_dev *
> > > > > +scmi_alloc_iiodev(struct scmi_device *sdev, struct scmi_protocol_handle *ph,
> > > > > + const struct scmi_sensor_info *sensor_info)
> > > > > {
> > > > > struct iio_chan_spec *iio_channels;
> > > > > struct scmi_iio_priv *sensor;
> > > > > enum iio_modifier modifier;
> > > > > enum iio_chan_type type;
> > > > > struct iio_dev *iiodev;
> > > > > + struct device *dev = &sdev->dev;
> > > > > + const struct scmi_handle *handle = sdev->handle;
> > > > > int i, ret;
> > > > >
> > > > > iiodev = devm_iio_device_alloc(dev, sizeof(*sensor));
> > > > > @@ -560,7 +535,7 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > > > iiodev->modes = INDIO_DIRECT_MODE;
> > > > > iiodev->dev.parent = dev;
> > > > > sensor = iio_priv(iiodev);
> > > > > - sensor->handle = handle;
> > > > > + sensor->ph = ph;
> > > > > sensor->sensor_info = sensor_info;
> > > > > sensor->sensor_update_nb.notifier_call = scmi_iio_sensor_update_cb;
> > > > > sensor->indio_dev = iiodev;
> > > > > @@ -595,6 +570,17 @@ static struct iio_dev *scmi_alloc_iiodev(struct device *dev,
> > > > > sensor_info->axis[i].id);
> > > > > }
> > > > >
> > > > > + ret = handle->notify_ops->devm_event_notifier_register(sdev,
> > > > > + SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE,
> > > > > + &sensor->sensor_info->id,
> > > > > + &sensor->sensor_update_nb);
> > > > > + if (ret) {
> > > > > + dev_err(&iiodev->dev,
> > > > > + "Error in registering sensor update notifier for sensor %s err %d",
> > > > > + sensor->sensor_info->name, ret);
> > > > > + return ERR_PTR(ret);
> > > > > + }
> > > > > +
> > > > > scmi_iio_set_timestamp_channel(&iio_channels[i], i);
> > > > > iiodev->channels = iio_channels;
> > > > > return iiodev;
> > > > > @@ -604,24 +590,29 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > > > > {
> > > > > const struct scmi_sensor_info *sensor_info;
> > > > > struct scmi_handle *handle = sdev->handle;
> > > > > + struct scmi_protocol_handle *ph;
> > > > > struct device *dev = &sdev->dev;
> > > > > struct iio_dev *scmi_iio_dev;
> > > > > u16 nr_sensors;
> > > > > int err = -ENODEV, i;
> > > > >
> > > > > - if (!handle || !handle->sensor_ops) {
> > > > > + if (!handle)
> > > > > + return -ENODEV;
> > > > > +
> > > > > + sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
> > > > > + if (IS_ERR(sensor_ops)) {
> > > > > dev_err(dev, "SCMI device has no sensor interface\n");
> > > > > - return -EINVAL;
> > > > > + return PTR_ERR(sensor_ops);
> > > > > }
> > > > >
> > > > > - nr_sensors = handle->sensor_ops->count_get(handle);
> > > > > + nr_sensors = sensor_ops->count_get(ph);
> > > > > if (!nr_sensors) {
> > > > > dev_dbg(dev, "0 sensors found via SCMI bus\n");
> > > > > return -ENODEV;
> > > > > }
> > > > >
> > > > > for (i = 0; i < nr_sensors; i++) {
> > > > > - sensor_info = handle->sensor_ops->info_get(handle, i);
> > > > > + sensor_info = sensor_ops->info_get(ph, i);
> > > > > if (!sensor_info) {
> > > > > dev_err(dev, "SCMI sensor %d has missing info\n", i);
> > > > > return -EINVAL;
> > > > > @@ -636,7 +627,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev)
> > > > > sensor_info->axis[0].type != RADIANS_SEC)
> > > > > continue;
> > > > >
> > > > > - scmi_iio_dev = scmi_alloc_iiodev(dev, handle, sensor_info);
> > > > > + scmi_iio_dev = scmi_alloc_iiodev(sdev, ph, sensor_info);
> > > > > if (IS_ERR(scmi_iio_dev)) {
> > > > > dev_err(dev,
> > > > > "failed to allocate IIO device for sensor %s: %ld\n",
> > > >
> >