Skip to content

Commit 0dbf608

Browse files
committed
Merge branch 'thermal-intel' into thermal
* thermal-intel: thermal: intel: int340x_thermal: replace deprecated strncpy() with strscpy() thermal: intel: hfi: Enable HFI only when required thermal: netlink: Rename thermal_gnl_family thermal: netlink: Add genetlink bind/unbind notifications
2 parents 0444d57 + 03fa9a3 commit 0dbf608

File tree

4 files changed

+163
-26
lines changed

4 files changed

+163
-26
lines changed

drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ static int acpi_parse_psvt(acpi_handle handle, int *psvt_count, struct psvt **ps
309309

310310
if (knob->type == ACPI_TYPE_STRING) {
311311
memset(&psvt->limit, 0, sizeof(u64));
312-
strncpy(psvt->limit.string, psvt_ptr->limit.str_ptr, knob->string.length);
312+
strscpy(psvt->limit.string, psvt_ptr->limit.str_ptr, ACPI_LIMIT_STR_MAX_LEN);
313313
} else {
314314
psvt->limit.integer = psvt_ptr->limit.integer;
315315
}
@@ -468,7 +468,7 @@ static int fill_psvt(char __user *ubuf)
468468
psvt_user[i].unlimit_coeff = psvts[i].unlimit_coeff;
469469
psvt_user[i].control_knob_type = psvts[i].control_knob_type;
470470
if (psvt_user[i].control_knob_type == ACPI_TYPE_STRING)
471-
strncpy(psvt_user[i].limit.string, psvts[i].limit.string,
471+
strscpy(psvt_user[i].limit.string, psvts[i].limit.string,
472472
ACPI_LIMIT_STR_MAX_LEN);
473473
else
474474
psvt_user[i].limit.integer = psvts[i].limit.integer;

drivers/thermal/intel/intel_hfi.c

Lines changed: 89 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ struct hfi_cpu_info {
159159
static DEFINE_PER_CPU(struct hfi_cpu_info, hfi_cpu_info) = { .index = -1 };
160160

161161
static int max_hfi_instances;
162+
static int hfi_clients_nr;
162163
static struct hfi_instance *hfi_instances;
163164

164165
static struct hfi_features hfi_features;
@@ -477,8 +478,11 @@ void intel_hfi_online(unsigned int cpu)
477478
enable:
478479
cpumask_set_cpu(cpu, hfi_instance->cpus);
479480

480-
/* Enable this HFI instance if this is its first online CPU. */
481-
if (cpumask_weight(hfi_instance->cpus) == 1) {
481+
/*
482+
* Enable this HFI instance if this is its first online CPU and
483+
* there are user-space clients of thermal events.
484+
*/
485+
if (cpumask_weight(hfi_instance->cpus) == 1 && hfi_clients_nr > 0) {
482486
hfi_set_hw_table(hfi_instance);
483487
hfi_enable();
484488
}
@@ -573,18 +577,33 @@ static __init int hfi_parse_features(void)
573577
return 0;
574578
}
575579

576-
static void hfi_do_enable(void)
580+
/*
581+
* If concurrency is not prevented by other means, the HFI enable/disable
582+
* routines must be called under hfi_instance_lock."
583+
*/
584+
static void hfi_enable_instance(void *ptr)
585+
{
586+
hfi_set_hw_table(ptr);
587+
hfi_enable();
588+
}
589+
590+
static void hfi_disable_instance(void *ptr)
591+
{
592+
hfi_disable();
593+
}
594+
595+
static void hfi_syscore_resume(void)
577596
{
578597
/* This code runs only on the boot CPU. */
579598
struct hfi_cpu_info *info = &per_cpu(hfi_cpu_info, 0);
580599
struct hfi_instance *hfi_instance = info->hfi_instance;
581600

582601
/* No locking needed. There is no concurrency with CPU online. */
583-
hfi_set_hw_table(hfi_instance);
584-
hfi_enable();
602+
if (hfi_clients_nr > 0)
603+
hfi_enable_instance(hfi_instance);
585604
}
586605

587-
static int hfi_do_disable(void)
606+
static int hfi_syscore_suspend(void)
588607
{
589608
/* No locking needed. There is no concurrency with CPU offline. */
590609
hfi_disable();
@@ -593,8 +612,58 @@ static int hfi_do_disable(void)
593612
}
594613

595614
static struct syscore_ops hfi_pm_ops = {
596-
.resume = hfi_do_enable,
597-
.suspend = hfi_do_disable,
615+
.resume = hfi_syscore_resume,
616+
.suspend = hfi_syscore_suspend,
617+
};
618+
619+
static int hfi_thermal_notify(struct notifier_block *nb, unsigned long state,
620+
void *_notify)
621+
{
622+
struct thermal_genl_notify *notify = _notify;
623+
struct hfi_instance *hfi_instance;
624+
smp_call_func_t func = NULL;
625+
unsigned int cpu;
626+
int i;
627+
628+
if (notify->mcgrp != THERMAL_GENL_EVENT_GROUP)
629+
return NOTIFY_DONE;
630+
631+
if (state != THERMAL_NOTIFY_BIND && state != THERMAL_NOTIFY_UNBIND)
632+
return NOTIFY_DONE;
633+
634+
mutex_lock(&hfi_instance_lock);
635+
636+
switch (state) {
637+
case THERMAL_NOTIFY_BIND:
638+
if (++hfi_clients_nr == 1)
639+
func = hfi_enable_instance;
640+
break;
641+
case THERMAL_NOTIFY_UNBIND:
642+
if (--hfi_clients_nr == 0)
643+
func = hfi_disable_instance;
644+
break;
645+
}
646+
647+
if (!func)
648+
goto out;
649+
650+
for (i = 0; i < max_hfi_instances; i++) {
651+
hfi_instance = &hfi_instances[i];
652+
if (cpumask_empty(hfi_instance->cpus))
653+
continue;
654+
655+
cpu = cpumask_any(hfi_instance->cpus);
656+
smp_call_function_single(cpu, func, hfi_instance, true);
657+
}
658+
659+
out:
660+
mutex_unlock(&hfi_instance_lock);
661+
662+
return NOTIFY_OK;
663+
}
664+
665+
static struct notifier_block hfi_thermal_nb = {
666+
.notifier_call = hfi_thermal_notify,
598667
};
599668

600669
void __init intel_hfi_init(void)
@@ -628,10 +697,22 @@ void __init intel_hfi_init(void)
628697
if (!hfi_updates_wq)
629698
goto err_nomem;
630699

700+
/*
701+
* Both thermal core and Intel HFI can not be build as modules.
702+
* As kernel build-in drivers they are initialized before user-space
703+
* starts, hence we can not miss BIND/UNBIND events when applications
704+
* add/remove thermal multicast group to/from a netlink socket.
705+
*/
706+
if (thermal_genl_register_notifier(&hfi_thermal_nb))
707+
goto err_nl_notif;
708+
631709
register_syscore_ops(&hfi_pm_ops);
632710

633711
return;
634712

713+
err_nl_notif:
714+
destroy_workqueue(hfi_updates_wq);
715+
635716
err_nomem:
636717
for (j = 0; j < i; ++j) {
637718
hfi_instance = &hfi_instances[j];

drivers/thermal/thermal_netlink.c

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,13 @@
77
* Generic netlink for thermal management framework
88
*/
99
#include <linux/module.h>
10+
#include <linux/notifier.h>
1011
#include <linux/kernel.h>
1112
#include <net/genetlink.h>
1213
#include <uapi/linux/thermal.h>
1314

1415
#include "thermal_core.h"
1516

16-
enum thermal_genl_multicast_groups {
17-
THERMAL_GENL_SAMPLING_GROUP = 0,
18-
THERMAL_GENL_EVENT_GROUP = 1,
19-
};
20-
2117
static const struct genl_multicast_group thermal_genl_mcgrps[] = {
2218
[THERMAL_GENL_SAMPLING_GROUP] = { .name = THERMAL_GENL_SAMPLING_GROUP_NAME, },
2319
[THERMAL_GENL_EVENT_GROUP] = { .name = THERMAL_GENL_EVENT_GROUP_NAME, },
@@ -74,11 +70,12 @@ struct param {
7470

7571
typedef int (*cb_t)(struct param *);
7672

77-
static struct genl_family thermal_gnl_family;
73+
static struct genl_family thermal_genl_family;
74+
static BLOCKING_NOTIFIER_HEAD(thermal_genl_chain);
7875

7976
static int thermal_group_has_listeners(enum thermal_genl_multicast_groups group)
8077
{
81-
return genl_has_listeners(&thermal_gnl_family, &init_net, group);
78+
return genl_has_listeners(&thermal_genl_family, &init_net, group);
8279
}
8380

8481
/************************** Sampling encoding *******************************/
@@ -95,7 +92,7 @@ int thermal_genl_sampling_temp(int id, int temp)
9592
if (!skb)
9693
return -ENOMEM;
9794

98-
hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0,
95+
hdr = genlmsg_put(skb, 0, 0, &thermal_genl_family, 0,
9996
THERMAL_GENL_SAMPLING_TEMP);
10097
if (!hdr)
10198
goto out_free;
@@ -108,7 +105,7 @@ int thermal_genl_sampling_temp(int id, int temp)
108105

109106
genlmsg_end(skb, hdr);
110107

111-
genlmsg_multicast(&thermal_gnl_family, skb, 0, THERMAL_GENL_SAMPLING_GROUP, GFP_KERNEL);
108+
genlmsg_multicast(&thermal_genl_family, skb, 0, THERMAL_GENL_SAMPLING_GROUP, GFP_KERNEL);
112109

113110
return 0;
114111
out_cancel:
@@ -282,7 +279,7 @@ static int thermal_genl_send_event(enum thermal_genl_event event,
282279
return -ENOMEM;
283280
p->msg = msg;
284281

285-
hdr = genlmsg_put(msg, 0, 0, &thermal_gnl_family, 0, event);
282+
hdr = genlmsg_put(msg, 0, 0, &thermal_genl_family, 0, event);
286283
if (!hdr)
287284
goto out_free_msg;
288285

@@ -292,7 +289,7 @@ static int thermal_genl_send_event(enum thermal_genl_event event,
292289

293290
genlmsg_end(msg, hdr);
294291

295-
genlmsg_multicast(&thermal_gnl_family, msg, 0, THERMAL_GENL_EVENT_GROUP, GFP_KERNEL);
292+
genlmsg_multicast(&thermal_genl_family, msg, 0, THERMAL_GENL_EVENT_GROUP, GFP_KERNEL);
296293

297294
return 0;
298295

@@ -595,7 +592,7 @@ static int thermal_genl_cmd_dumpit(struct sk_buff *skb,
595592
int ret;
596593
void *hdr;
597594

598-
hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, cmd);
595+
hdr = genlmsg_put(skb, 0, 0, &thermal_genl_family, 0, cmd);
599596
if (!hdr)
600597
return -EMSGSIZE;
601598

@@ -627,7 +624,7 @@ static int thermal_genl_cmd_doit(struct sk_buff *skb,
627624
return -ENOMEM;
628625
p.msg = msg;
629626

630-
hdr = genlmsg_put_reply(msg, info, &thermal_gnl_family, 0, cmd);
627+
hdr = genlmsg_put_reply(msg, info, &thermal_genl_family, 0, cmd);
631628
if (!hdr)
632629
goto out_free_msg;
633630

@@ -647,6 +644,27 @@ static int thermal_genl_cmd_doit(struct sk_buff *skb,
647644
return ret;
648645
}
649646

647+
static int thermal_genl_bind(int mcgrp)
648+
{
649+
struct thermal_genl_notify n = { .mcgrp = mcgrp };
650+
651+
if (WARN_ON_ONCE(mcgrp > THERMAL_GENL_MAX_GROUP))
652+
return -EINVAL;
653+
654+
blocking_notifier_call_chain(&thermal_genl_chain, THERMAL_NOTIFY_BIND, &n);
655+
return 0;
656+
}
657+
658+
static void thermal_genl_unbind(int mcgrp)
659+
{
660+
struct thermal_genl_notify n = { .mcgrp = mcgrp };
661+
662+
if (WARN_ON_ONCE(mcgrp > THERMAL_GENL_MAX_GROUP))
663+
return;
664+
665+
blocking_notifier_call_chain(&thermal_genl_chain, THERMAL_NOTIFY_UNBIND, &n);
666+
}
667+
650668
static const struct genl_small_ops thermal_genl_ops[] = {
651669
{
652670
.cmd = THERMAL_GENL_CMD_TZ_GET_ID,
@@ -675,25 +693,37 @@ static const struct genl_small_ops thermal_genl_ops[] = {
675693
},
676694
};
677695

678-
static struct genl_family thermal_gnl_family __ro_after_init = {
696+
static struct genl_family thermal_genl_family __ro_after_init = {
679697
.hdrsize = 0,
680698
.name = THERMAL_GENL_FAMILY_NAME,
681699
.version = THERMAL_GENL_VERSION,
682700
.maxattr = THERMAL_GENL_ATTR_MAX,
683701
.policy = thermal_genl_policy,
702+
.bind = thermal_genl_bind,
703+
.unbind = thermal_genl_unbind,
684704
.small_ops = thermal_genl_ops,
685705
.n_small_ops = ARRAY_SIZE(thermal_genl_ops),
686706
.resv_start_op = THERMAL_GENL_CMD_CDEV_GET + 1,
687707
.mcgrps = thermal_genl_mcgrps,
688708
.n_mcgrps = ARRAY_SIZE(thermal_genl_mcgrps),
689709
};
690710

711+
int thermal_genl_register_notifier(struct notifier_block *nb)
712+
{
713+
return blocking_notifier_chain_register(&thermal_genl_chain, nb);
714+
}
715+
716+
int thermal_genl_unregister_notifier(struct notifier_block *nb)
717+
{
718+
return blocking_notifier_chain_unregister(&thermal_genl_chain, nb);
719+
}
720+
691721
int __init thermal_netlink_init(void)
692722
{
693-
return genl_register_family(&thermal_gnl_family);
723+
return genl_register_family(&thermal_genl_family);
694724
}
695725

696726
void __init thermal_netlink_exit(void)
697727
{
698-
genl_unregister_family(&thermal_gnl_family);
728+
genl_unregister_family(&thermal_genl_family);
699729
}

drivers/thermal/thermal_netlink.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@ struct thermal_genl_cpu_caps {
1010
int efficiency;
1111
};
1212

13+
enum thermal_genl_multicast_groups {
14+
THERMAL_GENL_SAMPLING_GROUP = 0,
15+
THERMAL_GENL_EVENT_GROUP = 1,
16+
THERMAL_GENL_MAX_GROUP = THERMAL_GENL_EVENT_GROUP,
17+
};
18+
19+
#define THERMAL_NOTIFY_BIND 0
20+
#define THERMAL_NOTIFY_UNBIND 1
21+
22+
struct thermal_genl_notify {
23+
int mcgrp;
24+
};
25+
1326
struct thermal_zone_device;
1427
struct thermal_trip;
1528
struct thermal_cooling_device;
@@ -18,6 +31,9 @@ struct thermal_cooling_device;
1831
#ifdef CONFIG_THERMAL_NETLINK
1932
int __init thermal_netlink_init(void);
2033
void __init thermal_netlink_exit(void);
34+
int thermal_genl_register_notifier(struct notifier_block *nb);
35+
int thermal_genl_unregister_notifier(struct notifier_block *nb);
36+
2137
int thermal_notify_tz_create(const struct thermal_zone_device *tz);
2238
int thermal_notify_tz_delete(const struct thermal_zone_device *tz);
2339
int thermal_notify_tz_enable(const struct thermal_zone_device *tz);
@@ -48,6 +64,16 @@ static inline int thermal_notify_tz_create(const struct thermal_zone_device *tz)
4864
return 0;
4965
}
5066

67+
static inline int thermal_genl_register_notifier(struct notifier_block *nb)
68+
{
69+
return 0;
70+
}
71+
72+
static inline int thermal_genl_unregister_notifier(struct notifier_block *nb)
73+
{
74+
return 0;
75+
}
76+
5177
static inline int thermal_notify_tz_delete(const struct thermal_zone_device *tz)
5278
{
5379
return 0;

0 commit comments

Comments
 (0)