[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <29ac489ff4d184c142ad62b56352ad9d5ef019b5.camel@intel.com>
Date: Mon, 18 May 2020 23:18:23 +0000
From: "Pandruvada, Srinivas" <srinivas.pandruvada@...el.com>
To: "matthewgarrett@...gle.com" <matthewgarrett@...gle.com>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
CC: "Zhang, Rui" <rui.zhang@...el.com>,
"linux-pm@...r.kernel.org" <linux-pm@...r.kernel.org>,
"Aram, Nisha" <nisha.aram@...el.com>,
"mjg59@...gle.com" <mjg59@...gle.com>
Subject: Re: [PATCH V2 2/3] thermal/int340x_thermal: Export OEM vendor
variables
On Mon, 2020-04-13 at 19:09 -0700, Matthew Garrett wrote:
> From: Matthew Garrett <mjg59@...gle.com>
>
> The platform vendor may expose an array of OEM-specific values to be
> used
> in determining DPTF policy. These are obtained via the ODVP method,
> and
> then simply exposed in sysfs. In addition, they are updated when a
> notification is received or when the DPTF policy is changed by
> userland.
>
> Signed-off-by: Matthew Garrett <mjg59@...gle.com>
Tested-by: Pandruvada, Srinivas <srinivas.pandruvada@...ux.intel.com>
> ---
> .../intel/int340x_thermal/int3400_thermal.c | 132
> +++++++++++++++++-
> 1 file changed, 131 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
> b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
> index 00a7732724cd0..3919098a73b47 100644
> --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
> +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
> @@ -13,6 +13,7 @@
> #include "acpi_thermal_rel.h"
>
> #define INT3400_THERMAL_TABLE_CHANGED 0x83
> +#define INT3400_ODVP_CHANGED 0x88
>
> enum int3400_thermal_uuid {
> INT3400_THERMAL_PASSIVE_1,
> @@ -41,8 +42,11 @@ static char
> *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = {
> "BE84BABF-C4D4-403D-B495-3128FD44dAC1",
> };
>
> +struct odvp_attr;
> +
> struct int3400_thermal_priv {
> struct acpi_device *adev;
> + struct platform_device *pdev;
> struct thermal_zone_device *thermal;
> int mode;
> int art_count;
> @@ -53,6 +57,17 @@ struct int3400_thermal_priv {
> int rel_misc_dev_res;
> int current_uuid_index;
> char *data_vault;
> + int odvp_count;
> + int *odvp;
> + struct odvp_attr *odvp_attrs;
> +};
> +
> +static int evaluate_odvp(struct int3400_thermal_priv *priv);
> +
> +struct odvp_attr {
> + int odvp;
> + struct int3400_thermal_priv *priv;
> + struct kobj_attribute attr;
> };
>
> static ssize_t data_vault_read(struct file *file, struct kobject
> *kobj,
> @@ -210,9 +225,110 @@ static int int3400_thermal_run_osc(acpi_handle
> handle,
> result = -EPERM;
>
> kfree(context.ret.pointer);
> +
> return result;
> }
>
> +static ssize_t odvp_show(struct kobject *kobj, struct kobj_attribute
> *attr,
> + char *buf)
> +{
> + struct odvp_attr *odvp_attr;
> +
> + odvp_attr = container_of(attr, struct odvp_attr, attr);
> +
> + return sprintf(buf, "%d\n", odvp_attr->priv->odvp[odvp_attr-
> >odvp]);
> +}
> +
> +static void cleanup_odvp(struct int3400_thermal_priv *priv)
> +{
> + int i;
> +
> + if (priv->odvp_attrs) {
> + for (i = 0; i < priv->odvp_count; i++) {
> + sysfs_remove_file(&priv->pdev->dev.kobj,
> + &priv-
> >odvp_attrs[i].attr.attr);
> + kfree(priv->odvp_attrs[i].attr.attr.name);
> + }
> + kfree(priv->odvp_attrs);
> + }
> + kfree(priv->odvp);
> + priv->odvp_count = 0;
> +}
> +
> +static int evaluate_odvp(struct int3400_thermal_priv *priv)
> +{
> + struct acpi_buffer odvp = { ACPI_ALLOCATE_BUFFER, NULL };
> + union acpi_object *obj = NULL;
> + acpi_status status;
> + int i, ret;
> +
> + status = acpi_evaluate_object(priv->adev->handle, "ODVP", NULL,
> &odvp);
> + if (ACPI_FAILURE(status)) {
> + ret = -EINVAL;
> + goto out_err;
> + }
> +
> + obj = odvp.pointer;
> + if (obj->type != ACPI_TYPE_PACKAGE) {
> + ret = -EINVAL;
> + goto out_err;
> + }
> +
> + if (priv->odvp == NULL) {
> + priv->odvp_count = obj->package.count;
> + priv->odvp = kmalloc_array(priv->odvp_count,
> sizeof(int),
> + GFP_KERNEL);
> + if (!priv->odvp) {
> + ret = -ENOMEM;
> + goto out_err;
> + }
> + }
> +
> + if (priv->odvp_attrs == NULL) {
> + priv->odvp_attrs = kcalloc(priv->odvp_count,
> + sizeof(struct odvp_attr),
> + GFP_KERNEL);
> + if (!priv->odvp_attrs) {
> + ret = -ENOMEM;
> + goto out_err;
> + }
> + for (i = 0; i < priv->odvp_count; i++) {
> + struct odvp_attr *odvp = &priv->odvp_attrs[i];
> +
> + sysfs_attr_init(&odvp->attr.attr);
> + odvp->priv = priv;
> + odvp->odvp = i;
> + odvp->attr.attr.name = kasprintf(GFP_KERNEL,
> + "odvp%d", i);
> +
> + if (!odvp->attr.attr.name) {
> + ret = -ENOMEM;
> + goto out_err;
> + }
> + odvp->attr.attr.mode = 0444;
> + odvp->attr.show = odvp_show;
> + odvp->attr.store = NULL;
> + ret = sysfs_create_file(&priv->pdev->dev.kobj,
> + &odvp->attr.attr);
> + if (ret)
> + goto out_err;
> + }
> + }
> +
> + for (i = 0; i < obj->package.count; i++) {
> + if (obj->package.elements[i].type == ACPI_TYPE_INTEGER)
> + priv->odvp[i] = obj-
> >package.elements[i].integer.value;
> + }
> +
> + kfree(obj);
> + return 0;
> +
> +out_err:
> + cleanup_odvp(priv);
> + kfree(obj);
> + return ret;
> +}
> +
> static void int3400_notify(acpi_handle handle,
> u32 event,
> void *data)
> @@ -236,6 +352,9 @@ static void int3400_notify(acpi_handle handle,
> kobject_uevent_env(&priv->thermal->device.kobj,
> KOBJ_CHANGE,
> thermal_prop);
> break;
> + case INT3400_ODVP_CHANGED:
> + evaluate_odvp(priv);
> + break;
> default:
> /* Ignore unknown notification codes sent to INT3400
> device */
> break;
> @@ -285,6 +404,9 @@ static int int3400_thermal_set_mode(struct
> thermal_zone_device *thermal,
> priv-
> >current_uuid_index,
> enable);
> }
> +
> + evaluate_odvp(priv);
> +
> return result;
> }
>
> @@ -336,6 +458,7 @@ static int int3400_thermal_probe(struct
> platform_device *pdev)
> if (!priv)
> return -ENOMEM;
>
> + priv->pdev = pdev;
> priv->adev = adev;
>
> result = int3400_thermal_get_uuids(priv);
> @@ -356,6 +479,8 @@ static int int3400_thermal_probe(struct
> platform_device *pdev)
>
> int3400_setup_gddv(priv);
>
> + evaluate_odvp(priv);
> +
> int3400_thermal_ops.get_mode = int3400_thermal_get_mode;
> int3400_thermal_ops.set_mode = int3400_thermal_set_mode;
>
> @@ -390,8 +515,11 @@ static int int3400_thermal_probe(struct
> platform_device *pdev)
> return 0;
>
> free_sysfs:
> - if (priv->data_vault)
> + cleanup_odvp(priv);
> + if (priv->data_vault) {
> sysfs_remove_group(&pdev->dev.kobj,
> &data_attribute_group);
> + kfree(priv->data_vault);
> + }
> free_uuid:
> sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group);
> free_rel_misc:
> @@ -414,6 +542,8 @@ static int int3400_thermal_remove(struct
> platform_device *pdev)
> priv->adev->handle, ACPI_DEVICE_NOTIFY,
> int3400_notify);
>
> + cleanup_odvp(priv);
> +
> if (!priv->rel_misc_dev_res)
> acpi_thermal_rel_misc_device_remove(priv->adev-
> >handle);
>
Powered by blists - more mailing lists