Commit 07f531b3 authored by Kurt Borja's avatar Kurt Borja Committed by Ilpo Järvinen
Browse files

ACPI: platform_profile: Remove platform_profile_handler from exported 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: default avatarMario Limonciello <mario.limonciello@amd.com>
Signed-off-by: default avatarKurt Borja <kuurtb@gmail.com>
Reviewed-by: default avatarMark Pearson <mpearson-lenovo@squebb.ca>
Tested-by: default avatarMark Pearson <mpearson-lenovo@squebb.ca>
Link: https://lore.kernel.org/r/20250116002721.75592-16-kuurtb@gmail.com


Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
parent 31658c91
Loading
Loading
Loading
Loading
+61 −37
Original line number Diff line number Diff line
@@ -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>
@@ -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,
};

/**
@@ -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");
}
@@ -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);

	err = pprof->ops->probe(drvdata, pprof->choices);
	struct platform_profile_handler *pprof __free(kfree) = kzalloc(
		sizeof(*pprof), GFP_KERNEL);
	if (!pprof)
		return ERR_PTR(-ENOMEM);

	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;
	}

@@ -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);

@@ -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);

+5 −6
Original line number Diff line number Diff line
@@ -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;
};

@@ -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[] = {
+6 −12
Original line number Diff line number Diff line
@@ -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;

/*
@@ -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;

@@ -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);
		}
	}

+1 −1
Original line number Diff line number Diff line
@@ -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;
+6 −11
Original line number Diff line number Diff line
@@ -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)) {
@@ -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);
}
Loading