lkml.org 
[lkml]   [2022]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4/5] firmware: arm_scmi: Add devm_protocol_acquire helper
    Date
    Add a method to get hold of a protocol, causing it to be initialized and
    its resource accounting updated, without getting access to its operations
    and handle.

    Some protocols, like SCMI SystemPower, do not expose any protocol ops to
    the Kernel OSPM agent but still need to be at least initialized: this
    helper avoids the need to invoke a full devm_get_protocol() only to get
    the protocol initialized while throwing away unused the protocol ops and
    handle.

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

    diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
    index 00b7f2aff4ec..7c91fd44baf5 100644
    --- a/drivers/firmware/arm_scmi/driver.c
    +++ b/drivers/firmware/arm_scmi/driver.c
    @@ -1662,6 +1662,30 @@ static void scmi_devm_release_protocol(struct device *dev, void *res)
    scmi_protocol_release(dres->handle, dres->protocol_id);
    }

    +static struct scmi_protocol_instance __must_check *
    +scmi_devres_protocol_instance_get(struct scmi_device *sdev, u8 protocol_id)
    +{
    + struct scmi_protocol_instance *pi;
    + struct scmi_protocol_devres *dres;
    +
    + dres = devres_alloc(scmi_devm_release_protocol,
    + sizeof(*dres), GFP_KERNEL);
    + if (!dres)
    + return ERR_PTR(-ENOMEM);
    +
    + pi = scmi_get_protocol_instance(sdev->handle, protocol_id);
    + if (IS_ERR(pi)) {
    + devres_free(dres);
    + return pi;
    + }
    +
    + dres->handle = sdev->handle;
    + dres->protocol_id = protocol_id;
    + devres_add(&sdev->dev, dres);
    +
    + return pi;
    +}
    +
    /**
    * scmi_devm_protocol_get - Devres managed get protocol operations and handle
    * @sdev: A reference to an scmi_device whose embedded struct device is to
    @@ -1685,32 +1709,47 @@ scmi_devm_protocol_get(struct scmi_device *sdev, u8 protocol_id,
    struct scmi_protocol_handle **ph)
    {
    struct scmi_protocol_instance *pi;
    - struct scmi_protocol_devres *dres;
    - struct scmi_handle *handle = sdev->handle;

    if (!ph)
    return ERR_PTR(-EINVAL);

    - dres = devres_alloc(scmi_devm_release_protocol,
    - sizeof(*dres), GFP_KERNEL);
    - if (!dres)
    - return ERR_PTR(-ENOMEM);
    -
    - pi = scmi_get_protocol_instance(handle, protocol_id);
    - if (IS_ERR(pi)) {
    - devres_free(dres);
    + pi = scmi_devres_protocol_instance_get(sdev, protocol_id);
    + if (IS_ERR(pi))
    return pi;
    - }
    -
    - dres->handle = handle;
    - dres->protocol_id = protocol_id;
    - devres_add(&sdev->dev, dres);

    *ph = &pi->ph;

    return pi->proto->ops;
    }

    +/**
    + * scmi_devm_protocol_acquire - Devres managed helper to get hold of a protocol
    + * @sdev: A reference to an scmi_device whose embedded struct device is to
    + * be used for devres accounting.
    + * @protocol_id: The protocol being requested.
    + *
    + * Get hold of a protocol accounting for its usage, possibly triggering its
    + * initialization but without getting access to its protocol specific operations
    + * and handle.
    + *
    + * Being a devres based managed method, protocol hold will be automatically
    + * released, and possibly de-initialized on last user, once the SCMI driver
    + * owning the scmi_device is unbound from it.
    + *
    + * Return: 0 on SUCCESS
    + */
    +static int __must_check scmi_devm_protocol_acquire(struct scmi_device *sdev,
    + u8 protocol_id)
    +{
    + struct scmi_protocol_instance *pi;
    +
    + pi = scmi_devres_protocol_instance_get(sdev, protocol_id);
    + if (IS_ERR(pi))
    + return PTR_ERR(pi);
    +
    + return 0;
    +}
    +
    static int scmi_devm_protocol_match(struct device *dev, void *res, void *data)
    {
    struct scmi_protocol_devres *dres = res;
    @@ -2297,6 +2336,7 @@ static int scmi_probe(struct platform_device *pdev)
    handle = &info->handle;
    handle->dev = info->dev;
    handle->version = &info->version;
    + handle->devm_protocol_acquire = scmi_devm_protocol_acquire;
    handle->devm_protocol_get = scmi_devm_protocol_get;
    handle->devm_protocol_put = scmi_devm_protocol_put;

    diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
    index 37d8603816c2..1846b4a870cf 100644
    --- a/include/linux/scmi_protocol.h
    +++ b/include/linux/scmi_protocol.h
    @@ -734,6 +734,9 @@ struct scmi_notify_ops {
    *
    * @dev: pointer to the SCMI device
    * @version: pointer to the structure containing SCMI version information
    + * @devm_protocol_acquire: devres managed method to get hold of a protocol,
    + * causing its initialization and related resource
    + * accounting
    * @devm_protocol_get: devres managed method to acquire a protocol and get specific
    * operations and a dedicated protocol handler
    * @devm_protocol_put: devres managed method to release a protocol
    @@ -752,6 +755,8 @@ struct scmi_handle {
    struct device *dev;
    struct scmi_revision_info *version;

    + int __must_check (*devm_protocol_acquire)(struct scmi_device *sdev,
    + u8 proto);
    const void __must_check *
    (*devm_protocol_get)(struct scmi_device *sdev, u8 proto,
    struct scmi_protocol_handle **ph);
    --
    2.32.0
    \
     
     \ /
      Last update: 2022-06-23 14:49    [W:2.750 / U:0.096 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site