Skip to content

Commit

Permalink
ACPI: platform_profile: Remove platform_profile_handler from exported…
Browse files Browse the repository at this point in the history
… symbols

In order to protect the platform_profile_handler from API consumers,
allocate it in platform_profile_register() and modify it's signature
accordingly.

Remove the platform_profile_handler from all consumer drivers and
replace them with a pointer to the class device, which is
now returned from platform_profile_register().

Replace *pprof with a pointer to the class device in the rest of
exported symbols.

Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Link: https://lore.kernel.org/r/20250116002721.75592-16-kuurtb@gmail.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
  • Loading branch information
Kurt Borja authored and Ilpo Järvinen committed Jan 17, 2025
1 parent 31658c9 commit 07f531b
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 132 deletions.
98 changes: 61 additions & 37 deletions drivers/acpi/platform_profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/platform_profile.h>
Expand Down Expand Up @@ -212,9 +213,17 @@ static struct attribute *profile_attrs[] = {
};
ATTRIBUTE_GROUPS(profile);

static void pprof_device_release(struct device *dev)
{
struct platform_profile_handler *pprof = to_pprof_handler(dev);

kfree(pprof);
}

static const struct class platform_profile_class = {
.name = "platform-profile",
.dev_groups = profile_groups,
.dev_release = pprof_device_release,
};

/**
Expand Down Expand Up @@ -408,10 +417,10 @@ static const struct attribute_group platform_profile_group = {
.is_visible = profile_class_is_visible,
};

void platform_profile_notify(struct platform_profile_handler *pprof)
void platform_profile_notify(struct device *dev)
{
scoped_cond_guard(mutex_intr, return, &profile_lock) {
_notify_class_profile(&pprof->class_dev, NULL);
_notify_class_profile(dev, NULL);
}
sysfs_notify(acpi_kobj, NULL, "platform_profile");
}
Expand Down Expand Up @@ -460,42 +469,54 @@ int platform_profile_cycle(void)
}
EXPORT_SYMBOL_GPL(platform_profile_cycle);

int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
struct device *platform_profile_register(struct device *dev, const char *name,
void *drvdata,
const struct platform_profile_ops *ops)
{
struct device *ppdev;
int minor;
int err;

/* Sanity check the profile handler */
if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
!pprof->ops->probe) {
pr_err("platform_profile: handler is invalid\n");
return -EINVAL;
}
/* Sanity check */
if (WARN_ON_ONCE(!dev || !name || !ops || !ops->profile_get ||
!ops->profile_set || !ops->probe))
return ERR_PTR(-EINVAL);

struct platform_profile_handler *pprof __free(kfree) = kzalloc(
sizeof(*pprof), GFP_KERNEL);
if (!pprof)
return ERR_PTR(-ENOMEM);

err = pprof->ops->probe(drvdata, pprof->choices);
err = ops->probe(drvdata, pprof->choices);
if (err) {
dev_err(pprof->dev, "platform_profile probe failed\n");
return err;
dev_err(dev, "platform_profile probe failed\n");
return ERR_PTR(err);
}

if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
dev_err(pprof->dev, "Failed to register a platform_profile class device with empty choices\n");
return -EINVAL;
dev_err(dev, "Failed to register platform_profile class device with empty choices\n");
return ERR_PTR(-EINVAL);
}

guard(mutex)(&profile_lock);

/* create class interface for individual handler */
pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
if (pprof->minor < 0)
return pprof->minor;
minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
if (minor < 0)
return ERR_PTR(minor);

pprof->name = name;
pprof->ops = ops;
pprof->minor = minor;
pprof->class_dev.class = &platform_profile_class;
pprof->class_dev.parent = pprof->dev;
pprof->class_dev.parent = dev;
dev_set_drvdata(&pprof->class_dev, drvdata);
dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
err = device_register(&pprof->class_dev);
/* device_register() takes ownership of pprof/ppdev */
ppdev = &no_free_ptr(pprof)->class_dev;
err = device_register(ppdev);
if (err) {
put_device(&pprof->class_dev);
put_device(ppdev);
goto cleanup_ida;
}

Expand All @@ -505,20 +526,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
if (err)
goto cleanup_cur;

return 0;
return ppdev;

cleanup_cur:
device_unregister(&pprof->class_dev);
device_unregister(ppdev);

cleanup_ida:
ida_free(&platform_profile_ida, pprof->minor);
ida_free(&platform_profile_ida, minor);

return err;
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(platform_profile_register);

