From de6b0c1acc1411a67fb89f60ee7b526066da7bfb Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 29 Oct 2016 21:37:01 +0200 Subject: thermal: hwmon: use permission-specific DEVICE_ATTR variants Use DEVICE_ATTR_RO for read only attributes. This simplifies the source code, improves readbility, and reduces the chance of inconsistencies. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @ro@ declarer name DEVICE_ATTR; identifier x,x_show; @@ DEVICE_ATTR(x, \(0444\|S_IRUGO\), x_show, NULL); @script:ocaml@ x << ro.x; x_show << ro.x_show; @@ if not (x^"_show" = x_show) then Coccilib.include_match false @@ declarer name DEVICE_ATTR_RO; identifier ro.x,ro.x_show; @@ - DEVICE_ATTR(x, \(0444\|S_IRUGO\), x_show, NULL); + DEVICE_ATTR_RO(x); // Signed-off-by: Julia Lawall Signed-off-by: Zhang Rui --- drivers/thermal/thermal_hwmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c index c41c7742903a..8c45de6a9140 100644 --- a/drivers/thermal/thermal_hwmon.c +++ b/drivers/thermal/thermal_hwmon.c @@ -64,7 +64,7 @@ name_show(struct device *dev, struct device_attribute *attr, char *buf) struct thermal_hwmon_device *hwmon = dev_get_drvdata(dev); return sprintf(buf, "%s\n", hwmon->type); } -static DEVICE_ATTR(name, 0444, name_show, NULL); +static DEVICE_ATTR_RO(name); static ssize_t temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) -- cgit v1.2.3 From 5184eeb3b016470956de4c89ca9b53c65ef41452 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 29 Oct 2016 21:37:00 +0200 Subject: thermal: int340x_thermal: use permission-specific DEVICE_ATTR variants Use DEVICE_ATTR_RW for read-write attributes. This simplifies the source code, improves readbility, and reduces the chance of inconsistencies. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @rw@ declarer name DEVICE_ATTR; identifier x,x_show,x_store; @@ DEVICE_ATTR(x, \(0644\|S_IRUGO|S_IWUSR\), x_show, x_store); @script:ocaml@ x << rw.x; x_show << rw.x_show; x_store << rw.x_store; @@ if not (x^"_show" = x_show && x^"_store" = x_store) then Coccilib.include_match false @@ declarer name DEVICE_ATTR_RW; identifier rw.x,rw.x_show,rw.x_store; @@ - DEVICE_ATTR(x, \(0644\|S_IRUGO|S_IWUSR\), x_show, x_store); + DEVICE_ATTR_RW(x); // Signed-off-by: Julia Lawall Signed-off-by: Zhang Rui --- drivers/thermal/int340x_thermal/int3400_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c index 5836e5554433..9413c4abf0b9 100644 --- a/drivers/thermal/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/int340x_thermal/int3400_thermal.c @@ -96,7 +96,7 @@ static ssize_t current_uuid_store(struct device *dev, return -EINVAL; } -static DEVICE_ATTR(current_uuid, 0644, current_uuid_show, current_uuid_store); +static DEVICE_ATTR_RW(current_uuid); static DEVICE_ATTR_RO(available_uuids); static struct attribute *uuid_attrs[] = { &dev_attr_available_uuids.attr, -- cgit v1.2.3 From c6068a6edd50569fc34340c3abb30c24e24b8909 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Wed, 19 Oct 2016 05:59:29 +0900 Subject: thermal: intel_pch_thermal: Support skylake PCH 100 series thermal This patch uses .driver_data and board_info[] to make per pci device behavior table (name and ops), instead of adding the code for each pci device in switch-case. This will make easier to add new pci device ids. Then this adds new device id actually for skylake PCH 100 series (using registers are compatible with currently driver, so no need to change except adding device id to table). Signed-off-by: OGAWA Hirofumi Reviewed-by: Srinivas Pandruvada Signed-off-by: Zhang Rui --- drivers/thermal/intel_pch_thermal.c | 64 ++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 25 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel_pch_thermal.c b/drivers/thermal/intel_pch_thermal.c index 19bf2028e508..2b49e8d0fe9e 100644 --- a/drivers/thermal/intel_pch_thermal.c +++ b/drivers/thermal/intel_pch_thermal.c @@ -29,6 +29,7 @@ #define PCH_THERMAL_DID_HSW_2 0x8C24 /* Haswell PCH */ #define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */ #define PCH_THERMAL_DID_SKL 0x9D31 /* Skylake PCH */ +#define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */ /* Wildcat Point-LP PCH Thermal registers */ #define WPT_TEMP 0x0000 /* Temperature */ @@ -273,37 +274,44 @@ static struct thermal_zone_device_ops tzd_ops = { .get_trip_temp = pch_get_trip_temp, }; +enum board_ids { + board_hsw, + board_wpt, + board_skl, +}; + +static const struct board_info { + const char *name; + const struct pch_dev_ops *ops; +} board_info[] = { + [board_hsw] = { + .name = "pch_haswell", + .ops = &pch_dev_ops_wpt, + }, + [board_wpt] = { + .name = "pch_wildcat_point", + .ops = &pch_dev_ops_wpt, + }, + [board_skl] = { + .name = "pch_skylake", + .ops = &pch_dev_ops_wpt, + }, +}; static int intel_pch_thermal_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + enum board_ids board_id = id->driver_data; + const struct board_info *bi = &board_info[board_id]; struct pch_thermal_device *ptd; int err; int nr_trips; - char *dev_name; ptd = devm_kzalloc(&pdev->dev, sizeof(*ptd), GFP_KERNEL); if (!ptd) return -ENOMEM; - switch (pdev->device) { - case PCH_THERMAL_DID_WPT: - ptd->ops = &pch_dev_ops_wpt; - dev_name = "pch_wildcat_point"; - break; - case PCH_THERMAL_DID_SKL: - ptd->ops = &pch_dev_ops_wpt; - dev_name = "pch_skylake"; - break; - case PCH_THERMAL_DID_HSW_1: - case PCH_THERMAL_DID_HSW_2: - ptd->ops = &pch_dev_ops_wpt; - dev_name = "pch_haswell"; - break; - default: - dev_err(&pdev->dev, "unknown pch thermal device\n"); - return -ENODEV; - } + ptd->ops = bi->ops; pci_set_drvdata(pdev, ptd); ptd->pdev = pdev; @@ -331,11 +339,11 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev, if (err) goto error_cleanup; - ptd->tzd = thermal_zone_device_register(dev_name, nr_trips, 0, ptd, + ptd->tzd = thermal_zone_device_register(bi->name, nr_trips, 0, ptd, &tzd_ops, NULL, 0, 0); if (IS_ERR(ptd->tzd)) { dev_err(&pdev->dev, "Failed to register thermal zone %s\n", - dev_name); + bi->name); err = PTR_ERR(ptd->tzd); goto error_cleanup; } @@ -380,10 +388,16 @@ static int intel_pch_thermal_resume(struct device *device) } static struct pci_device_id intel_pch_thermal_id[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_1) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_2) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_1), + .driver_data = board_hsw, }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_2), + .driver_data = board_hsw, }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT), + .driver_data = board_wpt, }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL), + .driver_data = board_skl, }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL_H), + .driver_data = board_skl, }, { 0, }, }; MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id); -- cgit v1.2.3 From 54fa38cc2eda43599b51695f9918208e7250ac46 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:39 -0800 Subject: thermal: core: prevent zones with no types to be registered There are APIs that rely on tz->type. This patch prevent thermal zones without it to be registered. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 226b0b4aced6..ec0d15805df2 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1873,6 +1873,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, int passive = 0; struct thermal_governor *governor; + if (!type || strlen(type) == 0) + return ERR_PTR(-EINVAL); + if (type && strlen(type) >= THERMAL_NAME_LENGTH) return ERR_PTR(-EINVAL); @@ -1898,7 +1901,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, return ERR_PTR(result); } - strlcpy(tz->type, type ? : "", sizeof(tz->type)); + strlcpy(tz->type, type, sizeof(tz->type)); tz->ops = ops; tz->tzp = tzp; tz->device.class = &thermal_class; @@ -1918,11 +1921,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, } /* sys I/F */ - if (type) { - result = device_create_file(&tz->device, &dev_attr_type); - if (result) - goto unregister; - } + result = device_create_file(&tz->device, &dev_attr_type); + if (result) + goto unregister; result = device_create_file(&tz->device, &dev_attr_temp); if (result) @@ -2071,8 +2072,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) thermal_zone_device_set_polling(tz, 0); - if (tz->type[0]) - device_remove_file(&tz->device, &dev_attr_type); + device_remove_file(&tz->device, &dev_attr_type); device_remove_file(&tz->device, &dev_attr_temp); if (tz->ops->get_mode) device_remove_file(&tz->device, &dev_attr_mode); -- cgit v1.2.3 From ef1d8bff72e15854fd7db9b56d807fcad36e16d9 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:40 -0800 Subject: thermal: core: group thermal_zone DEVICE_ATTR's declarations Simply reorganize the code to have all DEVICE_ATTR's in one point in the file. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index ec0d15805df2..97f314e39b3d 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -975,7 +975,6 @@ emul_temp_store(struct device *dev, struct device_attribute *attr, return ret ? ret : count; } -static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); static ssize_t sustainable_power_show(struct device *dev, struct device_attribute *devattr, @@ -1006,8 +1005,6 @@ sustainable_power_store(struct device *dev, struct device_attribute *devattr, return count; } -static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show, - sustainable_power_store); #define create_s32_tzp_attr(name) \ static ssize_t \ @@ -1050,6 +1047,16 @@ create_s32_tzp_attr(slope); create_s32_tzp_attr(offset); #undef create_s32_tzp_attr +static DEVICE_ATTR(type, 0444, type_show, NULL); +static DEVICE_ATTR(temp, 0444, temp_show, NULL); +static DEVICE_ATTR(mode, 0644, mode_show, mode_store); +static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); +static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store); +static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL); +static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); +static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show, + sustainable_power_store); + static struct device_attribute *dev_tzp_attrs[] = { &dev_attr_sustainable_power, &dev_attr_k_po, @@ -1159,13 +1166,6 @@ int power_actor_set_power(struct thermal_cooling_device *cdev, return 0; } -static DEVICE_ATTR(type, 0444, type_show, NULL); -static DEVICE_ATTR(temp, 0444, temp_show, NULL); -static DEVICE_ATTR(mode, 0644, mode_show, mode_store); -static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); -static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store); -static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL); - /* sys I/F for cooling device */ #define to_cooling_device(_dev) \ container_of(_dev, struct thermal_cooling_device, device) -- cgit v1.2.3 From 308f726ac872bee72ab0fccb0ef6a75364e47496 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:41 -0800 Subject: thermal: core: group device_create_file() calls that are always created Simple code reorganization to group files that are always created when registering a thermal zone. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 97f314e39b3d..3d43c297948a 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1921,14 +1921,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, } /* sys I/F */ - result = device_create_file(&tz->device, &dev_attr_type); - if (result) - goto unregister; - - result = device_create_file(&tz->device, &dev_attr_temp); - if (result) - goto unregister; - if (ops->get_mode) { result = device_create_file(&tz->device, &dev_attr_mode); if (result) @@ -1963,13 +1955,16 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, goto unregister; } - /* Create policy attribute */ - result = device_create_file(&tz->device, &dev_attr_policy); + result = device_create_file(&tz->device, &dev_attr_type); if (result) goto unregister; - /* Add thermal zone params */ - result = create_tzp_attrs(&tz->device); + result = device_create_file(&tz->device, &dev_attr_temp); + if (result) + goto unregister; + + /* Create policy attribute */ + result = device_create_file(&tz->device, &dev_attr_policy); if (result) goto unregister; @@ -1978,6 +1973,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, if (result) goto unregister; + /* Add thermal zone params */ + result = create_tzp_attrs(&tz->device); + if (result) + goto unregister; + /* Update 'this' zone's governor information */ mutex_lock(&thermal_governor_lock); -- cgit v1.2.3 From 1c600861fa6fd8891c3c6936e93288f912630f53 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:42 -0800 Subject: thermal: core: use dev.groups to manage always present tz attributes Thermal zones attributes are all being created using device_create_file(). This has the disadvantage of making the code complicated and sometimes we may miss the cleanup of them. This patch starts to move the thermal zone sysfs attributes to the dev.groups, so Linux device core manage them for us. For now, this patch only moves those attributes are always present regardless of thermal zone condition. This change has also the advantage of cleaning up the thermal zone parameters sysfs entries that are left unclean after device registration. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 87 +++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 53 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 3d43c297948a..3da4cd3f7fb8 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1047,42 +1047,47 @@ create_s32_tzp_attr(slope); create_s32_tzp_attr(offset); #undef create_s32_tzp_attr +/* + * These are thermal zone device attributes that will always be present. + * All the attributes created for tzp (create_s32_tzp_attr) also are always + * present on the sysfs interface. + */ static DEVICE_ATTR(type, 0444, type_show, NULL); static DEVICE_ATTR(temp, 0444, temp_show, NULL); -static DEVICE_ATTR(mode, 0644, mode_show, mode_store); -static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store); static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL); -static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show, sustainable_power_store); -static struct device_attribute *dev_tzp_attrs[] = { - &dev_attr_sustainable_power, - &dev_attr_k_po, - &dev_attr_k_pu, - &dev_attr_k_i, - &dev_attr_k_d, - &dev_attr_integral_cutoff, - &dev_attr_slope, - &dev_attr_offset, -}; - -static int create_tzp_attrs(struct device *dev) -{ - int i; +/* These thermal zone device attributes are created based on conditions */ +static DEVICE_ATTR(mode, 0644, mode_show, mode_store); +static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); +static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); - for (i = 0; i < ARRAY_SIZE(dev_tzp_attrs); i++) { - int ret; - struct device_attribute *dev_attr = dev_tzp_attrs[i]; +static struct attribute *thermal_zone_dev_attrs[] = { + &dev_attr_type.attr, + &dev_attr_temp.attr, + &dev_attr_policy.attr, + &dev_attr_available_policies.attr, + &dev_attr_sustainable_power.attr, + &dev_attr_k_po.attr, + &dev_attr_k_pu.attr, + &dev_attr_k_i.attr, + &dev_attr_k_d.attr, + &dev_attr_integral_cutoff.attr, + &dev_attr_slope.attr, + &dev_attr_offset.attr, + NULL, +}; - ret = device_create_file(dev, dev_attr); - if (ret) - return ret; - } +static struct attribute_group thermal_zone_attribute_group = { + .attrs = thermal_zone_dev_attrs, +}; - return 0; -} +static const struct attribute_group *thermal_zone_attribute_groups[] = { + &thermal_zone_attribute_group, + NULL +}; /** * power_actor_get_max_power() - get the maximum power that a cdev can consume @@ -1909,6 +1914,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, tz->trips = trips; tz->passive_delay = passive_delay; tz->polling_delay = polling_delay; + + /* Add nodes that are always present via .groups */ + tz->device.groups = thermal_zone_attribute_groups; /* A new thermal zone needs to be updated anyway. */ atomic_set(&tz->need_update, 1); @@ -1955,29 +1963,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, goto unregister; } - result = device_create_file(&tz->device, &dev_attr_type); - if (result) - goto unregister; - - result = device_create_file(&tz->device, &dev_attr_temp); - if (result) - goto unregister; - - /* Create policy attribute */ - result = device_create_file(&tz->device, &dev_attr_policy); - if (result) - goto unregister; - - /* Create available_policies attribute */ - result = device_create_file(&tz->device, &dev_attr_available_policies); - if (result) - goto unregister; - - /* Add thermal zone params */ - result = create_tzp_attrs(&tz->device); - if (result) - goto unregister; - /* Update 'this' zone's governor information */ mutex_lock(&thermal_governor_lock); @@ -2072,12 +2057,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) thermal_zone_device_set_polling(tz, 0); - device_remove_file(&tz->device, &dev_attr_type); - device_remove_file(&tz->device, &dev_attr_temp); if (tz->ops->get_mode) device_remove_file(&tz->device, &dev_attr_mode); - device_remove_file(&tz->device, &dev_attr_policy); - device_remove_file(&tz->device, &dev_attr_available_policies); remove_trip_attrs(tz); thermal_set_governor(tz, NULL); -- cgit v1.2.3 From 66e554bde9f879ea09379848acc4446effad9dfb Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:43 -0800 Subject: thermal: core: move emul_temp creation to tz->device.groups emul_temp creation is dependent on a compile time condition. Moving to tz->device.groups. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 3da4cd3f7fb8..ec15a600fbbb 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1054,6 +1054,7 @@ create_s32_tzp_attr(offset); */ static DEVICE_ATTR(type, 0444, type_show, NULL); static DEVICE_ATTR(temp, 0444, temp_show, NULL); +static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store); static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL); static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show, @@ -1062,11 +1063,13 @@ static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show, /* These thermal zone device attributes are created based on conditions */ static DEVICE_ATTR(mode, 0644, mode_show, mode_store); static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); -static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); static struct attribute *thermal_zone_dev_attrs[] = { &dev_attr_type.attr, &dev_attr_temp.attr, +#if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) + &dev_attr_emul_temp.attr, +#endif &dev_attr_policy.attr, &dev_attr_available_policies.attr, &dev_attr_sustainable_power.attr, @@ -1957,12 +1960,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, goto unregister; } - if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) { - result = device_create_file(&tz->device, &dev_attr_emul_temp); - if (result) - goto unregister; - } - /* Update 'this' zone's governor information */ mutex_lock(&thermal_governor_lock); -- cgit v1.2.3 From 8baa5dae60adf95c44d52be3dae2367e3d5e9530 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:44 -0800 Subject: thermal: core: move mode attribute to tz->device.groups Moving mode attribute to tz->device.groups requires the implementation of a .is_visible() callback. The condition returned by .is_visible() of the mode attribute group is kept the same, we allow the attribute to be visible only if ops->get_mode() is set by the thermal driver. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index ec15a600fbbb..ec8551a83a87 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1064,6 +1064,7 @@ static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show, static DEVICE_ATTR(mode, 0644, mode_show, mode_store); static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); +/* These attributes are unconditionally added to a thermal zone */ static struct attribute *thermal_zone_dev_attrs[] = { &dev_attr_type.attr, &dev_attr_temp.attr, @@ -1087,8 +1088,35 @@ static struct attribute_group thermal_zone_attribute_group = { .attrs = thermal_zone_dev_attrs, }; +/* We expose mode only if .get_mode is present */ +static struct attribute *thermal_zone_mode_attrs[] = { + &dev_attr_mode.attr, + NULL, +}; + +static umode_t thermal_zone_mode_is_visible(struct kobject *kobj, + struct attribute *attr, + int attrno) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct thermal_zone_device *tz; + + tz = container_of(dev, struct thermal_zone_device, device); + + if (tz->ops->get_mode) + return attr->mode; + + return 0; +} + +static struct attribute_group thermal_zone_mode_attribute_group = { + .attrs = thermal_zone_mode_attrs, + .is_visible = thermal_zone_mode_is_visible, +}; + static const struct attribute_group *thermal_zone_attribute_groups[] = { &thermal_zone_attribute_group, + &thermal_zone_mode_attribute_group, NULL }; @@ -1932,12 +1960,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, } /* sys I/F */ - if (ops->get_mode) { - result = device_create_file(&tz->device, &dev_attr_mode); - if (result) - goto unregister; - } - result = create_trip_attrs(tz, mask); if (result) goto unregister; @@ -2054,8 +2076,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) thermal_zone_device_set_polling(tz, 0); - if (tz->ops->get_mode) - device_remove_file(&tz->device, &dev_attr_mode); remove_trip_attrs(tz); thermal_set_governor(tz, NULL); -- cgit v1.2.3 From 3a836bfe9ff6342303bd2a146bcc42eebc3a259a Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:45 -0800 Subject: thermal: core: move passive attr to tz->device.groups This patch moves the passive attribute to tz->device.groups. Moving the passive attribute also requires a .is_visible() callback implementation for its attribute group. The logic behind the visibility of passive attribute is kept the same. We only expose the passive attribute if the thermal driver has exposed at least one passive trip point. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 45 +++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index ec8551a83a87..f3d9fe9d5c48 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1114,9 +1114,45 @@ static struct attribute_group thermal_zone_mode_attribute_group = { .is_visible = thermal_zone_mode_is_visible, }; +/* We expose passive only if passive trips are present */ +static struct attribute *thermal_zone_passive_attrs[] = { + &dev_attr_passive.attr, + NULL, +}; + +static umode_t thermal_zone_passive_is_visible(struct kobject *kobj, + struct attribute *attr, + int attrno) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct thermal_zone_device *tz; + enum thermal_trip_type trip_type; + int count, passive = 0; + + tz = container_of(dev, struct thermal_zone_device, device); + + for (count = 0; count < tz->trips && !passive; count++) { + tz->ops->get_trip_type(tz, count, &trip_type); + + if (trip_type == THERMAL_TRIP_PASSIVE) + passive = 1; + } + + if (!passive) + return attr->mode; + + return 0; +} + +static struct attribute_group thermal_zone_passive_attribute_group = { + .attrs = thermal_zone_passive_attrs, + .is_visible = thermal_zone_passive_is_visible, +}; + static const struct attribute_group *thermal_zone_attribute_groups[] = { &thermal_zone_attribute_group, &thermal_zone_mode_attribute_group, + &thermal_zone_passive_attribute_group, NULL }; @@ -1906,7 +1942,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, int trip_temp; int result; int count; - int passive = 0; struct thermal_governor *governor; if (!type || strlen(type) == 0) @@ -1967,8 +2002,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, for (count = 0; count < trips; count++) { if (tz->ops->get_trip_type(tz, count, &trip_type)) set_bit(count, &tz->trips_disabled); - if (trip_type == THERMAL_TRIP_PASSIVE) - passive = 1; if (tz->ops->get_trip_temp(tz, count, &trip_temp)) set_bit(count, &tz->trips_disabled); /* Check for bogus trip points */ @@ -1976,12 +2009,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, set_bit(count, &tz->trips_disabled); } - if (!passive) { - result = device_create_file(&tz->device, &dev_attr_passive); - if (result) - goto unregister; - } - /* Update 'this' zone's governor information */ mutex_lock(&thermal_governor_lock); -- cgit v1.2.3 From 059386f43ef96bd61af40715aff757b727c3105b Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:46 -0800 Subject: thermal: core: improve power actor documentation Simple improvement on clarity and removal of checkpatch warning in the documentation of power actor kernel doc. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f3d9fe9d5c48..3d2adfac9578 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1206,12 +1206,13 @@ int power_actor_get_min_power(struct thermal_cooling_device *cdev, } /** - * power_actor_set_power() - limit the maximum power that a cooling device can consume + * power_actor_set_power() - limit the maximum power a cooling device consumes * @cdev: pointer to &thermal_cooling_device * @instance: thermal instance to update * @power: the power in milliwatts * - * Set the cooling device to consume at most @power milliwatts. + * Set the cooling device to consume at most @power milliwatts. The limit is + * expected to be a cap at the maximum power consumption. * * Return: 0 on success, -EINVAL if the cooling device does not * implement the power actor API or -E* for other failures. -- cgit v1.2.3 From 1a7e7cc03f172622792dafbbc6c93d8891fba569 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:47 -0800 Subject: thermal: core: move power actor code out of sysfs I/F section Simply reorganize code to keep only functions of sysfs interface of thermal zone device together. Therefore, move the power actor code out of the sysfs I/F section. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 166 ++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 83 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 3d2adfac9578..e8098f695c84 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -637,6 +637,89 @@ static void thermal_zone_device_check(struct work_struct *work) thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); } +/** + * power_actor_get_max_power() - get the maximum power that a cdev can consume + * @cdev: pointer to &thermal_cooling_device + * @tz: a valid thermal zone device pointer + * @max_power: pointer in which to store the maximum power + * + * Calculate the maximum power consumption in milliwats that the + * cooling device can currently consume and store it in @max_power. + * + * Return: 0 on success, -EINVAL if @cdev doesn't support the + * power_actor API or -E* on other error. + */ +int power_actor_get_max_power(struct thermal_cooling_device *cdev, + struct thermal_zone_device *tz, u32 *max_power) +{ + if (!cdev_is_power_actor(cdev)) + return -EINVAL; + + return cdev->ops->state2power(cdev, tz, 0, max_power); +} + +/** + * power_actor_get_min_power() - get the mainimum power that a cdev can consume + * @cdev: pointer to &thermal_cooling_device + * @tz: a valid thermal zone device pointer + * @min_power: pointer in which to store the minimum power + * + * Calculate the minimum power consumption in milliwatts that the + * cooling device can currently consume and store it in @min_power. + * + * Return: 0 on success, -EINVAL if @cdev doesn't support the + * power_actor API or -E* on other error. + */ +int power_actor_get_min_power(struct thermal_cooling_device *cdev, + struct thermal_zone_device *tz, u32 *min_power) +{ + unsigned long max_state; + int ret; + + if (!cdev_is_power_actor(cdev)) + return -EINVAL; + + ret = cdev->ops->get_max_state(cdev, &max_state); + if (ret) + return ret; + + return cdev->ops->state2power(cdev, tz, max_state, min_power); +} + +/** + * power_actor_set_power() - limit the maximum power a cooling device consumes + * @cdev: pointer to &thermal_cooling_device + * @instance: thermal instance to update + * @power: the power in milliwatts + * + * Set the cooling device to consume at most @power milliwatts. The limit is + * expected to be a cap at the maximum power consumption. + * + * Return: 0 on success, -EINVAL if the cooling device does not + * implement the power actor API or -E* for other failures. + */ +int power_actor_set_power(struct thermal_cooling_device *cdev, + struct thermal_instance *instance, u32 power) +{ + unsigned long state; + int ret; + + if (!cdev_is_power_actor(cdev)) + return -EINVAL; + + ret = cdev->ops->power2state(cdev, instance->tz, power, &state); + if (ret) + return ret; + + instance->target = state; + mutex_lock(&cdev->lock); + cdev->updated = false; + mutex_unlock(&cdev->lock); + thermal_cdev_update(cdev); + + return 0; +} + /* sys I/F for thermal zone */ #define to_thermal_zone(_dev) \ @@ -1156,89 +1239,6 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = { NULL }; -/** - * power_actor_get_max_power() - get the maximum power that a cdev can consume - * @cdev: pointer to &thermal_cooling_device - * @tz: a valid thermal zone device pointer - * @max_power: pointer in which to store the maximum power - * - * Calculate the maximum power consumption in milliwats that the - * cooling device can currently consume and store it in @max_power. - * - * Return: 0 on success, -EINVAL if @cdev doesn't support the - * power_actor API or -E* on other error. - */ -int power_actor_get_max_power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 *max_power) -{ - if (!cdev_is_power_actor(cdev)) - return -EINVAL; - - return cdev->ops->state2power(cdev, tz, 0, max_power); -} - -/** - * power_actor_get_min_power() - get the mainimum power that a cdev can consume - * @cdev: pointer to &thermal_cooling_device - * @tz: a valid thermal zone device pointer - * @min_power: pointer in which to store the minimum power - * - * Calculate the minimum power consumption in milliwatts that the - * cooling device can currently consume and store it in @min_power. - * - * Return: 0 on success, -EINVAL if @cdev doesn't support the - * power_actor API or -E* on other error. - */ -int power_actor_get_min_power(struct thermal_cooling_device *cdev, - struct thermal_zone_device *tz, u32 *min_power) -{ - unsigned long max_state; - int ret; - - if (!cdev_is_power_actor(cdev)) - return -EINVAL; - - ret = cdev->ops->get_max_state(cdev, &max_state); - if (ret) - return ret; - - return cdev->ops->state2power(cdev, tz, max_state, min_power); -} - -/** - * power_actor_set_power() - limit the maximum power a cooling device consumes - * @cdev: pointer to &thermal_cooling_device - * @instance: thermal instance to update - * @power: the power in milliwatts - * - * Set the cooling device to consume at most @power milliwatts. The limit is - * expected to be a cap at the maximum power consumption. - * - * Return: 0 on success, -EINVAL if the cooling device does not - * implement the power actor API or -E* for other failures. - */ -int power_actor_set_power(struct thermal_cooling_device *cdev, - struct thermal_instance *instance, u32 power) -{ - unsigned long state; - int ret; - - if (!cdev_is_power_actor(cdev)) - return -EINVAL; - - ret = cdev->ops->power2state(cdev, instance->tz, power, &state); - if (ret) - return ret; - - instance->target = state; - mutex_lock(&cdev->lock); - cdev->updated = false; - mutex_unlock(&cdev->lock); - thermal_cdev_update(cdev); - - return 0; -} - /* sys I/F for cooling device */ #define to_cooling_device(_dev) \ container_of(_dev, struct thermal_cooling_device, device) -- cgit v1.2.3 From 9d934fc8838b061cc02b8b7416e5defb6299dec1 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:48 -0800 Subject: thermal: core: remove useless empty line Fix style problem on create_trip_attrs(); Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e8098f695c84..122eba77360c 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1833,7 +1833,6 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) } } - for (indx = 0; indx < tz->trips; indx++) { /* create trip type attribute */ snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH, -- cgit v1.2.3 From 3bafb5e2a683626387337eda28bbef927bce1a0d Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:49 -0800 Subject: thermal: core: fix style on remove_trip_attrs() Align to parentheses, removing checkpatch warning. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 122eba77360c..592c72bd5835 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1900,7 +1900,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) &tz->trip_temp_attrs[indx].attr); if (tz->ops->get_trip_hyst) device_remove_file(&tz->device, - &tz->trip_hyst_attrs[indx].attr); + &tz->trip_hyst_attrs[indx].attr); } kfree(tz->trip_type_attrs); kfree(tz->trip_temp_attrs); -- cgit v1.2.3 From 0a9de81907e6dc2adaddedca91ee26a7479b3750 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:50 -0800 Subject: thermal: core: move the trip attrs to the tz sysfs I/F section Code reorganization to keep all the sysfs I/F of a thermal zone in the same section. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 216 ++++++++++++++++++++--------------------- 1 file changed, 108 insertions(+), 108 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 592c72bd5835..e399ae67b18b 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1239,6 +1239,114 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = { NULL }; +/** + * create_trip_attrs() - create attributes for trip points + * @tz: the thermal zone device + * @mask: Writeable trip point bitmap. + * + * helper function to instantiate sysfs entries for every trip + * point and its properties of a struct thermal_zone_device. + * + * Return: 0 on success, the proper error value otherwise. + */ +static int create_trip_attrs(struct thermal_zone_device *tz, int mask) +{ + int indx; + int size = sizeof(struct thermal_attr) * tz->trips; + + tz->trip_type_attrs = kzalloc(size, GFP_KERNEL); + if (!tz->trip_type_attrs) + return -ENOMEM; + + tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL); + if (!tz->trip_temp_attrs) { + kfree(tz->trip_type_attrs); + return -ENOMEM; + } + + if (tz->ops->get_trip_hyst) { + tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL); + if (!tz->trip_hyst_attrs) { + kfree(tz->trip_type_attrs); + kfree(tz->trip_temp_attrs); + return -ENOMEM; + } + } + + for (indx = 0; indx < tz->trips; indx++) { + /* create trip type attribute */ + snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH, + "trip_point_%d_type", indx); + + sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr); + tz->trip_type_attrs[indx].attr.attr.name = + tz->trip_type_attrs[indx].name; + tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO; + tz->trip_type_attrs[indx].attr.show = trip_point_type_show; + + device_create_file(&tz->device, + &tz->trip_type_attrs[indx].attr); + + /* create trip temp attribute */ + snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH, + "trip_point_%d_temp", indx); + + sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr); + tz->trip_temp_attrs[indx].attr.attr.name = + tz->trip_temp_attrs[indx].name; + tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO; + tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show; + if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) && + mask & (1 << indx)) { + tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR; + tz->trip_temp_attrs[indx].attr.store = + trip_point_temp_store; + } + + device_create_file(&tz->device, + &tz->trip_temp_attrs[indx].attr); + + /* create Optional trip hyst attribute */ + if (!tz->ops->get_trip_hyst) + continue; + snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH, + "trip_point_%d_hyst", indx); + + sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr); + tz->trip_hyst_attrs[indx].attr.attr.name = + tz->trip_hyst_attrs[indx].name; + tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO; + tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show; + if (tz->ops->set_trip_hyst) { + tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR; + tz->trip_hyst_attrs[indx].attr.store = + trip_point_hyst_store; + } + + device_create_file(&tz->device, + &tz->trip_hyst_attrs[indx].attr); + } + return 0; +} + +static void remove_trip_attrs(struct thermal_zone_device *tz) +{ + int indx; + + for (indx = 0; indx < tz->trips; indx++) { + device_remove_file(&tz->device, + &tz->trip_type_attrs[indx].attr); + device_remove_file(&tz->device, + &tz->trip_temp_attrs[indx].attr); + if (tz->ops->get_trip_hyst) + device_remove_file(&tz->device, + &tz->trip_hyst_attrs[indx].attr); + } + kfree(tz->trip_type_attrs); + kfree(tz->trip_temp_attrs); + kfree(tz->trip_hyst_attrs); +} + /* sys I/F for cooling device */ #define to_cooling_device(_dev) \ container_of(_dev, struct thermal_cooling_device, device) @@ -1799,114 +1907,6 @@ void thermal_notify_framework(struct thermal_zone_device *tz, int trip) } EXPORT_SYMBOL_GPL(thermal_notify_framework); -/** - * create_trip_attrs() - create attributes for trip points - * @tz: the thermal zone device - * @mask: Writeable trip point bitmap. - * - * helper function to instantiate sysfs entries for every trip - * point and its properties of a struct thermal_zone_device. - * - * Return: 0 on success, the proper error value otherwise. - */ -static int create_trip_attrs(struct thermal_zone_device *tz, int mask) -{ - int indx; - int size = sizeof(struct thermal_attr) * tz->trips; - - tz->trip_type_attrs = kzalloc(size, GFP_KERNEL); - if (!tz->trip_type_attrs) - return -ENOMEM; - - tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL); - if (!tz->trip_temp_attrs) { - kfree(tz->trip_type_attrs); - return -ENOMEM; - } - - if (tz->ops->get_trip_hyst) { - tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL); - if (!tz->trip_hyst_attrs) { - kfree(tz->trip_type_attrs); - kfree(tz->trip_temp_attrs); - return -ENOMEM; - } - } - - for (indx = 0; indx < tz->trips; indx++) { - /* create trip type attribute */ - snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH, - "trip_point_%d_type", indx); - - sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr); - tz->trip_type_attrs[indx].attr.attr.name = - tz->trip_type_attrs[indx].name; - tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO; - tz->trip_type_attrs[indx].attr.show = trip_point_type_show; - - device_create_file(&tz->device, - &tz->trip_type_attrs[indx].attr); - - /* create trip temp attribute */ - snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH, - "trip_point_%d_temp", indx); - - sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr); - tz->trip_temp_attrs[indx].attr.attr.name = - tz->trip_temp_attrs[indx].name; - tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO; - tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show; - if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) && - mask & (1 << indx)) { - tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR; - tz->trip_temp_attrs[indx].attr.store = - trip_point_temp_store; - } - - device_create_file(&tz->device, - &tz->trip_temp_attrs[indx].attr); - - /* create Optional trip hyst attribute */ - if (!tz->ops->get_trip_hyst) - continue; - snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH, - "trip_point_%d_hyst", indx); - - sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr); - tz->trip_hyst_attrs[indx].attr.attr.name = - tz->trip_hyst_attrs[indx].name; - tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO; - tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show; - if (tz->ops->set_trip_hyst) { - tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR; - tz->trip_hyst_attrs[indx].attr.store = - trip_point_hyst_store; - } - - device_create_file(&tz->device, - &tz->trip_hyst_attrs[indx].attr); - } - return 0; -} - -static void remove_trip_attrs(struct thermal_zone_device *tz) -{ - int indx; - - for (indx = 0; indx < tz->trips; indx++) { - device_remove_file(&tz->device, - &tz->trip_type_attrs[indx].attr); - device_remove_file(&tz->device, - &tz->trip_temp_attrs[indx].attr); - if (tz->ops->get_trip_hyst) - device_remove_file(&tz->device, - &tz->trip_hyst_attrs[indx].attr); - } - kfree(tz->trip_type_attrs); - kfree(tz->trip_temp_attrs); - kfree(tz->trip_hyst_attrs); -} - /** * thermal_zone_device_register() - register a new thermal zone device * @type: the thermal zone device type -- cgit v1.2.3 From e161aefb9a5fff038054231ffb80abbc2aa42238 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:51 -0800 Subject: thermal: core: create tz->device.groups dynamically This is a patch to allow adding groups created dynamically. For now we create only the existing group. However, this is a preparation to allow creating trip groups, which are determined only when the number of trips are known at runtime. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e399ae67b18b..971f033368b2 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1236,7 +1236,7 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = { &thermal_zone_attribute_group, &thermal_zone_mode_attribute_group, &thermal_zone_passive_attribute_group, - NULL + /* This is not NULL terminated as we create the group dynamically */ }; /** @@ -1347,6 +1347,25 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) kfree(tz->trip_hyst_attrs); } +static int thermal_zone_create_device_groups(struct thermal_zone_device *tz) +{ + const struct attribute_group **groups; + int i, size; + + size = ARRAY_SIZE(thermal_zone_attribute_groups) + 1; + /* This also takes care of API requirement to be NULL terminated */ + groups = kcalloc(size, sizeof(*groups), GFP_KERNEL); + if (!groups) + return -ENOMEM; + + for (i = 0; i < size - 1; i++) + groups[i] = thermal_zone_attribute_groups[i]; + + tz->device.groups = groups; + + return 0; +} + /* sys I/F for cooling device */ #define to_cooling_device(_dev) \ container_of(_dev, struct thermal_cooling_device, device) @@ -1982,7 +2001,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, tz->polling_delay = polling_delay; /* Add nodes that are always present via .groups */ - tz->device.groups = thermal_zone_attribute_groups; + thermal_zone_create_device_groups(tz); /* A new thermal zone needs to be updated anyway. */ atomic_set(&tz->need_update, 1); @@ -2111,7 +2130,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) idr_destroy(&tz->idr); mutex_destroy(&tz->lock); device_unregister(&tz->device); - return; + kfree(tz->device.groups); } EXPORT_SYMBOL_GPL(thermal_zone_device_unregister); -- cgit v1.2.3 From 4d0fe7490d7f4d61b582acbae718328284f151b9 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:52 -0800 Subject: thermal: core: move trips attributes to tz->device.groups Finally, move the last thermal zone sysfs attributes to tz->device.groups: trips attributes. This requires adding a attribute_group to thermal_zone_device, creating it dynamically, and then setting all trips attributes in it. The trips attribute is then added to the tz->device.groups. As the removal of all attributes are handled by device core, the device remove calls are not needed anymore. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 86 +++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 38 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 971f033368b2..b1d6de9185f4 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1251,8 +1251,13 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = { */ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) { - int indx; int size = sizeof(struct thermal_attr) * tz->trips; + struct attribute **attrs; + int indx; + + /* This function works only for zones with at least one trip */ + if (tz->trips <= 0) + return -EINVAL; tz->trip_type_attrs = kzalloc(size, GFP_KERNEL); if (!tz->trip_type_attrs) @@ -1273,6 +1278,15 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) } } + attrs = kzalloc(sizeof(*attrs) * (tz->trips * 3 + 1), GFP_KERNEL); + if (!attrs) { + kfree(tz->trip_type_attrs); + kfree(tz->trip_temp_attrs); + if (tz->ops->get_trip_hyst) + kfree(tz->trip_hyst_attrs); + return -ENOMEM; + } + for (indx = 0; indx < tz->trips; indx++) { /* create trip type attribute */ snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH, @@ -1283,9 +1297,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) tz->trip_type_attrs[indx].name; tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO; tz->trip_type_attrs[indx].attr.show = trip_point_type_show; - - device_create_file(&tz->device, - &tz->trip_type_attrs[indx].attr); + attrs[indx] = &tz->trip_type_attrs[indx].attr.attr; /* create trip temp attribute */ snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH, @@ -1302,9 +1314,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) tz->trip_temp_attrs[indx].attr.store = trip_point_temp_store; } - - device_create_file(&tz->device, - &tz->trip_temp_attrs[indx].attr); + attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.attr; /* create Optional trip hyst attribute */ if (!tz->ops->get_trip_hyst) @@ -1322,45 +1332,43 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) tz->trip_hyst_attrs[indx].attr.store = trip_point_hyst_store; } - - device_create_file(&tz->device, - &tz->trip_hyst_attrs[indx].attr); + attrs[indx + tz->trips * 2] = + &tz->trip_hyst_attrs[indx].attr.attr; } - return 0; -} + attrs[tz->trips * 3] = NULL; -static void remove_trip_attrs(struct thermal_zone_device *tz) -{ - int indx; + tz->trips_attribute_group.attrs = attrs; - for (indx = 0; indx < tz->trips; indx++) { - device_remove_file(&tz->device, - &tz->trip_type_attrs[indx].attr); - device_remove_file(&tz->device, - &tz->trip_temp_attrs[indx].attr); - if (tz->ops->get_trip_hyst) - device_remove_file(&tz->device, - &tz->trip_hyst_attrs[indx].attr); - } - kfree(tz->trip_type_attrs); - kfree(tz->trip_temp_attrs); - kfree(tz->trip_hyst_attrs); + return 0; } -static int thermal_zone_create_device_groups(struct thermal_zone_device *tz) +static int thermal_zone_create_device_groups(struct thermal_zone_device *tz, + int mask) { const struct attribute_group **groups; - int i, size; + int i, size, result; - size = ARRAY_SIZE(thermal_zone_attribute_groups) + 1; + /* we need one extra for trips and the NULL to terminate the array */ + size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2; /* This also takes care of API requirement to be NULL terminated */ groups = kcalloc(size, sizeof(*groups), GFP_KERNEL); if (!groups) return -ENOMEM; - for (i = 0; i < size - 1; i++) + for (i = 0; i < size - 2; i++) groups[i] = thermal_zone_attribute_groups[i]; + if (tz->trips) { + result = create_trip_attrs(tz, mask); + if (result) { + kfree(groups); + + return result; + } + + groups[size - 2] = &tz->trips_attribute_group; + } + tz->device.groups = groups; return 0; @@ -2000,8 +2008,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, tz->passive_delay = passive_delay; tz->polling_delay = polling_delay; + /* sys I/F */ /* Add nodes that are always present via .groups */ - thermal_zone_create_device_groups(tz); + result = thermal_zone_create_device_groups(tz, mask); + if (result) + goto unregister; + /* A new thermal zone needs to be updated anyway. */ atomic_set(&tz->need_update, 1); @@ -2013,11 +2025,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, return ERR_PTR(result); } - /* sys I/F */ - result = create_trip_attrs(tz, mask); - if (result) - goto unregister; - for (count = 0; count < trips; count++) { if (tz->ops->get_trip_type(tz, count, &trip_type)) set_bit(count, &tz->trips_disabled); @@ -2122,7 +2129,10 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) thermal_zone_device_set_polling(tz, 0); - remove_trip_attrs(tz); + kfree(tz->trip_type_attrs); + kfree(tz->trip_temp_attrs); + kfree(tz->trip_hyst_attrs); + kfree(tz->trips_attribute_group.attrs); thermal_set_governor(tz, NULL); thermal_remove_hwmon_sysfs(tz); -- cgit v1.2.3 From 2a4806bf7afd37c719b10099415318a9936a3293 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:53 -0800 Subject: thermal: core: remove unnecessary device_remove() calls Given that cdevs sysfs properties are already registered using the dev.groups, there is no need to explicitly call device_remove() for each property. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index b1d6de9185f4..6100ae70ccfb 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1876,11 +1876,6 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) mutex_unlock(&thermal_list_lock); - if (cdev->type[0]) - device_remove_file(&cdev->device, &dev_attr_cdev_type); - device_remove_file(&cdev->device, &dev_attr_max_state); - device_remove_file(&cdev->device, &dev_attr_cur_state); - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); device_unregister(&cdev->device); return; -- cgit v1.2.3 From 3d0055d2b252d9bbae8c064b37dd444b77f4c4c1 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:54 -0800 Subject: thermal: core: split passive_store Split passive_store between sysfs handling and thermal core internal data handling. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 62 ++++++++++++++++++++++++++++-------------- drivers/thermal/thermal_core.h | 4 +++ 2 files changed, 45 insertions(+), 21 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 6100ae70ccfb..4e315c979f89 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -720,6 +720,43 @@ int power_actor_set_power(struct thermal_cooling_device *cdev, return 0; } +void thermal_zone_device_rebind_exception(struct thermal_zone_device *tz, + const char *cdev_type, size_t size) +{ + struct thermal_cooling_device *cdev = NULL; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(cdev, &thermal_cdev_list, node) { + /* skip non matching cdevs */ + if (strncmp(cdev_type, cdev->type, size)) + continue; + + /* re binding the exception matching the type pattern */ + thermal_zone_bind_cooling_device(tz, THERMAL_TRIPS_NONE, cdev, + THERMAL_NO_LIMIT, + THERMAL_NO_LIMIT, + THERMAL_WEIGHT_DEFAULT); + } + mutex_unlock(&thermal_list_lock); +} + +void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz, + const char *cdev_type, size_t size) +{ + struct thermal_cooling_device *cdev = NULL; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(cdev, &thermal_cdev_list, node) { + /* skip non matching cdevs */ + if (strncmp(cdev_type, cdev->type, size)) + continue; + /* unbinding the exception matching the type pattern */ + thermal_zone_unbind_cooling_device(tz, THERMAL_TRIPS_NONE, + cdev); + } + mutex_unlock(&thermal_list_lock); +} + /* sys I/F for thermal zone */ #define to_thermal_zone(_dev) \ @@ -922,7 +959,6 @@ passive_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct thermal_zone_device *tz = to_thermal_zone(dev); - struct thermal_cooling_device *cdev = NULL; int state; if (!sscanf(buf, "%d\n", &state)) @@ -935,30 +971,14 @@ passive_store(struct device *dev, struct device_attribute *attr, return -EINVAL; if (state && !tz->forced_passive) { - mutex_lock(&thermal_list_lock); - list_for_each_entry(cdev, &thermal_cdev_list, node) { - if (!strncmp("Processor", cdev->type, - sizeof("Processor"))) - thermal_zone_bind_cooling_device(tz, - THERMAL_TRIPS_NONE, cdev, - THERMAL_NO_LIMIT, - THERMAL_NO_LIMIT, - THERMAL_WEIGHT_DEFAULT); - } - mutex_unlock(&thermal_list_lock); if (!tz->passive_delay) tz->passive_delay = 1000; + thermal_zone_device_rebind_exception(tz, "Processor", + sizeof("Processor")); } else if (!state && tz->forced_passive) { - mutex_lock(&thermal_list_lock); - list_for_each_entry(cdev, &thermal_cdev_list, node) { - if (!strncmp("Processor", cdev->type, - sizeof("Processor"))) - thermal_zone_unbind_cooling_device(tz, - THERMAL_TRIPS_NONE, - cdev); - } - mutex_unlock(&thermal_list_lock); tz->passive_delay = 0; + thermal_zone_device_unbind_exception(tz, "Processor", + sizeof("Processor")); } tz->forced_passive = state; diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 749d41abfbab..a765c753c62c 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -56,6 +56,10 @@ struct thermal_instance { int thermal_register_governor(struct thermal_governor *); void thermal_unregister_governor(struct thermal_governor *); +void thermal_zone_device_rebind_exception(struct thermal_zone_device *, + const char *, size_t); +void thermal_zone_device_unbind_exception(struct thermal_zone_device *, + const char *, size_t); #ifdef CONFIG_THERMAL_GOV_STEP_WISE int thermal_gov_step_wise_register(void); -- cgit v1.2.3 From 6b885202d7c17157a44d5cb42793f795d6d7a58e Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:55 -0800 Subject: thermal: core: split policy_store Similarly to passive_store, policy_store now is split between thermal core data structure handling and sysfs handling. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 37 ++++++++++++++++++++++++------------- drivers/thermal/thermal_core.h | 1 + 2 files changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 4e315c979f89..23f138f7eb68 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -757,6 +757,28 @@ void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz, mutex_unlock(&thermal_list_lock); } +int thermal_zone_device_set_policy(struct thermal_zone_device *tz, + char *policy) +{ + struct thermal_governor *gov; + int ret = -EINVAL; + + mutex_lock(&thermal_governor_lock); + mutex_lock(&tz->lock); + + gov = __find_governor(strim(policy)); + if (!gov) + goto exit; + + ret = thermal_set_governor(tz, gov); + +exit: + mutex_unlock(&tz->lock); + mutex_unlock(&thermal_governor_lock); + + return ret; +} + /* sys I/F for thermal zone */ #define to_thermal_zone(_dev) \ @@ -1001,27 +1023,16 @@ static ssize_t policy_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int ret = -EINVAL; struct thermal_zone_device *tz = to_thermal_zone(dev); - struct thermal_governor *gov; char name[THERMAL_NAME_LENGTH]; + int ret; snprintf(name, sizeof(name), "%s", buf); - mutex_lock(&thermal_governor_lock); - mutex_lock(&tz->lock); - - gov = __find_governor(strim(name)); - if (!gov) - goto exit; - - ret = thermal_set_governor(tz, gov); + ret = thermal_zone_device_set_policy(tz, name); if (!ret) ret = count; -exit: - mutex_unlock(&tz->lock); - mutex_unlock(&thermal_governor_lock); return ret; } diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index a765c753c62c..db65d3b08cf7 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -60,6 +60,7 @@ void thermal_zone_device_rebind_exception(struct thermal_zone_device *, const char *, size_t); void thermal_zone_device_unbind_exception(struct thermal_zone_device *, const char *, size_t); +int thermal_zone_device_set_policy(struct thermal_zone_device *, char *); #ifdef CONFIG_THERMAL_GOV_STEP_WISE int thermal_gov_step_wise_register(void); -- cgit v1.2.3 From 97d2423bd9738bb75cd716d01c4c4e1d6fae8441 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:56 -0800 Subject: thermal: core: split available_policies_show() This patch creates a helper to build a list of available governors. Cc: Zhang Rui