/* *Ratecontroldelay:Ideaistointroducedenounceeffect *Thisshouldbelongenoughtoavoidreduceevents,when *thresholdissettoatemperature,whichisconstantly *violated,butattheshortenoughtotakeanyaction. *Theactioncanberemovethresholdorchangeittonext *interestingsetting.Basedonexperiments,inaround *every5secondsunderloadwillgiveusasignificant *temperaturechange.
*/ #define PKG_TEMP_THERMAL_NOTIFY_DELAY 5000 staticint notify_delay_ms = PKG_TEMP_THERMAL_NOTIFY_DELAY;
module_param(notify_delay_ms, int, 0644);
MODULE_PARM_DESC(notify_delay_ms, "User space notification delay in milli seconds.");
/* Number of trip points in thermal zone. Currently it can't *bemorethan2.MSRcanallowsettingandgettingnotifications *foronly2thresholds.Thisdefineenforcesthis,ifthere *issomewrongvaluesreturnedbycpuidfornumberofthresholds.
*/ #define MAX_NUMBER_OF_TRIPS 2
/* Keep track of how many zone pointers we allocated in init() */ staticint max_id __read_mostly; /* Array of zone pointers */ staticstruct zone_device **zones; /* Serializes interrupt notification, work and hotplug */ static DEFINE_RAW_SPINLOCK(pkg_temp_lock); /* Protects zone operation in the work function against hotplug removal */ static DEFINE_MUTEX(thermal_zone_mutex);
/* The dynamically assigned cpu hotplug state for module_exit() */ staticenum cpuhp_state pkg_thermal_hp_state __read_mostly;
/* Debug counters to show using debugfs */ staticstruct dentry *debugfs; staticunsignedint pkg_interrupt_cnt; staticunsignedint pkg_work_cnt;
/* Enable threshold interrupt on local package/cpu */ staticinlinevoid enable_pkg_thres_interrupt(void)
{
u8 thres_0, thres_1;
u32 l, h;
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); /* only enable/disable if it had valid threshold value */
thres_0 = (l & THERM_MASK_THRESHOLD0) >> THERM_SHIFT_THRESHOLD0;
thres_1 = (l & THERM_MASK_THRESHOLD1) >> THERM_SHIFT_THRESHOLD1; if (thres_0)
l |= THERM_INT_THRESHOLD0_ENABLE; if (thres_1)
l |= THERM_INT_THRESHOLD1_ENABLE;
wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
}
/* Disable threshold interrupt on local package/cpu */ staticinlinevoid disable_pkg_thres_interrupt(void)
{
u32 l, h;
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
l &= ~(THERM_INT_THRESHOLD0_ENABLE | THERM_INT_THRESHOLD1_ENABLE);
wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
}
staticvoid pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
{ struct thermal_zone_device *tzone = NULL; int cpu = smp_processor_id(); struct zone_device *zonedev;
/* Work is per package, so scheduling it once is enough. */
zonedev = pkg_temp_thermal_get_dev(cpu); if (zonedev && !zonedev->work_scheduled) {
zonedev->work_scheduled = true;
pkg_thermal_schedule_work(zonedev->cpu, &zonedev->work);
}
/* Store MSR value for package thermal interrupt, to restore at exit */
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low,
zonedev->msr_pkg_therm_high);
/* If the package exists, nothing to do */ if (zonedev) {
cpumask_set_cpu(cpu, &zonedev->cpumask); return0;
} return pkg_temp_thermal_device_add(cpu);
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.12Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.