int platform_profile_remove(struct platform_profile_handler *pprof)
int platform_profile_remove(struct device *dev)
{
struct platform_profile_handler *pprof = to_pprof_handler(dev);
int id;
guard(mutex)(&profile_lock);

Expand All @@ -536,30 +558,32 @@ EXPORT_SYMBOL_GPL(platform_profile_remove);

static void devm_platform_profile_release(struct device *dev, void *res)
{
struct platform_profile_handler **pprof = res;
struct device **ppdev = res;

platform_profile_remove(*pprof);
platform_profile_remove(*ppdev);
}

int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
struct device *devm_platform_profile_register(struct device *dev, const char *name,
void *drvdata,
const struct platform_profile_ops *ops)
{
struct platform_profile_handler **dr;
int ret;
struct device *ppdev;
struct device **dr;

dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL);
if (!dr)
return -ENOMEM;
return ERR_PTR(-ENOMEM);

ret = platform_profile_register(pprof, drvdata);
if (ret) {
ppdev = platform_profile_register(dev, name, drvdata, ops);
if (IS_ERR(ppdev)) {
devres_free(dr);
return ret;
return ppdev;
}

*dr = pprof;
devres_add(pprof->dev, dr);
*dr = ppdev;
devres_add(dev, dr);

return 0;
return ppdev;
}
EXPORT_SYMBOL_GPL(devm_platform_profile_register);

Expand Down
11 changes: 5 additions & 6 deletions drivers/platform/surface/surface_platform_profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct ssam_tmp_profile_info {

struct ssam_platform_profile_device {
struct ssam_device *sdev;
struct platform_profile_handler handler;
struct device *ppdev;
bool has_fan;
};

Expand Down Expand Up @@ -228,13 +228,12 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
tpd->sdev = sdev;
ssam_device_set_drvdata(sdev, tpd);

tpd->handler.name = "Surface Platform Profile";
tpd->handler.dev = &sdev->dev;
tpd->handler.ops = &ssam_platform_profile_ops;

tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");

return devm_platform_profile_register(&tpd->handler, tpd);
tpd->ppdev = devm_platform_profile_register(&sdev->dev, "Surface Platform Profile",
tpd, &ssam_platform_profile_ops);

return PTR_ERR_OR_ZERO(tpd->ppdev);
}

static const struct ssam_device_id ssam_platform_profile_match[] = {
Expand Down
18 changes: 6 additions & 12 deletions drivers/platform/x86/acer-wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ static const struct dmi_system_id non_acer_quirks[] __initconst = {
{}
};

static struct platform_profile_handler platform_profile_handler;
static struct device *platform_profile_device;
static bool platform_profile_support;

/*
Expand Down Expand Up @@ -2073,16 +2073,10 @@ static const struct platform_profile_ops acer_predator_v4_platform_profile_ops =
static int acer_platform_profile_setup(struct platform_device *device)
{
if (quirks->predator_v4) {
int err;

platform_profile_handler.name = "acer-wmi";
platform_profile_handler.dev = &device->dev;
platform_profile_handler.ops =
&acer_predator_v4_platform_profile_ops;

err = devm_platform_profile_register(&platform_profile_handler, NULL);
if (err)
return err;
platform_profile_device = devm_platform_profile_register(
&device->dev, "acer-wmi", NULL, &acer_predator_v4_platform_profile_ops);
if (IS_ERR(platform_profile_device))
return PTR_ERR(platform_profile_device);

platform_profile_support = true;

Expand Down Expand Up @@ -2125,7 +2119,7 @@ static int acer_thermal_profile_change(void)
if (current_tp != acer_predator_v4_max_perf)
last_non_turbo_profile = current_tp;

platform_profile_notify(&platform_profile_handler);
platform_profile_notify(platform_profile_device);
}
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/platform/x86/amd/pmf/pmf.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ struct amd_pmf_dev {
struct mutex lock; /* protects the PMF interface */
u32 supported_func;
enum platform_profile_option current_profile;
struct platform_profile_handler pprof;
struct device *ppdev; /* platform profile class device */
struct dentry *dbgfs_dir;
int hb_interval; /* SBIOS heartbeat interval */
struct delayed_work heart_beat;
Expand Down
17 changes: 6 additions & 11 deletions drivers/platform/x86/amd/pmf/sps.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,6 @@ static const struct platform_profile_ops amd_pmf_profile_ops = {

int amd_pmf_init_sps(struct amd_pmf_dev *dev)
{
int err;

dev->current_profile = PLATFORM_PROFILE_BALANCED;

if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
Expand All @@ -420,15 +418,12 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
amd_pmf_set_sps_power_limits(dev);
}

dev->pprof.name = "amd-pmf";
dev->pprof.dev = dev->dev;
dev->pprof.ops = &amd_pmf_profile_ops;

/* Create platform_profile structure and register */
err = devm_platform_profile_register(&dev->pprof, dev);
if (err)
dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
err);
dev->ppdev = devm_platform_profile_register(dev->dev, "amd-pmf", dev,
&amd_pmf_profile_ops);
if (IS_ERR(dev->ppdev))
dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %ld\n",
PTR_ERR(dev->ppdev));

return err;
return PTR_ERR_OR_ZERO(dev->ppdev);
}
15 changes: 6 additions & 9 deletions drivers/platform/x86/asus-wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ struct asus_wmi {
bool mid_fan_curve_available;
struct fan_curve_data custom_fan_curves[3];

struct platform_profile_handler platform_profile_handler;
struct device *ppdev;
bool platform_profile_support;

// The RSOC controls the maximum charging percentage.
Expand Down Expand Up @@ -3789,7 +3789,7 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
* Ensure that platform_profile updates userspace with the change to ensure
* that platform_profile and throttle_thermal_policy_mode are in sync.
*/
platform_profile_notify(&asus->platform_profile_handler);
platform_profile_notify(asus->ppdev);

return count;
}
Expand Down Expand Up @@ -3891,14 +3891,11 @@ static int platform_profile_setup(struct asus_wmi *asus)

dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");

asus->platform_profile_handler.name = "asus-wmi";
asus->platform_profile_handler.dev = dev;
asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;

err = devm_platform_profile_register(&asus->platform_profile_handler, asus);
if (err) {
asus->ppdev = devm_platform_profile_register(dev, "asus-wmi", asus,
&asus_wmi_platform_profile_ops);
if (IS_ERR(asus->ppdev)) {
dev_err(dev, "Failed to register a platform_profile class device\n");
return err;
return PTR_ERR(asus->ppdev);
}

asus->platform_profile_support = true;
Expand Down
10 changes: 5 additions & 5 deletions drivers/platform/x86/dell/alienware-wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,6 @@ struct wmax_u32_args {

static struct platform_device *platform_device;
static struct color_platform colors[4];
static struct platform_profile_handler pp_handler;
static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST];

static u8 interface;
Expand Down Expand Up @@ -1135,11 +1134,12 @@ static const struct platform_profile_ops awcc_platform_profile_ops = {

static int create_thermal_profile(struct platform_device *platform_device)
{
pp_handler.name = "alienware-wmi";
pp_handler.dev = &platform_device->dev;
pp_handler.ops = &awcc_platform_profile_ops;
struct device *ppdev;

return devm_platform_profile_register(&pp_handler, NULL);
ppdev = devm_platform_profile_register(&platform_device->dev, "alienware-wmi",
NULL, &awcc_platform_profile_ops);

return PTR_ERR_OR_ZERO(ppdev);
}

/*
Expand Down
21 changes: 5 additions & 16 deletions drivers/platform/x86/dell/dell-pc.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ MODULE_DEVICE_TABLE(dmi, dell_device_table);
#define DELL_ACC_SET_FIELD GENMASK(11, 8)
#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)

static struct platform_profile_handler *thermal_handler;

enum thermal_mode_bits {
DELL_BALANCED = BIT(0),
DELL_COOL_BOTTOM = BIT(1),
Expand Down Expand Up @@ -254,6 +252,7 @@ static const struct platform_profile_ops dell_pc_platform_profile_ops = {

static int thermal_init(void)
{
struct device *ppdev;
int ret;

/* If thermal commands are not supported, exit without error */
Expand All @@ -271,25 +270,15 @@ static int thermal_init(void)
if (IS_ERR(platform_device))
return PTR_ERR(platform_device);

thermal_handler = devm_kzalloc(&platform_device->dev, sizeof(*thermal_handler), GFP_KERNEL);
if (!thermal_handler) {
ret = -ENOMEM;
ppdev = devm_platform_profile_register(&platform_device->dev, "dell-pc",
NULL, &dell_pc_platform_profile_ops);
if (IS_ERR(ppdev)) {
ret = PTR_ERR(ppdev);
goto cleanup_platform_device;
}
thermal_handler->name = "dell-pc";
thermal_handler->dev = &platform_device->dev;
thermal_handler->ops = &dell_pc_platform_profile_ops;

/* Clean up if failed */
ret = devm_platform_profile_register(thermal_handler, NULL);
if (ret)
goto cleanup_thermal_handler;

return 0;

cleanup_thermal_handler:
thermal_handler = NULL;

cleanup_platform_device:
platform_device_unregister(platform_device);

Expand Down
Loading

0 comments on commit 07f531b

Please sign in to comment.