Message ID | 20250109150731.110799-15-kuurtb@gmail.com (mailing list archive) |
---|---|
State | Changes Requested, archived |
Headers | show |
Series | Hide platform_profile_handler from consumers | expand |
On 1/9/2025 09:06, Kurt Borja wrote: > 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. > > Signed-off-by: Kurt Borja <kuurtb@gmail.com> > --- > drivers/acpi/platform_profile.c | 93 ++++++++++++------- > .../surface/surface_platform_profile.c | 11 +-- > drivers/platform/x86/acer-wmi.c | 18 ++-- > drivers/platform/x86/amd/pmf/pmf.h | 2 +- > drivers/platform/x86/amd/pmf/sps.c | 15 +-- > drivers/platform/x86/asus-wmi.c | 17 ++-- > drivers/platform/x86/dell/alienware-wmi.c | 10 +- > drivers/platform/x86/dell/dell-pc.c | 22 ++--- > drivers/platform/x86/hp/hp-wmi.c | 19 ++-- > drivers/platform/x86/ideapad-laptop.c | 14 +-- > .../platform/x86/inspur_platform_profile.c | 9 +- > drivers/platform/x86/thinkpad_acpi.c | 14 +-- > include/linux/platform_profile.h | 12 ++- > 13 files changed, 131 insertions(+), 125 deletions(-) > > diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c > index 5a867b912964..fdf79b81b62e 100644 > --- a/drivers/acpi/platform_profile.c > +++ b/drivers/acpi/platform_profile.c > @@ -3,6 +3,7 @@ > /* Platform profile sysfs interface */ > > #include <linux/acpi.h> > +#include <linux/cleanup.h> > #include <linux/bits.h> > #include <linux/init.h> > #include <linux/kdev_t.h> > @@ -213,9 +214,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, > }; > > /** > @@ -409,10 +418,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"); > } > @@ -461,40 +470,57 @@ 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->choices) { > + /* Sanity check */ > + if (!dev || !name || !ops || !ops->profile_get || > + !ops->profile_set || !ops->choices) { > pr_err("platform_profile: handler is invalid\n"); > - return -EINVAL; > + return ERR_PTR(-EINVAL); > } > > - err = pprof->ops->choices(pprof); > + struct platform_profile_handler *pprof __free(kfree) = kzalloc( > + sizeof(*pprof), GFP_KERNEL); > + if (!pprof) > + return ERR_PTR(-ENOMEM); > + > + err = ops->choices(pprof); > if (err < 0) > - return err; > + return ERR_PTR(err); > > if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) { > pr_err("platform_profile: no available profiles\n"); > - return -EINVAL; > + 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); > - if (err) > + if (err) { > + put_device(&no_free_ptr(pprof)->class_dev); > goto cleanup_ida; > + } > + > + /* After this point, device_unregister will free pprof on error */ > + ppdev = &no_free_ptr(pprof)->class_dev; > > sysfs_notify(acpi_kobj, NULL, "platform_profile"); > > @@ -502,20 +528,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); > > @@ -533,30 +560,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(dev)) { > 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); > > diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c > index efb6653ed1d5..965940223892 100644 > --- a/drivers/platform/surface/surface_platform_profile.c > +++ b/drivers/platform/surface/surface_platform_profile.c > @@ -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[] = { > diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c > index 70ec667e0cbf..2059b29dd36b 100644 > --- a/drivers/platform/x86/acer-wmi.c > +++ b/drivers/platform/x86/acer-wmi.c > @@ -742,7 +742,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; > > /* > @@ -1921,16 +1921,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; > > @@ -2017,7 +2011,7 @@ static int acer_thermal_profile_change(void) > if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI) > last_non_turbo_profile = tp; > > - platform_profile_notify(&platform_profile_handler); > + platform_profile_notify(platform_profile_device); > } > > return 0; > diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h > index 198bfe3306be..3806f9efaff8 100644 > --- a/drivers/platform/x86/amd/pmf/pmf.h > +++ b/drivers/platform/x86/amd/pmf/pmf.h > @@ -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; > diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c > index 4f80a73eff9f..e8d2de9bb646 100644 > --- a/drivers/platform/x86/amd/pmf/sps.c > +++ b/drivers/platform/x86/amd/pmf/sps.c > @@ -420,15 +420,16 @@ 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->ppdev = devm_platform_profile_register( > + dev->dev, "amd-pmf", dev, &amd_pmf_profile_ops); > + if (IS_ERR(dev->ppdev)) { > + err = PTR_ERR(dev->ppdev); > dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n", > err); > > - return err; > + return err; > + } > + > + return 0; Maybe instead of: if (IS_ERR()) { err = PTR_ERR(); dev_err(); return err; } return 0; You do this: if (IS_ERR()) { err = PTR_ERR(); dev_err(); } return err; > } > diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c > index 5c7099dc6109..809ab0353b68 100644 > --- a/drivers/platform/x86/asus-wmi.c > +++ b/drivers/platform/x86/asus-wmi.c > @@ -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 *platform_profile_device; > bool platform_profile_support; > > // The RSOC controls the maximum charging percentage. > @@ -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->platform_profile_device); > > return count; > } > @@ -3891,15 +3891,10 @@ 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 == -EEXIST) { > - pr_warn("%s, a platform_profile handler is already registered\n", __func__); > - return 0; > - } else if (err) { > + asus->platform_profile_device = devm_platform_profile_register( > + dev, "asus-wmi", asus, &asus_wmi_platform_profile_ops); > + if (IS_ERR(asus->platform_profile_device)) { > + err = PTR_ERR(asus->platform_profile_device); > pr_err("%s, failed at devm_platform_profile_register: %d\n", __func__, err); > return err; > } > diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c > index a8961de004ab..1eaa746eb4f1 100644 > --- a/drivers/platform/x86/dell/alienware-wmi.c > +++ b/drivers/platform/x86/dell/alienware-wmi.c > @@ -414,7 +414,6 @@ static struct platform_device *platform_device; > static struct device_attribute *zone_dev_attrs; > static struct attribute **zone_attrs; > static struct platform_zone *zone_data; > -static struct platform_profile_handler pp_handler; > static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST]; > > static struct platform_driver platform_driver = { > @@ -1165,11 +1164,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); > } > > static int __init alienware_wmi_init(void) > diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c > index dda6f13295e8..4ff80ed4f157 100644 > --- a/drivers/platform/x86/dell/dell-pc.c > +++ b/drivers/platform/x86/dell/dell-pc.c > @@ -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), > @@ -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 */ > @@ -271,26 +270,17 @@ 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; > - 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) > + 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_thermal_handler; > + } > > return 0; > > cleanup_thermal_handler: > - thermal_handler = NULL; > - > -cleanup_platform_device: > platform_device_unregister(platform_device); > > return ret; > diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c > index 8a620d36f926..1b9e176f8d6f 100644 > --- a/drivers/platform/x86/hp/hp-wmi.c > +++ b/drivers/platform/x86/hp/hp-wmi.c > @@ -273,7 +273,7 @@ static DEFINE_MUTEX(active_platform_profile_lock); > static struct input_dev *hp_wmi_input_dev; > static struct input_dev *camera_shutter_input_dev; > static struct platform_device *hp_wmi_platform_dev; > -static struct platform_profile_handler platform_profile_handler; > +static struct device *platform_profile_device; > static struct notifier_block platform_power_source_nb; > static enum platform_profile_option active_platform_profile; > static bool platform_profile_support; > @@ -1602,6 +1602,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = { > > static int thermal_profile_setup(struct platform_device *device) > { > + const struct platform_profile_ops *ops; > int err, tp; > > if (is_omen_thermal_profile()) { > @@ -1617,7 +1618,7 @@ static int thermal_profile_setup(struct platform_device *device) > if (err < 0) > return err; > > - platform_profile_handler.ops = &platform_profile_omen_ops; > + ops = &platform_profile_omen_ops; > } else if (is_victus_thermal_profile()) { > err = platform_profile_victus_get_ec(&active_platform_profile); > if (err < 0) > @@ -1631,7 +1632,7 @@ static int thermal_profile_setup(struct platform_device *device) > if (err < 0) > return err; > > - platform_profile_handler.ops = &platform_profile_victus_ops; > + ops = &platform_profile_victus_ops; > } else { > tp = thermal_profile_get(); > > @@ -1646,15 +1647,13 @@ static int thermal_profile_setup(struct platform_device *device) > if (err) > return err; > > - platform_profile_handler.ops = &hp_wmi_platform_profile_ops; > + ops = &hp_wmi_platform_profile_ops; > } > > - platform_profile_handler.name = "hp-wmi"; > - platform_profile_handler.dev = &device->dev; > - > - err = devm_platform_profile_register(&platform_profile_handler, NULL); > - if (err) > - return err; > + platform_profile_device = devm_platform_profile_register( > + &device->dev, "hp-wmi", NULL, ops); > + if (IS_ERR(platform_profile_device)) > + return PTR_ERR(platform_profile_device); > > platform_profile_support = true; > > diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c > index d34d565172f5..55aac0190624 100644 > --- a/drivers/platform/x86/ideapad-laptop.c > +++ b/drivers/platform/x86/ideapad-laptop.c > @@ -142,7 +142,7 @@ enum { > > struct ideapad_dytc_priv { > enum platform_profile_option current_profile; > - struct platform_profile_handler pprof; > + struct device *ppdev; /* platform profile device */ > struct mutex mutex; /* protects the DYTC interface */ > struct ideapad_private *priv; > }; > @@ -1050,7 +1050,7 @@ static void dytc_profile_refresh(struct ideapad_private *priv) > > if (profile != priv->dytc->current_profile) { > priv->dytc->current_profile = profile; > - platform_profile_notify(&priv->dytc->pprof); > + platform_profile_notify(priv->dytc->ppdev); > } > } > > @@ -1117,15 +1117,15 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv) > > mutex_init(&priv->dytc->mutex); > > - priv->dytc->pprof.name = "ideapad-laptop"; > - priv->dytc->pprof.dev = &priv->platform_device->dev; > priv->dytc->priv = priv; > - priv->dytc->pprof.ops = &dytc_profile_ops; > > /* Create platform_profile structure and register */ > - err = devm_platform_profile_register(&priv->dytc->pprof, &priv->dytc); > - if (err) > + priv->dytc->ppdev = devm_platform_profile_register( > + &priv->platform_device->dev, "ideapad-laptop", &priv->dytc, &dytc_profile_ops); > + if (IS_ERR(priv->dytc->ppdev)) { > + err = PTR_ERR(priv->dytc->ppdev); > goto pp_reg_failed; > + } > > /* Ensure initial values are correct */ > dytc_profile_refresh(priv); > diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c > index 543e4bce1a57..9e2f24de0207 100644 > --- a/drivers/platform/x86/inspur_platform_profile.c > +++ b/drivers/platform/x86/inspur_platform_profile.c > @@ -32,7 +32,7 @@ enum inspur_tmp_profile { > > struct inspur_wmi_priv { > struct wmi_device *wdev; > - struct platform_profile_handler handler; > + struct device *ppdev; > }; > > static int inspur_wmi_perform_query(struct wmi_device *wdev, > @@ -190,11 +190,10 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context) > priv->wdev = wdev; > dev_set_drvdata(&wdev->dev, priv); > > - priv->handler.name = "inspur-wmi"; > - priv->handler.dev = &wdev->dev; > - priv->handler.ops = &inspur_platform_profile_ops; > + priv->ppdev = devm_platform_profile_register( > + &wdev->dev, "inspur-wmi", priv, &inspur_platform_profile_ops); > > - return devm_platform_profile_register(&priv->handler, priv); > + return PTR_ERR_OR_ZERO(priv->ppdev); > } > > static const struct wmi_device_id inspur_wmi_id_table[] = { > diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c > index a0b8987bc328..964f842ef756 100644 > --- a/drivers/platform/x86/thinkpad_acpi.c > +++ b/drivers/platform/x86/thinkpad_acpi.c > @@ -962,6 +962,7 @@ static const struct proc_ops dispatch_proc_ops = { > static struct platform_device *tpacpi_pdev; > static struct platform_device *tpacpi_sensors_pdev; > static struct device *tpacpi_hwmon; > +static struct device *tpacpi_pprof; > static struct input_dev *tpacpi_inputdev; > static struct mutex tpacpi_inputdev_send_mutex; > static LIST_HEAD(tpacpi_all_drivers); > @@ -10553,11 +10554,6 @@ static const struct platform_profile_ops dytc_profile_ops = { > .choices = dytc_profile_choices, > }; > > -static struct platform_profile_handler dytc_profile = { > - .name = "thinkpad-acpi", > - .ops = &dytc_profile_ops, > -}; > - > static void dytc_profile_refresh(void) > { > enum platform_profile_option profile; > @@ -10586,7 +10582,7 @@ static void dytc_profile_refresh(void) > err = convert_dytc_to_profile(funcmode, perfmode, &profile); > if (!err && profile != dytc_current_profile) { > dytc_current_profile = profile; > - platform_profile_notify(&dytc_profile); > + platform_profile_notify(tpacpi_pprof); > } > } > > @@ -10647,14 +10643,14 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) > dbg_printk(TPACPI_DBG_INIT, > "DYTC version %d: thermal mode available\n", dytc_version); > > - dytc_profile.dev = &tpacpi_pdev->dev; > /* Create platform_profile structure and register */ > - err = devm_platform_profile_register(&dytc_profile, NULL); > + tpacpi_pprof = devm_platform_profile_register( > + &tpacpi_pdev->dev, "thinkpad-acpi", NULL, &dytc_profile_ops); > /* > * If for some reason platform_profiles aren't enabled > * don't quit terminally. > */ > - if (err) > + if (IS_ERR(tpacpi_pprof)) > return -ENODEV; > > /* Ensure initial values are correct */ > diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h > index cadbd3168d84..97ce9bd476ab 100644 > --- a/include/linux/platform_profile.h > +++ b/include/linux/platform_profile.h > @@ -47,10 +47,14 @@ struct platform_profile_handler { > const struct platform_profile_ops *ops; > }; > > -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata); > -int platform_profile_remove(struct platform_profile_handler *pprof); > -int devm_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); > +int platform_profile_remove(struct device *dev); > +struct device *devm_platform_profile_register(struct device *dev, const char *name, > + void *drvdata, > + const struct platform_profile_ops *ops); > int platform_profile_cycle(void); > -void platform_profile_notify(struct platform_profile_handler *pprof); > +void platform_profile_notify(struct device *dev); > > #endif /*_PLATFORM_PROFILE_H_*/
On Thu, Jan 09, 2025 at 10:45:38AM -0600, Mario Limonciello wrote: > On 1/9/2025 09:06, Kurt Borja wrote: > > 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. > > > > Signed-off-by: Kurt Borja <kuurtb@gmail.com> > > --- > > drivers/acpi/platform_profile.c | 93 ++++++++++++------- > > .../surface/surface_platform_profile.c | 11 +-- > > drivers/platform/x86/acer-wmi.c | 18 ++-- > > drivers/platform/x86/amd/pmf/pmf.h | 2 +- > > drivers/platform/x86/amd/pmf/sps.c | 15 +-- > > drivers/platform/x86/asus-wmi.c | 17 ++-- > > drivers/platform/x86/dell/alienware-wmi.c | 10 +- > > drivers/platform/x86/dell/dell-pc.c | 22 ++--- > > drivers/platform/x86/hp/hp-wmi.c | 19 ++-- > > drivers/platform/x86/ideapad-laptop.c | 14 +-- > > .../platform/x86/inspur_platform_profile.c | 9 +- > > drivers/platform/x86/thinkpad_acpi.c | 14 +-- > > include/linux/platform_profile.h | 12 ++- > > 13 files changed, 131 insertions(+), 125 deletions(-) > > > > diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c > > index 5a867b912964..fdf79b81b62e 100644 > > --- a/drivers/acpi/platform_profile.c > > +++ b/drivers/acpi/platform_profile.c > > @@ -3,6 +3,7 @@ > > /* Platform profile sysfs interface */ > > #include <linux/acpi.h> > > +#include <linux/cleanup.h> > > #include <linux/bits.h> > > #include <linux/init.h> > > #include <linux/kdev_t.h> > > @@ -213,9 +214,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, > > }; > > /** > > @@ -409,10 +418,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"); > > } > > @@ -461,40 +470,57 @@ 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->choices) { > > + /* Sanity check */ > > + if (!dev || !name || !ops || !ops->profile_get || > > + !ops->profile_set || !ops->choices) { > > pr_err("platform_profile: handler is invalid\n"); > > - return -EINVAL; > > + return ERR_PTR(-EINVAL); > > } > > - err = pprof->ops->choices(pprof); > > + struct platform_profile_handler *pprof __free(kfree) = kzalloc( > > + sizeof(*pprof), GFP_KERNEL); > > + if (!pprof) > > + return ERR_PTR(-ENOMEM); > > + > > + err = ops->choices(pprof); > > if (err < 0) > > - return err; > > + return ERR_PTR(err); > > if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) { > > pr_err("platform_profile: no available profiles\n"); > > - return -EINVAL; > > + 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); > > - if (err) > > + if (err) { > > + put_device(&no_free_ptr(pprof)->class_dev); > > goto cleanup_ida; > > + } > > + > > + /* After this point, device_unregister will free pprof on error */ > > + ppdev = &no_free_ptr(pprof)->class_dev; > > sysfs_notify(acpi_kobj, NULL, "platform_profile"); > > @@ -502,20 +528,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); > > @@ -533,30 +560,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(dev)) { > > 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); > > diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c > > index efb6653ed1d5..965940223892 100644 > > --- a/drivers/platform/surface/surface_platform_profile.c > > +++ b/drivers/platform/surface/surface_platform_profile.c > > @@ -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[] = { > > diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c > > index 70ec667e0cbf..2059b29dd36b 100644 > > --- a/drivers/platform/x86/acer-wmi.c > > +++ b/drivers/platform/x86/acer-wmi.c > > @@ -742,7 +742,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; > > /* > > @@ -1921,16 +1921,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; > > @@ -2017,7 +2011,7 @@ static int acer_thermal_profile_change(void) > > if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI) > > last_non_turbo_profile = tp; > > - platform_profile_notify(&platform_profile_handler); > > + platform_profile_notify(platform_profile_device); > > } > > return 0; > > diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h > > index 198bfe3306be..3806f9efaff8 100644 > > --- a/drivers/platform/x86/amd/pmf/pmf.h > > +++ b/drivers/platform/x86/amd/pmf/pmf.h > > @@ -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; > > diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c > > index 4f80a73eff9f..e8d2de9bb646 100644 > > --- a/drivers/platform/x86/amd/pmf/sps.c > > +++ b/drivers/platform/x86/amd/pmf/sps.c > > @@ -420,15 +420,16 @@ 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->ppdev = devm_platform_profile_register( > > + dev->dev, "amd-pmf", dev, &amd_pmf_profile_ops); > > + if (IS_ERR(dev->ppdev)) { > > + err = PTR_ERR(dev->ppdev); > > dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n", > > err); > > - return err; > > + return err; > > + } > > + > > + return 0; > > Maybe instead of: > > if (IS_ERR()) { > err = PTR_ERR(); > dev_err(); > return err; > } > > return 0; > > You do this: > > if (IS_ERR()) { > err = PTR_ERR(); > dev_err(); > } > > return err; Ack. > > > > } > > diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c > > index 5c7099dc6109..809ab0353b68 100644 > > --- a/drivers/platform/x86/asus-wmi.c > > +++ b/drivers/platform/x86/asus-wmi.c > > @@ -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 *platform_profile_device; > > bool platform_profile_support; > > // The RSOC controls the maximum charging percentage. > > @@ -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->platform_profile_device); > > return count; > > } > > @@ -3891,15 +3891,10 @@ 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 == -EEXIST) { > > - pr_warn("%s, a platform_profile handler is already registered\n", __func__); > > - return 0; > > - } else if (err) { > > + asus->platform_profile_device = devm_platform_profile_register( > > + dev, "asus-wmi", asus, &asus_wmi_platform_profile_ops); > > + if (IS_ERR(asus->platform_profile_device)) { > > + err = PTR_ERR(asus->platform_profile_device); > > pr_err("%s, failed at devm_platform_profile_register: %d\n", __func__, err); > > return err; > > } > > diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c > > index a8961de004ab..1eaa746eb4f1 100644 > > --- a/drivers/platform/x86/dell/alienware-wmi.c > > +++ b/drivers/platform/x86/dell/alienware-wmi.c > > @@ -414,7 +414,6 @@ static struct platform_device *platform_device; > > static struct device_attribute *zone_dev_attrs; > > static struct attribute **zone_attrs; > > static struct platform_zone *zone_data; > > -static struct platform_profile_handler pp_handler; > > static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST]; > > static struct platform_driver platform_driver = { > > @@ -1165,11 +1164,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); > > } > > static int __init alienware_wmi_init(void) > > diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c > > index dda6f13295e8..4ff80ed4f157 100644 > > --- a/drivers/platform/x86/dell/dell-pc.c > > +++ b/drivers/platform/x86/dell/dell-pc.c > > @@ -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), > > @@ -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 */ > > @@ -271,26 +270,17 @@ 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; > > - 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) > > + 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_thermal_handler; > > + } > > return 0; > > cleanup_thermal_handler: > > - thermal_handler = NULL; > > - > > -cleanup_platform_device: > > platform_device_unregister(platform_device); > > return ret; > > diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c > > index 8a620d36f926..1b9e176f8d6f 100644 > > --- a/drivers/platform/x86/hp/hp-wmi.c > > +++ b/drivers/platform/x86/hp/hp-wmi.c > > @@ -273,7 +273,7 @@ static DEFINE_MUTEX(active_platform_profile_lock); > > static struct input_dev *hp_wmi_input_dev; > > static struct input_dev *camera_shutter_input_dev; > > static struct platform_device *hp_wmi_platform_dev; > > -static struct platform_profile_handler platform_profile_handler; > > +static struct device *platform_profile_device; > > static struct notifier_block platform_power_source_nb; > > static enum platform_profile_option active_platform_profile; > > static bool platform_profile_support; > > @@ -1602,6 +1602,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = { > > static int thermal_profile_setup(struct platform_device *device) > > { > > + const struct platform_profile_ops *ops; > > int err, tp; > > if (is_omen_thermal_profile()) { > > @@ -1617,7 +1618,7 @@ static int thermal_profile_setup(struct platform_device *device) > > if (err < 0) > > return err; > > - platform_profile_handler.ops = &platform_profile_omen_ops; > > + ops = &platform_profile_omen_ops; > > } else if (is_victus_thermal_profile()) { > > err = platform_profile_victus_get_ec(&active_platform_profile); > > if (err < 0) > > @@ -1631,7 +1632,7 @@ static int thermal_profile_setup(struct platform_device *device) > > if (err < 0) > > return err; > > - platform_profile_handler.ops = &platform_profile_victus_ops; > > + ops = &platform_profile_victus_ops; > > } else { > > tp = thermal_profile_get(); > > @@ -1646,15 +1647,13 @@ static int thermal_profile_setup(struct platform_device *device) > > if (err) > > return err; > > - platform_profile_handler.ops = &hp_wmi_platform_profile_ops; > > + ops = &hp_wmi_platform_profile_ops; > > } > > - platform_profile_handler.name = "hp-wmi"; > > - platform_profile_handler.dev = &device->dev; > > - > > - err = devm_platform_profile_register(&platform_profile_handler, NULL); > > - if (err) > > - return err; > > + platform_profile_device = devm_platform_profile_register( > > + &device->dev, "hp-wmi", NULL, ops); > > + if (IS_ERR(platform_profile_device)) > > + return PTR_ERR(platform_profile_device); > > platform_profile_support = true; > > diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c > > index d34d565172f5..55aac0190624 100644 > > --- a/drivers/platform/x86/ideapad-laptop.c > > +++ b/drivers/platform/x86/ideapad-laptop.c > > @@ -142,7 +142,7 @@ enum { > > struct ideapad_dytc_priv { > > enum platform_profile_option current_profile; > > - struct platform_profile_handler pprof; > > + struct device *ppdev; /* platform profile device */ > > struct mutex mutex; /* protects the DYTC interface */ > > struct ideapad_private *priv; > > }; > > @@ -1050,7 +1050,7 @@ static void dytc_profile_refresh(struct ideapad_private *priv) > > if (profile != priv->dytc->current_profile) { > > priv->dytc->current_profile = profile; > > - platform_profile_notify(&priv->dytc->pprof); > > + platform_profile_notify(priv->dytc->ppdev); > > } > > } > > @@ -1117,15 +1117,15 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv) > > mutex_init(&priv->dytc->mutex); > > - priv->dytc->pprof.name = "ideapad-laptop"; > > - priv->dytc->pprof.dev = &priv->platform_device->dev; > > priv->dytc->priv = priv; > > - priv->dytc->pprof.ops = &dytc_profile_ops; > > /* Create platform_profile structure and register */ > > - err = devm_platform_profile_register(&priv->dytc->pprof, &priv->dytc); > > - if (err) > > + priv->dytc->ppdev = devm_platform_profile_register( > > + &priv->platform_device->dev, "ideapad-laptop", &priv->dytc, &dytc_profile_ops); > > + if (IS_ERR(priv->dytc->ppdev)) { > > + err = PTR_ERR(priv->dytc->ppdev); > > goto pp_reg_failed; > > + } > > /* Ensure initial values are correct */ > > dytc_profile_refresh(priv); > > diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c > > index 543e4bce1a57..9e2f24de0207 100644 > > --- a/drivers/platform/x86/inspur_platform_profile.c > > +++ b/drivers/platform/x86/inspur_platform_profile.c > > @@ -32,7 +32,7 @@ enum inspur_tmp_profile { > > struct inspur_wmi_priv { > > struct wmi_device *wdev; > > - struct platform_profile_handler handler; > > + struct device *ppdev; > > }; > > static int inspur_wmi_perform_query(struct wmi_device *wdev, > > @@ -190,11 +190,10 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context) > > priv->wdev = wdev; > > dev_set_drvdata(&wdev->dev, priv); > > - priv->handler.name = "inspur-wmi"; > > - priv->handler.dev = &wdev->dev; > > - priv->handler.ops = &inspur_platform_profile_ops; > > + priv->ppdev = devm_platform_profile_register( > > + &wdev->dev, "inspur-wmi", priv, &inspur_platform_profile_ops); > > - return devm_platform_profile_register(&priv->handler, priv); > > + return PTR_ERR_OR_ZERO(priv->ppdev); > > } > > static const struct wmi_device_id inspur_wmi_id_table[] = { > > diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c > > index a0b8987bc328..964f842ef756 100644 > > --- a/drivers/platform/x86/thinkpad_acpi.c > > +++ b/drivers/platform/x86/thinkpad_acpi.c > > @@ -962,6 +962,7 @@ static const struct proc_ops dispatch_proc_ops = { > > static struct platform_device *tpacpi_pdev; > > static struct platform_device *tpacpi_sensors_pdev; > > static struct device *tpacpi_hwmon; > > +static struct device *tpacpi_pprof; > > static struct input_dev *tpacpi_inputdev; > > static struct mutex tpacpi_inputdev_send_mutex; > > static LIST_HEAD(tpacpi_all_drivers); > > @@ -10553,11 +10554,6 @@ static const struct platform_profile_ops dytc_profile_ops = { > > .choices = dytc_profile_choices, > > }; > > -static struct platform_profile_handler dytc_profile = { > > - .name = "thinkpad-acpi", > > - .ops = &dytc_profile_ops, > > -}; > > - > > static void dytc_profile_refresh(void) > > { > > enum platform_profile_option profile; > > @@ -10586,7 +10582,7 @@ static void dytc_profile_refresh(void) > > err = convert_dytc_to_profile(funcmode, perfmode, &profile); > > if (!err && profile != dytc_current_profile) { > > dytc_current_profile = profile; > > - platform_profile_notify(&dytc_profile); > > + platform_profile_notify(tpacpi_pprof); > > } > > } > > @@ -10647,14 +10643,14 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) > > dbg_printk(TPACPI_DBG_INIT, > > "DYTC version %d: thermal mode available\n", dytc_version); > > - dytc_profile.dev = &tpacpi_pdev->dev; > > /* Create platform_profile structure and register */ > > - err = devm_platform_profile_register(&dytc_profile, NULL); > > + tpacpi_pprof = devm_platform_profile_register( > > + &tpacpi_pdev->dev, "thinkpad-acpi", NULL, &dytc_profile_ops); > > /* > > * If for some reason platform_profiles aren't enabled > > * don't quit terminally. > > */ > > - if (err) > > + if (IS_ERR(tpacpi_pprof)) > > return -ENODEV; > > /* Ensure initial values are correct */ > > diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h > > index cadbd3168d84..97ce9bd476ab 100644 > > --- a/include/linux/platform_profile.h > > +++ b/include/linux/platform_profile.h > > @@ -47,10 +47,14 @@ struct platform_profile_handler { > > const struct platform_profile_ops *ops; > > }; > > -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata); > > -int platform_profile_remove(struct platform_profile_handler *pprof); > > -int devm_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); > > +int platform_profile_remove(struct device *dev); > > +struct device *devm_platform_profile_register(struct device *dev, const char *name, > > + void *drvdata, > > + const struct platform_profile_ops *ops); > > int platform_profile_cycle(void); > > -void platform_profile_notify(struct platform_profile_handler *pprof); > > +void platform_profile_notify(struct device *dev); > > #endif /*_PLATFORM_PROFILE_H_*/ >
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 5a867b912964..fdf79b81b62e 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -3,6 +3,7 @@ /* Platform profile sysfs interface */ #include <linux/acpi.h> +#include <linux/cleanup.h> #include <linux/bits.h> #include <linux/init.h> #include <linux/kdev_t.h> @@ -213,9 +214,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, }; /** @@ -409,10 +418,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"); } @@ -461,40 +470,57 @@ 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->choices) { + /* Sanity check */ + if (!dev || !name || !ops || !ops->profile_get || + !ops->profile_set || !ops->choices) { pr_err("platform_profile: handler is invalid\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } - err = pprof->ops->choices(pprof); + struct platform_profile_handler *pprof __free(kfree) = kzalloc( + sizeof(*pprof), GFP_KERNEL); + if (!pprof) + return ERR_PTR(-ENOMEM); + + err = ops->choices(pprof); if (err < 0) - return err; + return ERR_PTR(err); if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) { pr_err("platform_profile: no available profiles\n"); - return -EINVAL; + 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); - if (err) + if (err) { + put_device(&no_free_ptr(pprof)->class_dev); goto cleanup_ida; + } + + /* After this point, device_unregister will free pprof on error */ + ppdev = &no_free_ptr(pprof)->class_dev; sysfs_notify(acpi_kobj, NULL, "platform_profile"); @@ -502,20 +528,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); @@ -533,30 +560,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(dev)) { 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); diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c index efb6653ed1d5..965940223892 100644 --- a/drivers/platform/surface/surface_platform_profile.c +++ b/drivers/platform/surface/surface_platform_profile.c @@ -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[] = { diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 70ec667e0cbf..2059b29dd36b 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -742,7 +742,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; /* @@ -1921,16 +1921,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; @@ -2017,7 +2011,7 @@ static int acer_thermal_profile_change(void) if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI) last_non_turbo_profile = tp; - platform_profile_notify(&platform_profile_handler); + platform_profile_notify(platform_profile_device); } return 0; diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h index 198bfe3306be..3806f9efaff8 100644 --- a/drivers/platform/x86/amd/pmf/pmf.h +++ b/drivers/platform/x86/amd/pmf/pmf.h @@ -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; diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c index 4f80a73eff9f..e8d2de9bb646 100644 --- a/drivers/platform/x86/amd/pmf/sps.c +++ b/drivers/platform/x86/amd/pmf/sps.c @@ -420,15 +420,16 @@ 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->ppdev = devm_platform_profile_register( + dev->dev, "amd-pmf", dev, &amd_pmf_profile_ops); + if (IS_ERR(dev->ppdev)) { + err = PTR_ERR(dev->ppdev); dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n", err); - return err; + return err; + } + + return 0; } diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 5c7099dc6109..809ab0353b68 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -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 *platform_profile_device; bool platform_profile_support; // The RSOC controls the maximum charging percentage. @@ -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->platform_profile_device); return count; } @@ -3891,15 +3891,10 @@ 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 == -EEXIST) { - pr_warn("%s, a platform_profile handler is already registered\n", __func__); - return 0; - } else if (err) { + asus->platform_profile_device = devm_platform_profile_register( + dev, "asus-wmi", asus, &asus_wmi_platform_profile_ops); + if (IS_ERR(asus->platform_profile_device)) { + err = PTR_ERR(asus->platform_profile_device); pr_err("%s, failed at devm_platform_profile_register: %d\n", __func__, err); return err; } diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c index a8961de004ab..1eaa746eb4f1 100644 --- a/drivers/platform/x86/dell/alienware-wmi.c +++ b/drivers/platform/x86/dell/alienware-wmi.c @@ -414,7 +414,6 @@ static struct platform_device *platform_device; static struct device_attribute *zone_dev_attrs; static struct attribute **zone_attrs; static struct platform_zone *zone_data; -static struct platform_profile_handler pp_handler; static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST]; static struct platform_driver platform_driver = { @@ -1165,11 +1164,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); } static int __init alienware_wmi_init(void) diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c index dda6f13295e8..4ff80ed4f157 100644 --- a/drivers/platform/x86/dell/dell-pc.c +++ b/drivers/platform/x86/dell/dell-pc.c @@ -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), @@ -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 */ @@ -271,26 +270,17 @@ 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; - 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) + 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_thermal_handler; + } return 0; cleanup_thermal_handler: - thermal_handler = NULL; - -cleanup_platform_device: platform_device_unregister(platform_device); return ret; diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 8a620d36f926..1b9e176f8d6f 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -273,7 +273,7 @@ static DEFINE_MUTEX(active_platform_profile_lock); static struct input_dev *hp_wmi_input_dev; static struct input_dev *camera_shutter_input_dev; static struct platform_device *hp_wmi_platform_dev; -static struct platform_profile_handler platform_profile_handler; +static struct device *platform_profile_device; static struct notifier_block platform_power_source_nb; static enum platform_profile_option active_platform_profile; static bool platform_profile_support; @@ -1602,6 +1602,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = { static int thermal_profile_setup(struct platform_device *device) { + const struct platform_profile_ops *ops; int err, tp; if (is_omen_thermal_profile()) { @@ -1617,7 +1618,7 @@ static int thermal_profile_setup(struct platform_device *device) if (err < 0) return err; - platform_profile_handler.ops = &platform_profile_omen_ops; + ops = &platform_profile_omen_ops; } else if (is_victus_thermal_profile()) { err = platform_profile_victus_get_ec(&active_platform_profile); if (err < 0) @@ -1631,7 +1632,7 @@ static int thermal_profile_setup(struct platform_device *device) if (err < 0) return err; - platform_profile_handler.ops = &platform_profile_victus_ops; + ops = &platform_profile_victus_ops; } else { tp = thermal_profile_get(); @@ -1646,15 +1647,13 @@ static int thermal_profile_setup(struct platform_device *device) if (err) return err; - platform_profile_handler.ops = &hp_wmi_platform_profile_ops; + ops = &hp_wmi_platform_profile_ops; } - platform_profile_handler.name = "hp-wmi"; - platform_profile_handler.dev = &device->dev; - - err = devm_platform_profile_register(&platform_profile_handler, NULL); - if (err) - return err; + platform_profile_device = devm_platform_profile_register( + &device->dev, "hp-wmi", NULL, ops); + if (IS_ERR(platform_profile_device)) + return PTR_ERR(platform_profile_device); platform_profile_support = true; diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index d34d565172f5..55aac0190624 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -142,7 +142,7 @@ enum { struct ideapad_dytc_priv { enum platform_profile_option current_profile; - struct platform_profile_handler pprof; + struct device *ppdev; /* platform profile device */ struct mutex mutex; /* protects the DYTC interface */ struct ideapad_private *priv; }; @@ -1050,7 +1050,7 @@ static void dytc_profile_refresh(struct ideapad_private *priv) if (profile != priv->dytc->current_profile) { priv->dytc->current_profile = profile; - platform_profile_notify(&priv->dytc->pprof); + platform_profile_notify(priv->dytc->ppdev); } } @@ -1117,15 +1117,15 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv) mutex_init(&priv->dytc->mutex); - priv->dytc->pprof.name = "ideapad-laptop"; - priv->dytc->pprof.dev = &priv->platform_device->dev; priv->dytc->priv = priv; - priv->dytc->pprof.ops = &dytc_profile_ops; /* Create platform_profile structure and register */ - err = devm_platform_profile_register(&priv->dytc->pprof, &priv->dytc); - if (err) + priv->dytc->ppdev = devm_platform_profile_register( + &priv->platform_device->dev, "ideapad-laptop", &priv->dytc, &dytc_profile_ops); + if (IS_ERR(priv->dytc->ppdev)) { + err = PTR_ERR(priv->dytc->ppdev); goto pp_reg_failed; + } /* Ensure initial values are correct */ dytc_profile_refresh(priv); diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c index 543e4bce1a57..9e2f24de0207 100644 --- a/drivers/platform/x86/inspur_platform_profile.c +++ b/drivers/platform/x86/inspur_platform_profile.c @@ -32,7 +32,7 @@ enum inspur_tmp_profile { struct inspur_wmi_priv { struct wmi_device *wdev; - struct platform_profile_handler handler; + struct device *ppdev; }; static int inspur_wmi_perform_query(struct wmi_device *wdev, @@ -190,11 +190,10 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context) priv->wdev = wdev; dev_set_drvdata(&wdev->dev, priv); - priv->handler.name = "inspur-wmi"; - priv->handler.dev = &wdev->dev; - priv->handler.ops = &inspur_platform_profile_ops; + priv->ppdev = devm_platform_profile_register( + &wdev->dev, "inspur-wmi", priv, &inspur_platform_profile_ops); - return devm_platform_profile_register(&priv->handler, priv); + return PTR_ERR_OR_ZERO(priv->ppdev); } static const struct wmi_device_id inspur_wmi_id_table[] = { diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index a0b8987bc328..964f842ef756 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -962,6 +962,7 @@ static const struct proc_ops dispatch_proc_ops = { static struct platform_device *tpacpi_pdev; static struct platform_device *tpacpi_sensors_pdev; static struct device *tpacpi_hwmon; +static struct device *tpacpi_pprof; static struct input_dev *tpacpi_inputdev; static struct mutex tpacpi_inputdev_send_mutex; static LIST_HEAD(tpacpi_all_drivers); @@ -10553,11 +10554,6 @@ static const struct platform_profile_ops dytc_profile_ops = { .choices = dytc_profile_choices, }; -static struct platform_profile_handler dytc_profile = { - .name = "thinkpad-acpi", - .ops = &dytc_profile_ops, -}; - static void dytc_profile_refresh(void) { enum platform_profile_option profile; @@ -10586,7 +10582,7 @@ static void dytc_profile_refresh(void) err = convert_dytc_to_profile(funcmode, perfmode, &profile); if (!err && profile != dytc_current_profile) { dytc_current_profile = profile; - platform_profile_notify(&dytc_profile); + platform_profile_notify(tpacpi_pprof); } } @@ -10647,14 +10643,14 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) dbg_printk(TPACPI_DBG_INIT, "DYTC version %d: thermal mode available\n", dytc_version); - dytc_profile.dev = &tpacpi_pdev->dev; /* Create platform_profile structure and register */ - err = devm_platform_profile_register(&dytc_profile, NULL); + tpacpi_pprof = devm_platform_profile_register( + &tpacpi_pdev->dev, "thinkpad-acpi", NULL, &dytc_profile_ops); /* * If for some reason platform_profiles aren't enabled * don't quit terminally. */ - if (err) + if (IS_ERR(tpacpi_pprof)) return -ENODEV; /* Ensure initial values are correct */ diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h index cadbd3168d84..97ce9bd476ab 100644 --- a/include/linux/platform_profile.h +++ b/include/linux/platform_profile.h @@ -47,10 +47,14 @@ struct platform_profile_handler { const struct platform_profile_ops *ops; }; -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata); -int platform_profile_remove(struct platform_profile_handler *pprof); -int devm_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); +int platform_profile_remove(struct device *dev); +struct device *devm_platform_profile_register(struct device *dev, const char *name, + void *drvdata, + const struct platform_profile_ops *ops); int platform_profile_cycle(void); -void platform_profile_notify(struct platform_profile_handler *pprof); +void platform_profile_notify(struct device *dev); #endif /*_PLATFORM_PROFILE_H_*/
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. Signed-off-by: Kurt Borja <kuurtb@gmail.com> --- drivers/acpi/platform_profile.c | 93 ++++++++++++------- .../surface/surface_platform_profile.c | 11 +-- drivers/platform/x86/acer-wmi.c | 18 ++-- drivers/platform/x86/amd/pmf/pmf.h | 2 +- drivers/platform/x86/amd/pmf/sps.c | 15 +-- drivers/platform/x86/asus-wmi.c | 17 ++-- drivers/platform/x86/dell/alienware-wmi.c | 10 +- drivers/platform/x86/dell/dell-pc.c | 22 ++--- drivers/platform/x86/hp/hp-wmi.c | 19 ++-- drivers/platform/x86/ideapad-laptop.c | 14 +-- .../platform/x86/inspur_platform_profile.c | 9 +- drivers/platform/x86/thinkpad_acpi.c | 14 +-- include/linux/platform_profile.h | 12 ++- 13 files changed, 131 insertions(+), 125 deletions(-)