Attachment 'thermal_management-13.3-RELEASE.diff'
Download 1 diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf
2 index 824751078833..54bd19a7d42a 100644
3 --- a/libexec/rc/rc.conf
4 +++ b/libexec/rc/rc.conf
5 @@ -718,8 +718,12 @@ devfs_set_rulesets="" # A list of /mount/dev=ruleset_name settings to
6 devfs_load_rulesets="YES" # Enable to always load the default rulesets
7 performance_cx_lowest="NONE" # Online CPU idle state
8 performance_cpu_freq="NONE" # Online CPU frequency
9 +performance_tz0_active="NONE" # Online forced active cooling zone
10 +performance_tz0_PSV="NONE" # Online passive cooling threshold
11 economy_cx_lowest="Cmax" # Offline CPU idle state
12 economy_cpu_freq="NONE" # Offline CPU frequency
13 +economy_tz0_active="NONE" # Offline forced active cooling zone
14 +economy_tz0_PSV="NONE" # Offline passive cooling threshold
15 virecover_enable="YES" # Perform housekeeping for the vi(1) editor
16 ugidfw_enable="NO" # Load mac_bsdextended(4) rules on boot
17 bsdextended_script="/etc/rc.bsdextended" # Default mac_bsdextended(4)
18 diff --git a/libexec/rc/rc.d/power_profile b/libexec/rc/rc.d/power_profile
19 index 71f3f3ad8792..ec07eb920c93 100755
20 --- a/libexec/rc/rc.d/power_profile
21 +++ b/libexec/rc/rc.d/power_profile
22 @@ -79,6 +79,14 @@ case ${state} in
23 esac
24
25 # Set the various sysctls based on the profile's values.
26 +node="hw.acpi.thermal.tz0._PSV"
27 +eval value=\$${profile}_tz0_PSV
28 +sysctl_set
29 +
30 +node="hw.acpi.thermal.tz0.active"
31 +eval value=\$${profile}_tz0_active
32 +sysctl_set
33 +
34 node="hw.acpi.cpu.cx_lowest"
35 highest_value="C1"
36 lowest_value="Cmax"
37 diff --git a/share/man/man4/acpi_thermal.4 b/share/man/man4/acpi_thermal.4
38 index 3961ed36276c..256aa978b486 100644
39 --- a/share/man/man4/acpi_thermal.4
40 +++ b/share/man/man4/acpi_thermal.4
41 @@ -22,7 +22,7 @@
42 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 .\" SUCH DAMAGE.
44 .\"
45 -.Dd March 17, 2007
46 +.Dd July 31, 2022
47 .Dt ACPI_THERMAL 4
48 .Os
49 .Sh NAME
50 @@ -82,6 +82,9 @@ Current temperature for this zone.
51 .It Va hw.acpi.thermal.tz%d._PSV
52 Temperature to start passive cooling by throttling down CPU, etc.
53 This value can be overridden by the user.
54 +.It Va hw.acpi.thermal.tz%d._CR3
55 +Temperature to start critical suspend to RAM (S3).
56 +This value can be overridden by the user.
57 .It Va hw.acpi.thermal.tz%d._HOT
58 Temperature to start critical suspend to disk (S4).
59 This value can be overridden by the user.
60 diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c
61 index c436390d84b4..fb7a478fd479 100644
62 --- a/sys/dev/acpica/acpi_thermal.c
63 +++ b/sys/dev/acpica/acpi_thermal.c
64 @@ -58,7 +58,7 @@ ACPI_MODULE_NAME("THERMAL")
65 #define TZ_NOTIFY_TEMPERATURE 0x80 /* Temperature changed. */
66 #define TZ_NOTIFY_LEVELS 0x81 /* Cooling levels changed. */
67 #define TZ_NOTIFY_DEVICES 0x82 /* Device lists changed. */
68 -#define TZ_NOTIFY_CRITICAL 0xcc /* Fake notify that _CRT/_HOT reached. */
69 +#define TZ_NOTIFY_CRITICAL 0xcc /* Fake notify that _CRT/_HOT/_CR3 reached. */
70
71 /* Check for temperature changes every 10 seconds by default */
72 #define TZ_POLLRATE 10
73 @@ -76,6 +76,7 @@ struct acpi_tz_zone {
74 ACPI_BUFFER al[TZ_NUMLEVELS];
75 int crt;
76 int hot;
77 + int cr3;
78 ACPI_BUFFER psl;
79 int psv;
80 int tc1;
81 @@ -95,8 +96,9 @@ struct acpi_tz_softc {
82 int tz_thflags; /*Current temp-related flags*/
83 #define TZ_THFLAG_NONE 0
84 #define TZ_THFLAG_PSV (1<<0)
85 -#define TZ_THFLAG_HOT (1<<2)
86 -#define TZ_THFLAG_CRT (1<<3)
87 +#define TZ_THFLAG_CR3 (1<<2)
88 +#define TZ_THFLAG_HOT (1<<3)
89 +#define TZ_THFLAG_CRT (1<<4)
90 int tz_flags;
91 #define TZ_FLAG_NO_SCP (1<<0) /*No _SCP method*/
92 #define TZ_FLAG_GETPROFILE (1<<1) /*Get power_profile in timeout*/
93 @@ -280,6 +282,10 @@ acpi_tz_attach(device_t dev)
94 OID_AUTO, "_PSV", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
95 offsetof(struct acpi_tz_softc, tz_zone.psv), acpi_tz_temp_sysctl, "IK",
96 "passive cooling temp setpoint");
97 + SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
98 + OID_AUTO, "_CR3", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
99 + offsetof(struct acpi_tz_softc, tz_zone.cr3), acpi_tz_temp_sysctl, "IK",
100 + "too warm temp setpoint (standby now)");
101 SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
102 OID_AUTO, "_HOT", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
103 offsetof(struct acpi_tz_softc, tz_zone.hot), acpi_tz_temp_sysctl, "IK",
104 @@ -419,6 +425,7 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
105 }
106 acpi_tz_getparam(sc, "_CRT", &sc->tz_zone.crt);
107 acpi_tz_getparam(sc, "_HOT", &sc->tz_zone.hot);
108 + acpi_tz_getparam(sc, "_CR3", &sc->tz_zone.cr3);
109 sc->tz_zone.psl.Length = ACPI_ALLOCATE_BUFFER;
110 sc->tz_zone.psl.Pointer = NULL;
111 AcpiEvaluateObject(sc->tz_handle, "_PSL", NULL, &sc->tz_zone.psl);
112 @@ -436,6 +443,7 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
113 */
114 acpi_tz_sanity(sc, &sc->tz_zone.crt, "_CRT");
115 acpi_tz_sanity(sc, &sc->tz_zone.hot, "_HOT");
116 + acpi_tz_sanity(sc, &sc->tz_zone.cr3, "_CR3");
117 acpi_tz_sanity(sc, &sc->tz_zone.psv, "_PSV");
118 for (i = 0; i < TZ_NUMLEVELS; i++)
119 acpi_tz_sanity(sc, &sc->tz_zone.ac[i], "_ACx");
120 @@ -493,6 +501,7 @@ acpi_tz_get_temperature(struct acpi_tz_softc *sc)
121 static void
122 acpi_tz_monitor(void *Context)
123 {
124 + struct acpi_softc *acpi_sc;
125 struct acpi_tz_softc *sc;
126 struct timespec curtime;
127 int temp;
128 @@ -543,6 +552,8 @@ acpi_tz_monitor(void *Context)
129 newflags = TZ_THFLAG_NONE;
130 if (sc->tz_zone.psv != -1 && temp >= sc->tz_zone.psv)
131 newflags |= TZ_THFLAG_PSV;
132 + if (sc->tz_zone.cr3 != -1 && temp >= sc->tz_zone.cr3)
133 + newflags |= TZ_THFLAG_CR3;
134 if (sc->tz_zone.hot != -1 && temp >= sc->tz_zone.hot)
135 newflags |= TZ_THFLAG_HOT;
136 if (sc->tz_zone.crt != -1 && temp >= sc->tz_zone.crt)
137 @@ -593,7 +604,7 @@ acpi_tz_monitor(void *Context)
138 /* XXX (de)activate any passive cooling that may be required. */
139
140 /*
141 - * If the temperature is at _HOT or _CRT, increment our event count.
142 + * If the temperature is at _CR3, _HOT or _CRT, increment our event count.
143 * If it has occurred enough times, shutdown the system. This is
144 * needed because some systems will report an invalid high temperature
145 * for one poll cycle. It is suspected this is due to the embedded
146 @@ -602,13 +613,18 @@ acpi_tz_monitor(void *Context)
147 *
148 * If we're almost at that threshold, notify the user through devd(8).
149 */
150 - if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) {
151 + if ((newflags & (TZ_THFLAG_CR3 | TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) {
152 sc->tz_validchecks++;
153 if (sc->tz_validchecks == TZ_VALIDCHECKS) {
154 device_printf(sc->tz_dev,
155 "WARNING - current temperature (%d.%dC) exceeds safe limits\n",
156 TZ_KELVTOC(sc->tz_temperature));
157 - shutdown_nice(RB_POWEROFF);
158 + if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0)
159 + shutdown_nice(RB_POWEROFF);
160 + else {
161 + acpi_sc = acpi_device_get_parent_softc(sc->tz_dev);
162 + acpi_ReqSleepState(acpi_sc, ACPI_STATE_S3);
163 + }
164 } else if (sc->tz_validchecks == TZ_NOTIFYCOUNT)
165 acpi_UserNotify("Thermal", sc->tz_handle, TZ_NOTIFY_CRITICAL);
166 } else {
167 @@ -1004,51 +1020,68 @@ acpi_tz_thread(void *arg)
168 static int
169 acpi_tz_cpufreq_restore(struct acpi_tz_softc *sc)
170 {
171 - device_t dev;
172 - int error;
173 + device_t *devs;
174 + int devcount, error, n;
175
176 if (!sc->tz_cooling_updated)
177 return (0);
178 - if ((dev = devclass_get_device(devclass_find("cpufreq"), 0)) == NULL)
179 +
180 + if ((error = devclass_get_devices(devclass_find("cpufreq"), &devs, &devcount))) {
181 + free(devs, M_TEMP);
182 return (ENXIO);
183 + }
184 +
185 ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
186 "temperature %d.%dC: resuming previous clock speed (%d MHz)\n",
187 TZ_KELVTOC(sc->tz_temperature), sc->tz_cooling_saved_freq);
188 - error = CPUFREQ_SET(dev, NULL, CPUFREQ_PRIO_KERN);
189 + for (n = 0; n < devcount; n++) {
190 + if ((error = CPUFREQ_SET(devs[n], NULL, CPUFREQ_PRIO_KERN))) {
191 + /*
192 + * If you find yourself here: cf_set_method() in kern_cpu.c
193 + * requires CPUFREQ_GET() be run before CPUFREQ_SET(), otherwise on
194 + * a restore sc->curr_level.total_set.freq = CPUFREQ_VAL_UNKNOWN,
195 + * and then if it hasn't been updated the next save/restore will fail.
196 + */
197 + device_printf(sc->tz_dev, "cpu%d: failed to restore cpufreq priority\n", n);
198 + break;
199 + }
200 + }
201 if (error == 0)
202 sc->tz_cooling_updated = FALSE;
203 +
204 + free(devs, M_TEMP);
205 return (error);
206 }
207
208 static int
209 acpi_tz_cpufreq_update(struct acpi_tz_softc *sc, int req)
210 {
211 - device_t dev;
212 + device_t *devs;
213 struct cf_level *levels;
214 - int num_levels, error, freq, desired_freq, perf, i;
215 + int num_levels, error, freq, desired_freq, perf, devcount, i, n;
216
217 levels = malloc(CPUFREQ_MAX_LEVELS * sizeof(*levels), M_TEMP, M_NOWAIT);
218 if (levels == NULL)
219 return (ENOMEM);
220
221 /*
222 - * Find the main device, cpufreq0. We don't yet support independent
223 - * CPU frequency control on SMP.
224 + * Find the main device, cpufreq0. We make plans based upon cpu0, and
225 + * change all the cpu frequencies to the same level.
226 */
227 - if ((dev = devclass_get_device(devclass_find("cpufreq"), 0)) == NULL) {
228 - error = ENXIO;
229 + if ((error = devclass_get_devices(devclass_find("cpufreq"), &devs, &devcount))) {
230 + free(devs, M_TEMP);
231 goto out;
232 }
233
234 - /* Get the current frequency. */
235 - error = CPUFREQ_GET(dev, &levels[0]);
236 + /* Get the current frequency for cpu0. */
237 + error = CPUFREQ_GET(devs[0], &levels[0]);
238 if (error)
239 goto out;
240 freq = levels[0].total_set.freq;
241
242 - /* Get the current available frequency levels. */
243 + /* Get the current available frequency levels for cpu0. */
244 num_levels = CPUFREQ_MAX_LEVELS;
245 - error = CPUFREQ_LEVELS(dev, levels, &num_levels);
246 + error = CPUFREQ_LEVELS(devs[0], levels, &num_levels);
247 if (error) {
248 if (error == E2BIG)
249 printf("cpufreq: need to increase CPUFREQ_MAX_LEVELS\n");
250 @@ -1109,8 +1142,22 @@ acpi_tz_cpufreq_update(struct acpi_tz_softc *sc, int req)
251 TZ_KELVTOC(sc->tz_temperature),
252 (freq > levels[i].total_set.freq) ? "de" : "in",
253 freq, levels[i].total_set.freq);
254 - error = CPUFREQ_SET(dev, &levels[i], CPUFREQ_PRIO_KERN);
255 - if (error == 0 && !sc->tz_cooling_updated) {
256 +
257 + /* Change all the cpus to the chosen frequency. */
258 + for (n = 0; n < devcount; n++) {
259 + /* CPUFREQ_SET() fails occasionally without this. */
260 + if ((error = CPUFREQ_GET(devs[n], &levels[0])))
261 + goto out;
262 +
263 + if ((error = CPUFREQ_LEVELS(devs[n], levels, &num_levels))) {
264 + if (error == E2BIG)
265 + printf("cpufreq: need to increase CPUFREQ_MAX_LEVELS\n");
266 + goto out;
267 + }
268 + if ((error = CPUFREQ_SET(devs[n], &levels[i], CPUFREQ_PRIO_KERN)))
269 + goto out;
270 + }
271 + if (!sc->tz_cooling_updated) {
272 sc->tz_cooling_saved_freq = freq;
273 sc->tz_cooling_updated = TRUE;
274 }
275 @@ -1119,6 +1166,7 @@ acpi_tz_cpufreq_update(struct acpi_tz_softc *sc, int req)
276 out:
277 if (levels)
278 free(levels, M_TEMP);
279 + free(devs, M_TEMP);
280 return (error);
281 }
282
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.