···58835883F: include/linux/clk-pr*58845884F: include/linux/clk/58855885F: include/linux/of_clk.h58865886+F: rust/helpers/clk.c58875887+F: rust/kernel/clk.rs58865888X: drivers/clk/clkdev.c5887588958885890COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)···61426140F: include/linux/cpufreq.h61436141F: include/linux/sched/cpufreq.h61446142F: kernel/sched/cpufreq*.c61436143+F: rust/kernel/cpufreq.rs61456144F: tools/testing/selftests/cpufreq/6146614561476146CPU HOTPLUG···61566153F: include/linux/smpboot.h61576154F: kernel/cpu.c61586155F: kernel/smpboot.*61566156+F: rust/kernel/cpu.rs6159615761606158CPU IDLE TIME MANAGEMENT FRAMEWORK61616159M: "Rafael J. Wysocki" <rafael@kernel.org>···62406236L: linux-riscv@lists.infradead.org62416237S: Maintained62426238F: drivers/cpuidle/cpuidle-riscv-sbi.c62396239+62406240+CPUMASK API [RUST]62416241+M: Viresh Kumar <viresh.kumar@linaro.org>62426242+R: Yury Norov <yury.norov@gmail.com>62436243+S: Maintained62446244+F: rust/kernel/cpumask.rs6243624562446246CRAMFS FILESYSTEM62456247M: Nicolas Pitre <nico@fluxnic.net>···1816618156F: Documentation/power/opp.rst1816718157F: drivers/opp/1816818158F: include/linux/pm_opp.h1815918159+F: rust/kernel/opp.rs18169181601817018161OPL4 DRIVER1817118162M: Clemens Ladisch <clemens@ladisch.de>
+12
drivers/cpufreq/Kconfig
···217217218218 If in doubt, say N.219219220220+config CPUFREQ_DT_RUST221221+ tristate "Rust based Generic DT based cpufreq driver"222222+ depends on HAVE_CLK && OF && RUST223223+ select CPUFREQ_DT_PLATDEV224224+ select PM_OPP225225+ help226226+ This adds a Rust based generic DT based cpufreq driver for frequency227227+ management. It supports both uniprocessor (UP) and symmetric228228+ multiprocessor (SMP) systems.229229+230230+ If in doubt, say N.231231+220232config CPUFREQ_VIRT221233 tristate "Virtual cpufreq driver"222234 depends on GENERIC_ARCH_TOPOLOGY
···821821 schedule_work(&sched_prefcore_work);822822}823823824824-static void amd_pstate_update_limits(unsigned int cpu)824824+static void amd_pstate_update_limits(struct cpufreq_policy *policy)825825{826826- struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu);827826 struct amd_cpudata *cpudata;828827 u32 prev_high = 0, cur_high = 0;829828 bool highest_perf_changed = false;829829+ unsigned int cpu = policy->cpu;830830831831 if (!amd_pstate_prefcore)832832- return;833833-834834- if (!policy)835832 return;836833837834 if (amd_get_highest_perf(cpu, &cur_high))
+152-199
drivers/cpufreq/cpufreq.c
···255255}256256EXPORT_SYMBOL_GPL(cpufreq_cpu_put);257257258258-/**259259- * cpufreq_cpu_release - Unlock a policy and decrement its usage counter.260260- * @policy: cpufreq policy returned by cpufreq_cpu_acquire().261261- */262262-void cpufreq_cpu_release(struct cpufreq_policy *policy)263263-{264264- if (WARN_ON(!policy))265265- return;266266-267267- lockdep_assert_held(&policy->rwsem);268268-269269- up_write(&policy->rwsem);270270-271271- cpufreq_cpu_put(policy);272272-}273273-274274-/**275275- * cpufreq_cpu_acquire - Find policy for a CPU, mark it as busy and lock it.276276- * @cpu: CPU to find the policy for.277277- *278278- * Call cpufreq_cpu_get() to get a reference on the cpufreq policy for @cpu and279279- * if the policy returned by it is not NULL, acquire its rwsem for writing.280280- * Return the policy if it is active or release it and return NULL otherwise.281281- *282282- * The policy returned by this function has to be released with the help of283283- * cpufreq_cpu_release() in order to release its rwsem and balance its usage284284- * counter properly.285285- */286286-struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu)287287-{288288- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);289289-290290- if (!policy)291291- return NULL;292292-293293- down_write(&policy->rwsem);294294-295295- if (policy_is_inactive(policy)) {296296- cpufreq_cpu_release(policy);297297- return NULL;298298- }299299-300300- return policy;301301-}302302-303258/*********************************************************************304259 * EXTERNALLY AFFECTING FREQUENCY CHANGES *305260 *********************************************************************/···9641009{9651010 struct cpufreq_policy *policy = to_policy(kobj);9661011 struct freq_attr *fattr = to_attr(attr);967967- ssize_t ret = -EBUSY;96810129691013 if (!fattr->show)9701014 return -EIO;9711015972972- down_read(&policy->rwsem);973973- if (likely(!policy_is_inactive(policy)))974974- ret = fattr->show(policy, buf);975975- up_read(&policy->rwsem);10161016+ guard(cpufreq_policy_read)(policy);9761017977977- return ret;10181018+ if (likely(!policy_is_inactive(policy)))10191019+ return fattr->show(policy, buf);10201020+10211021+ return -EBUSY;9781022}97910239801024static ssize_t store(struct kobject *kobj, struct attribute *attr,···9811027{9821028 struct cpufreq_policy *policy = to_policy(kobj);9831029 struct freq_attr *fattr = to_attr(attr);984984- ssize_t ret = -EBUSY;98510309861031 if (!fattr->store)9871032 return -EIO;9881033989989- down_write(&policy->rwsem);990990- if (likely(!policy_is_inactive(policy)))991991- ret = fattr->store(policy, buf, count);992992- up_write(&policy->rwsem);10341034+ guard(cpufreq_policy_write)(policy);9931035994994- return ret;10361036+ if (likely(!policy_is_inactive(policy)))10371037+ return fattr->store(policy, buf, count);10381038+10391039+ return -EBUSY;9951040}99610419971042static void cpufreq_sysfs_release(struct kobject *kobj)···11481195 if (cpumask_test_cpu(cpu, policy->cpus))11491196 return 0;1150119711511151- down_write(&policy->rwsem);11981198+ guard(cpufreq_policy_write)(policy);11991199+11521200 if (has_target())11531201 cpufreq_stop_governor(policy);11541202···11601206 if (ret)11611207 pr_err("%s: Failed to start governor\n", __func__);11621208 }11631163- up_write(&policy->rwsem);12091209+11641210 return ret;11651211}11661212···11801226 container_of(work, struct cpufreq_policy, update);1181122711821228 pr_debug("handle_update for cpu %u called\n", policy->cpu);11831183- down_write(&policy->rwsem);12291229+12301230+ guard(cpufreq_policy_write)(policy);12311231+11841232 refresh_frequency_limits(policy);11851185- up_write(&policy->rwsem);11861233}1187123411881235static int cpufreq_notifier_min(struct notifier_block *nb, unsigned long freq,···12091254 struct kobject *kobj;12101255 struct completion *cmp;1211125612121212- down_write(&policy->rwsem);12131213- cpufreq_stats_free_table(policy);12141214- kobj = &policy->kobj;12151215- cmp = &policy->kobj_unregister;12161216- up_write(&policy->rwsem);12571257+ scoped_guard(cpufreq_policy_write, policy) {12581258+ cpufreq_stats_free_table(policy);12591259+ kobj = &policy->kobj;12601260+ cmp = &policy->kobj_unregister;12611261+ }12171262 kobject_put(kobj);1218126312191264 /*···12891334 init_waitqueue_head(&policy->transition_wait);12901335 INIT_WORK(&policy->update, handle_update);1291133612921292- policy->cpu = cpu;12931337 return policy;1294133812951339err_min_qos_notifier:···13571403 kfree(policy);13581404}1359140513601360-static int cpufreq_online(unsigned int cpu)14061406+static int cpufreq_policy_online(struct cpufreq_policy *policy,14071407+ unsigned int cpu, bool new_policy)13611408{13621362- struct cpufreq_policy *policy;13631363- bool new_policy;13641409 unsigned long flags;13651410 unsigned int j;13661411 int ret;1367141213681368- pr_debug("%s: bringing CPU%u online\n", __func__, cpu);14131413+ guard(cpufreq_policy_write)(policy);1369141413701370- /* Check if this CPU already has a policy to manage it */13711371- policy = per_cpu(cpufreq_cpu_data, cpu);13721372- if (policy) {13731373- WARN_ON(!cpumask_test_cpu(cpu, policy->related_cpus));13741374- if (!policy_is_inactive(policy))13751375- return cpufreq_add_policy_cpu(policy, cpu);13761376-13771377- /* This is the only online CPU for the policy. Start over. */13781378- new_policy = false;13791379- down_write(&policy->rwsem);13801380- policy->cpu = cpu;13811381- policy->governor = NULL;13821382- } else {13831383- new_policy = true;13841384- policy = cpufreq_policy_alloc(cpu);13851385- if (!policy)13861386- return -ENOMEM;13871387- down_write(&policy->rwsem);13881388- }14151415+ policy->cpu = cpu;14161416+ policy->governor = NULL;1389141713901418 if (!new_policy && cpufreq_driver->online) {13911419 /* Recover policy->cpus using related_cpus */···13901454 if (ret) {13911455 pr_debug("%s: %d: initialization failed\n", __func__,13921456 __LINE__);13931393- goto out_free_policy;14571457+ goto out_clear_policy;13941458 }1395145913961460 /*···15411605 goto out_destroy_policy;15421606 }1543160715441544- up_write(&policy->rwsem);16081608+ return 0;16091609+16101610+out_destroy_policy:16111611+ for_each_cpu(j, policy->real_cpus)16121612+ remove_cpu_dev_symlink(policy, j, get_cpu_device(j));16131613+16141614+out_offline_policy:16151615+ if (cpufreq_driver->offline)16161616+ cpufreq_driver->offline(policy);16171617+16181618+out_exit_policy:16191619+ if (cpufreq_driver->exit)16201620+ cpufreq_driver->exit(policy);16211621+16221622+out_clear_policy:16231623+ cpumask_clear(policy->cpus);16241624+16251625+ return ret;16261626+}16271627+16281628+static int cpufreq_online(unsigned int cpu)16291629+{16301630+ struct cpufreq_policy *policy;16311631+ bool new_policy;16321632+ int ret;16331633+16341634+ pr_debug("%s: bringing CPU%u online\n", __func__, cpu);16351635+16361636+ /* Check if this CPU already has a policy to manage it */16371637+ policy = per_cpu(cpufreq_cpu_data, cpu);16381638+ if (policy) {16391639+ WARN_ON(!cpumask_test_cpu(cpu, policy->related_cpus));16401640+ if (!policy_is_inactive(policy))16411641+ return cpufreq_add_policy_cpu(policy, cpu);16421642+16431643+ /* This is the only online CPU for the policy. Start over. */16441644+ new_policy = false;16451645+ } else {16461646+ new_policy = true;16471647+ policy = cpufreq_policy_alloc(cpu);16481648+ if (!policy)16491649+ return -ENOMEM;16501650+ }16511651+16521652+ ret = cpufreq_policy_online(policy, cpu, new_policy);16531653+ if (ret) {16541654+ cpufreq_policy_free(policy);16551655+ return ret;16561656+ }1545165715461658 kobject_uevent(&policy->kobj, KOBJ_ADD);15471659···16171633 pr_debug("initialization complete\n");1618163416191635 return 0;16201620-16211621-out_destroy_policy:16221622- for_each_cpu(j, policy->real_cpus)16231623- remove_cpu_dev_symlink(policy, j, get_cpu_device(j));16241624-16251625-out_offline_policy:16261626- if (cpufreq_driver->offline)16271627- cpufreq_driver->offline(policy);16281628-16291629-out_exit_policy:16301630- if (cpufreq_driver->exit)16311631- cpufreq_driver->exit(policy);16321632-16331633-out_free_policy:16341634- cpumask_clear(policy->cpus);16351635- up_write(&policy->rwsem);16361636-16371637- cpufreq_policy_free(policy);16381638- return ret;16391636}1640163716411638/**···17061741 return 0;17071742 }1708174317091709- down_write(&policy->rwsem);17441744+ guard(cpufreq_policy_write)(policy);1710174517111746 __cpufreq_offline(cpu, policy);1712174717131713- up_write(&policy->rwsem);17141748 return 0;17151749}17161750···17261762 if (!policy)17271763 return;1728176417291729- down_write(&policy->rwsem);17651765+ scoped_guard(cpufreq_policy_write, policy) {17661766+ if (cpu_online(cpu))17671767+ __cpufreq_offline(cpu, policy);1730176817311731- if (cpu_online(cpu))17321732- __cpufreq_offline(cpu, policy);17691769+ remove_cpu_dev_symlink(policy, cpu, dev);1733177017341734- remove_cpu_dev_symlink(policy, cpu, dev);17711771+ if (!cpumask_empty(policy->real_cpus))17721772+ return;1735177317361736- if (!cpumask_empty(policy->real_cpus)) {17371737- up_write(&policy->rwsem);17381738- return;17741774+ /*17751775+ * Unregister cpufreq cooling once all the CPUs of the policy17761776+ * are removed.17771777+ */17781778+ if (cpufreq_thermal_control_enabled(cpufreq_driver)) {17791779+ cpufreq_cooling_unregister(policy->cdev);17801780+ policy->cdev = NULL;17811781+ }17821782+17831783+ /* We did light-weight exit earlier, do full tear down now */17841784+ if (cpufreq_driver->offline && cpufreq_driver->exit)17851785+ cpufreq_driver->exit(policy);17391786 }17401740-17411741- /*17421742- * Unregister cpufreq cooling once all the CPUs of the policy are17431743- * removed.17441744- */17451745- if (cpufreq_thermal_control_enabled(cpufreq_driver)) {17461746- cpufreq_cooling_unregister(policy->cdev);17471747- policy->cdev = NULL;17481748- }17491749-17501750- /* We did light-weight exit earlier, do full tear down now */17511751- if (cpufreq_driver->offline && cpufreq_driver->exit)17521752- cpufreq_driver->exit(policy);17531753-17541754- up_write(&policy->rwsem);1755178717561788 cpufreq_policy_free(policy);17571789}···18181858 */18191859unsigned int cpufreq_quick_get(unsigned int cpu)18201860{18211821- struct cpufreq_policy *policy;18221822- unsigned int ret_freq = 0;18611861+ struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL;18231862 unsigned long flags;1824186318251864 read_lock_irqsave(&cpufreq_driver_lock, flags);1826186518271866 if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) {18281828- ret_freq = cpufreq_driver->get(cpu);18671867+ unsigned int ret_freq = cpufreq_driver->get(cpu);18681868+18291869 read_unlock_irqrestore(&cpufreq_driver_lock, flags);18701870+18301871 return ret_freq;18311872 }1832187318331874 read_unlock_irqrestore(&cpufreq_driver_lock, flags);1834187518351876 policy = cpufreq_cpu_get(cpu);18361836- if (policy) {18371837- ret_freq = policy->cur;18381838- cpufreq_cpu_put(policy);18391839- }18771877+ if (policy)18781878+ return policy->cur;1840187918411841- return ret_freq;18801880+ return 0;18421881}18431882EXPORT_SYMBOL(cpufreq_quick_get);18441883···18491890 */18501891unsigned int cpufreq_quick_get_max(unsigned int cpu)18511892{18521852- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);18531853- unsigned int ret_freq = 0;18931893+ struct cpufreq_policy *policy __free(put_cpufreq_policy);1854189418551855- if (policy) {18561856- ret_freq = policy->max;18571857- cpufreq_cpu_put(policy);18581858- }18951895+ policy = cpufreq_cpu_get(cpu);18961896+ if (policy)18971897+ return policy->max;1859189818601860- return ret_freq;18991899+ return 0;18611900}18621901EXPORT_SYMBOL(cpufreq_quick_get_max);18631902···18671910 */18681911__weak unsigned int cpufreq_get_hw_max_freq(unsigned int cpu)18691912{18701870- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);18711871- unsigned int ret_freq = 0;19131913+ struct cpufreq_policy *policy __free(put_cpufreq_policy);1872191418731873- if (policy) {18741874- ret_freq = policy->cpuinfo.max_freq;18751875- cpufreq_cpu_put(policy);18761876- }19151915+ policy = cpufreq_cpu_get(cpu);19161916+ if (policy)19171917+ return policy->cpuinfo.max_freq;1877191818781878- return ret_freq;19191919+ return 0;18791920}18801921EXPORT_SYMBOL(cpufreq_get_hw_max_freq);18811922···18931938 */18941939unsigned int cpufreq_get(unsigned int cpu)18951940{18961896- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);18971897- unsigned int ret_freq = 0;19411941+ struct cpufreq_policy *policy __free(put_cpufreq_policy);1898194218991899- if (policy) {19001900- down_read(&policy->rwsem);19011901- if (cpufreq_driver->get)19021902- ret_freq = __cpufreq_get(policy);19031903- up_read(&policy->rwsem);19431943+ policy = cpufreq_cpu_get(cpu);19441944+ if (!policy)19451945+ return 0;1904194619051905- cpufreq_cpu_put(policy);19061906- }19471947+ guard(cpufreq_policy_read)(policy);1907194819081908- return ret_freq;19491949+ if (cpufreq_driver->get)19501950+ return __cpufreq_get(policy);19511951+19521952+ return 0;19091953}19101954EXPORT_SYMBOL(cpufreq_get);19111955···1963200919642010 for_each_active_policy(policy) {19652011 if (has_target()) {19661966- down_write(&policy->rwsem);19671967- cpufreq_stop_governor(policy);19681968- up_write(&policy->rwsem);20122012+ scoped_guard(cpufreq_policy_write, policy) {20132013+ cpufreq_stop_governor(policy);20142014+ }19692015 }1970201619712017 if (cpufreq_driver->suspend && cpufreq_driver->suspend(policy))···20062052 pr_err("%s: Failed to resume driver: %s\n", __func__,20072053 cpufreq_driver->name);20082054 } else if (has_target()) {20092009- down_write(&policy->rwsem);20102010- ret = cpufreq_start_governor(policy);20112011- up_write(&policy->rwsem);20552055+ scoped_guard(cpufreq_policy_write, policy) {20562056+ ret = cpufreq_start_governor(policy);20572057+ }2012205820132059 if (ret)20142060 pr_err("%s: Failed to start governor for CPU%u's policy\n",···23752421 unsigned int target_freq,23762422 unsigned int relation)23772423{23782378- int ret;24242424+ guard(cpufreq_policy_write)(policy);2379242523802380- down_write(&policy->rwsem);23812381-23822382- ret = __cpufreq_driver_target(policy, target_freq, relation);23832383-23842384- up_write(&policy->rwsem);23852385-23862386- return ret;24262426+ return __cpufreq_driver_target(policy, target_freq, relation);23872427}23882428EXPORT_SYMBOL_GPL(cpufreq_driver_target);23892429···25592611 */25602612int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)25612613{25622562- struct cpufreq_policy *cpu_policy;26142614+ struct cpufreq_policy *cpu_policy __free(put_cpufreq_policy);26152615+25632616 if (!policy)25642617 return -EINVAL;25652618···2570262125712622 memcpy(policy, cpu_policy, sizeof(*policy));2572262325732573- cpufreq_cpu_put(cpu_policy);25742624 return 0;25752625}25762626EXPORT_SYMBOL(cpufreq_get_policy);···27172769 return ret;27182770}2719277127722772+static void cpufreq_policy_refresh(struct cpufreq_policy *policy)27732773+{27742774+ guard(cpufreq_policy_write)(policy);27752775+27762776+ /*27772777+ * BIOS might change freq behind our back27782778+ * -> ask driver for current freq and notify governors about a change27792779+ */27802780+ if (cpufreq_driver->get && has_target() &&27812781+ (cpufreq_suspended || WARN_ON(!cpufreq_verify_current_freq(policy, false))))27822782+ return;27832783+27842784+ refresh_frequency_limits(policy);27852785+}27862786+27202787/**27212788 * cpufreq_update_policy - Re-evaluate an existing cpufreq policy.27222789 * @cpu: CPU to re-evaluate the policy for.···27432780 */27442781void cpufreq_update_policy(unsigned int cpu)27452782{27462746- struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);27832783+ struct cpufreq_policy *policy __free(put_cpufreq_policy);2747278427852785+ policy = cpufreq_cpu_get(cpu);27482786 if (!policy)27492787 return;2750278827512751- /*27522752- * BIOS might change freq behind our back27532753- * -> ask driver for current freq and notify governors about a change27542754- */27552755- if (cpufreq_driver->get && has_target() &&27562756- (cpufreq_suspended || WARN_ON(!cpufreq_verify_current_freq(policy, false))))27572757- goto unlock;27582758-27592759- refresh_frequency_limits(policy);27602760-27612761-unlock:27622762- cpufreq_cpu_release(policy);27892789+ cpufreq_policy_refresh(policy);27632790}27642791EXPORT_SYMBOL(cpufreq_update_policy);27652792···27582805 * @cpu: CPU to update the policy limits for.27592806 *27602807 * Invoke the driver's ->update_limits callback if present or call27612761- * cpufreq_update_policy() for @cpu.28082808+ * cpufreq_policy_refresh() for @cpu.27622809 */27632810void cpufreq_update_limits(unsigned int cpu)27642811{···27692816 return;2770281727712818 if (cpufreq_driver->update_limits)27722772- cpufreq_driver->update_limits(cpu);28192819+ cpufreq_driver->update_limits(policy);27732820 else27742774- cpufreq_update_policy(cpu);28212821+ cpufreq_policy_refresh(policy);27752822}27762823EXPORT_SYMBOL_GPL(cpufreq_update_limits);27772824
+18-29
drivers/cpufreq/intel_pstate.c
···13531353 cpufreq_update_policy(cpu);13541354}1355135513561356-static void __intel_pstate_update_max_freq(struct cpudata *cpudata,13571357- struct cpufreq_policy *policy)13561356+static void __intel_pstate_update_max_freq(struct cpufreq_policy *policy,13571357+ struct cpudata *cpudata)13581358{13591359+ guard(cpufreq_policy_write)(policy);13601360+13591361 if (hwp_active)13601362 intel_pstate_get_hwp_cap(cpudata);13611363···13671365 refresh_frequency_limits(policy);13681366}1369136713701370-static void intel_pstate_update_limits(unsigned int cpu)13681368+static bool intel_pstate_update_max_freq(struct cpudata *cpudata)13711369{13721372- struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);13731373- struct cpudata *cpudata;13701370+ struct cpufreq_policy *policy __free(put_cpufreq_policy);1374137113721372+ policy = cpufreq_cpu_get(cpudata->cpu);13751373 if (!policy)13761376- return;13741374+ return false;1377137513781378- cpudata = all_cpu_data[cpu];13761376+ __intel_pstate_update_max_freq(policy, cpudata);1379137713801380- __intel_pstate_update_max_freq(cpudata, policy);13781378+ return true;13791379+}1381138013821382- /* Prevent the driver from being unregistered now. */13831383- mutex_lock(&intel_pstate_driver_lock);13811381+static void intel_pstate_update_limits(struct cpufreq_policy *policy)13821382+{13831383+ struct cpudata *cpudata = all_cpu_data[policy->cpu];1384138413851385- cpufreq_cpu_release(policy);13851385+ __intel_pstate_update_max_freq(policy, cpudata);1386138613871387 hybrid_update_capacity(cpudata);13881388-13891389- mutex_unlock(&intel_pstate_driver_lock);13901388}1391138913921390static void intel_pstate_update_limits_for_all(void)13931391{13941392 int cpu;1395139313961396- for_each_possible_cpu(cpu) {13971397- struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);13981398-13991399- if (!policy)14001400- continue;14011401-14021402- __intel_pstate_update_max_freq(all_cpu_data[cpu], policy);14031403-14041404- cpufreq_cpu_release(policy);14051405- }13941394+ for_each_possible_cpu(cpu)13951395+ intel_pstate_update_max_freq(all_cpu_data[cpu]);1406139614071397 mutex_lock(&hybrid_capacity_lock);14081398···18341840{18351841 struct cpudata *cpudata =18361842 container_of(to_delayed_work(work), struct cpudata, hwp_notify_work);18371837- struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpudata->cpu);1838184318391839- if (policy) {18401840- __intel_pstate_update_max_freq(cpudata, policy);18411841-18421842- cpufreq_cpu_release(policy);18431843-18441844+ if (intel_pstate_update_max_freq(cpudata)) {18441845 /*18451846 * The driver will not be unregistered while this function is18461847 * running, so update the capacity without acquiring the driver
+226
drivers/cpufreq/rcpufreq_dt.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+//! Rust based implementation of the cpufreq-dt driver.44+55+use kernel::{66+ c_str,77+ clk::Clk,88+ cpu, cpufreq,99+ cpumask::CpumaskVar,1010+ device::{Core, Device},1111+ error::code::*,1212+ fmt,1313+ macros::vtable,1414+ module_platform_driver, of, opp, platform,1515+ prelude::*,1616+ str::CString,1717+ sync::Arc,1818+};1919+2020+/// Finds exact supply name from the OF node.2121+fn find_supply_name_exact(dev: &Device, name: &str) -> Option<CString> {2222+ let prop_name = CString::try_from_fmt(fmt!("{}-supply", name)).ok()?;2323+ dev.property_present(&prop_name)2424+ .then(|| CString::try_from_fmt(fmt!("{name}")).ok())2525+ .flatten()2626+}2727+2828+/// Finds supply name for the CPU from DT.2929+fn find_supply_names(dev: &Device, cpu: u32) -> Option<KVec<CString>> {3030+ // Try "cpu0" for older DTs, fallback to "cpu".3131+ let name = (cpu == 0)3232+ .then(|| find_supply_name_exact(dev, "cpu0"))3333+ .flatten()3434+ .or_else(|| find_supply_name_exact(dev, "cpu"))?;3535+3636+ let mut list = KVec::with_capacity(1, GFP_KERNEL).ok()?;3737+ list.push(name, GFP_KERNEL).ok()?;3838+3939+ Some(list)4040+}4141+4242+/// Represents the cpufreq dt device.4343+struct CPUFreqDTDevice {4444+ opp_table: opp::Table,4545+ freq_table: opp::FreqTable,4646+ _mask: CpumaskVar,4747+ _token: Option<opp::ConfigToken>,4848+ _clk: Clk,4949+}5050+5151+#[derive(Default)]5252+struct CPUFreqDTDriver;5353+5454+#[vtable]5555+impl opp::ConfigOps for CPUFreqDTDriver {}5656+5757+#[vtable]5858+impl cpufreq::Driver for CPUFreqDTDriver {5959+ const NAME: &'static CStr = c_str!("cpufreq-dt");6060+ const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;6161+ const BOOST_ENABLED: bool = true;6262+6363+ type PData = Arc<CPUFreqDTDevice>;6464+6565+ fn init(policy: &mut cpufreq::Policy) -> Result<Self::PData> {6666+ let cpu = policy.cpu();6767+ // SAFETY: The CPU device is only used during init; it won't get hot-unplugged. The cpufreq6868+ // core registers with CPU notifiers and the cpufreq core/driver won't use the CPU device,6969+ // once the CPU is hot-unplugged.7070+ let dev = unsafe { cpu::from_cpu(cpu)? };7171+ let mut mask = CpumaskVar::new_zero(GFP_KERNEL)?;7272+7373+ mask.set(cpu);7474+7575+ let token = find_supply_names(dev, cpu)7676+ .map(|names| {7777+ opp::Config::<Self>::new()7878+ .set_regulator_names(names)?7979+ .set(dev)8080+ })8181+ .transpose()?;8282+8383+ // Get OPP-sharing information from "operating-points-v2" bindings.8484+ let fallback = match opp::Table::of_sharing_cpus(dev, &mut mask) {8585+ Ok(()) => false,8686+ Err(e) if e == ENOENT => {8787+ // "operating-points-v2" not supported. If the platform hasn't8888+ // set sharing CPUs, fallback to all CPUs share the `Policy`8989+ // for backward compatibility.9090+ opp::Table::sharing_cpus(dev, &mut mask).is_err()9191+ }9292+ Err(e) => return Err(e),9393+ };9494+9595+ // Initialize OPP tables for all policy cpus.9696+ //9797+ // For platforms not using "operating-points-v2" bindings, we do this9898+ // before updating policy cpus. Otherwise, we will end up creating9999+ // duplicate OPPs for the CPUs.100100+ //101101+ // OPPs might be populated at runtime, don't fail for error here unless102102+ // it is -EPROBE_DEFER.103103+ let mut opp_table = match opp::Table::from_of_cpumask(dev, &mut mask) {104104+ Ok(table) => table,105105+ Err(e) => {106106+ if e == EPROBE_DEFER {107107+ return Err(e);108108+ }109109+110110+ // The table is added dynamically ?111111+ opp::Table::from_dev(dev)?112112+ }113113+ };114114+115115+ // The OPP table must be initialized, statically or dynamically, by this point.116116+ opp_table.opp_count()?;117117+118118+ // Set sharing cpus for fallback scenario.119119+ if fallback {120120+ mask.setall();121121+ opp_table.set_sharing_cpus(&mut mask)?;122122+ }123123+124124+ let mut transition_latency = opp_table.max_transition_latency_ns() as u32;125125+ if transition_latency == 0 {126126+ transition_latency = cpufreq::ETERNAL_LATENCY_NS;127127+ }128128+129129+ policy130130+ .set_dvfs_possible_from_any_cpu(true)131131+ .set_suspend_freq(opp_table.suspend_freq())132132+ .set_transition_latency_ns(transition_latency);133133+134134+ let freq_table = opp_table.cpufreq_table()?;135135+ // SAFETY: The `freq_table` is not dropped while it is getting used by the C code.136136+ unsafe { policy.set_freq_table(&freq_table) };137137+138138+ // SAFETY: The returned `clk` is not dropped while it is getting used by the C code.139139+ let clk = unsafe { policy.set_clk(dev, None)? };140140+141141+ mask.copy(policy.cpus());142142+143143+ Ok(Arc::new(144144+ CPUFreqDTDevice {145145+ opp_table,146146+ freq_table,147147+ _mask: mask,148148+ _token: token,149149+ _clk: clk,150150+ },151151+ GFP_KERNEL,152152+ )?)153153+ }154154+155155+ fn exit(_policy: &mut cpufreq::Policy, _data: Option<Self::PData>) -> Result {156156+ Ok(())157157+ }158158+159159+ fn online(_policy: &mut cpufreq::Policy) -> Result {160160+ // We did light-weight tear down earlier, nothing to do here.161161+ Ok(())162162+ }163163+164164+ fn offline(_policy: &mut cpufreq::Policy) -> Result {165165+ // Preserve policy->data and don't free resources on light-weight166166+ // tear down.167167+ Ok(())168168+ }169169+170170+ fn suspend(policy: &mut cpufreq::Policy) -> Result {171171+ policy.generic_suspend()172172+ }173173+174174+ fn verify(data: &mut cpufreq::PolicyData) -> Result {175175+ data.generic_verify()176176+ }177177+178178+ fn target_index(policy: &mut cpufreq::Policy, index: cpufreq::TableIndex) -> Result {179179+ let Some(data) = policy.data::<Self::PData>() else {180180+ return Err(ENOENT);181181+ };182182+183183+ let freq = data.freq_table.freq(index)?;184184+ data.opp_table.set_rate(freq)185185+ }186186+187187+ fn get(policy: &mut cpufreq::Policy) -> Result<u32> {188188+ policy.generic_get()189189+ }190190+191191+ fn set_boost(_policy: &mut cpufreq::Policy, _state: i32) -> Result {192192+ Ok(())193193+ }194194+195195+ fn register_em(policy: &mut cpufreq::Policy) {196196+ policy.register_em_opp()197197+ }198198+}199199+200200+kernel::of_device_table!(201201+ OF_TABLE,202202+ MODULE_OF_TABLE,203203+ <CPUFreqDTDriver as platform::Driver>::IdInfo,204204+ [(of::DeviceId::new(c_str!("operating-points-v2")), ())]205205+);206206+207207+impl platform::Driver for CPUFreqDTDriver {208208+ type IdInfo = ();209209+ const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);210210+211211+ fn probe(212212+ pdev: &platform::Device<Core>,213213+ _id_info: Option<&Self::IdInfo>,214214+ ) -> Result<Pin<KBox<Self>>> {215215+ cpufreq::Registration::<CPUFreqDTDriver>::new_foreign_owned(pdev.as_ref())?;216216+ Ok(KBox::new(Self {}, GFP_KERNEL)?.into())217217+ }218218+}219219+220220+module_platform_driver! {221221+ type: CPUFreqDTDriver,222222+ name: "cpufreq-dt",223223+ author: "Viresh Kumar <viresh.kumar@linaro.org>",224224+ description: "Generic CPUFreq DT driver",225225+ license: "GPL v2",226226+}
+7-3
include/linux/cpufreq.h
···170170 struct notifier_block nb_max;171171};172172173173+DEFINE_GUARD(cpufreq_policy_write, struct cpufreq_policy *,174174+ down_write(&_T->rwsem), up_write(&_T->rwsem))175175+176176+DEFINE_GUARD(cpufreq_policy_read, struct cpufreq_policy *,177177+ down_read(&_T->rwsem), up_read(&_T->rwsem))178178+173179/*174180 * Used for passing new cpufreq policy data to the cpufreq driver's ->verify()175181 * callback for sanitization. That callback is only expected to modify the min···241235242236u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy);243237244244-struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu);245245-void cpufreq_cpu_release(struct cpufreq_policy *policy);246238int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);247239void refresh_frequency_limits(struct cpufreq_policy *policy);248240void cpufreq_update_policy(unsigned int cpu);···399395 unsigned int (*get)(unsigned int cpu);400396401397 /* Called to update policy limits on firmware notifications. */402402- void (*update_limits)(unsigned int cpu);398398+ void (*update_limits)(struct cpufreq_policy *policy);403399404400 /* optional */405401 int (*bios_limit)(int cpu, unsigned int *limit);
···11+// SPDX-License-Identifier: GPL-2.022+33+//! Clock abstractions.44+//!55+//! C header: [`include/linux/clk.h`](srctree/include/linux/clk.h)66+//!77+//! Reference: <https://docs.kernel.org/driver-api/clk.html>88+99+use crate::ffi::c_ulong;1010+1111+/// The frequency unit.1212+///1313+/// Represents a frequency in hertz, wrapping a [`c_ulong`] value.1414+///1515+/// ## Examples1616+///1717+/// ```1818+/// use kernel::clk::Hertz;1919+///2020+/// let hz = 1_000_000_000;2121+/// let rate = Hertz(hz);2222+///2323+/// assert_eq!(rate.as_hz(), hz);2424+/// assert_eq!(rate, Hertz(hz));2525+/// assert_eq!(rate, Hertz::from_khz(hz / 1_000));2626+/// assert_eq!(rate, Hertz::from_mhz(hz / 1_000_000));2727+/// assert_eq!(rate, Hertz::from_ghz(hz / 1_000_000_000));2828+/// ```2929+#[derive(Copy, Clone, PartialEq, Eq, Debug)]3030+pub struct Hertz(pub c_ulong);3131+3232+impl Hertz {3333+ /// Create a new instance from kilohertz (kHz)3434+ pub fn from_khz(khz: c_ulong) -> Self {3535+ Self(khz * 1_000)3636+ }3737+3838+ /// Create a new instance from megahertz (MHz)3939+ pub fn from_mhz(mhz: c_ulong) -> Self {4040+ Self(mhz * 1_000_000)4141+ }4242+4343+ /// Create a new instance from gigahertz (GHz)4444+ pub fn from_ghz(ghz: c_ulong) -> Self {4545+ Self(ghz * 1_000_000_000)4646+ }4747+4848+ /// Get the frequency in hertz4949+ pub fn as_hz(&self) -> c_ulong {5050+ self.05151+ }5252+5353+ /// Get the frequency in kilohertz5454+ pub fn as_khz(&self) -> c_ulong {5555+ self.0 / 1_0005656+ }5757+5858+ /// Get the frequency in megahertz5959+ pub fn as_mhz(&self) -> c_ulong {6060+ self.0 / 1_000_0006161+ }6262+6363+ /// Get the frequency in gigahertz6464+ pub fn as_ghz(&self) -> c_ulong {6565+ self.0 / 1_000_000_0006666+ }6767+}6868+6969+impl From<Hertz> for c_ulong {7070+ fn from(freq: Hertz) -> Self {7171+ freq.07272+ }7373+}7474+7575+#[cfg(CONFIG_COMMON_CLK)]7676+mod common_clk {7777+ use super::Hertz;7878+ use crate::{7979+ device::Device,8080+ error::{from_err_ptr, to_result, Result},8181+ prelude::*,8282+ };8383+8484+ use core::{ops::Deref, ptr};8585+8686+ /// A reference-counted clock.8787+ ///8888+ /// Rust abstraction for the C [`struct clk`].8989+ ///9090+ /// # Invariants9191+ ///9292+ /// A [`Clk`] instance holds either a pointer to a valid [`struct clk`] created by the C9393+ /// portion of the kernel or a NULL pointer.9494+ ///9595+ /// Instances of this type are reference-counted. Calling [`Clk::get`] ensures that the9696+ /// allocation remains valid for the lifetime of the [`Clk`].9797+ ///9898+ /// ## Examples9999+ ///100100+ /// The following example demonstrates how to obtain and configure a clock for a device.101101+ ///102102+ /// ```103103+ /// use kernel::c_str;104104+ /// use kernel::clk::{Clk, Hertz};105105+ /// use kernel::device::Device;106106+ /// use kernel::error::Result;107107+ ///108108+ /// fn configure_clk(dev: &Device) -> Result {109109+ /// let clk = Clk::get(dev, Some(c_str!("apb_clk")))?;110110+ ///111111+ /// clk.prepare_enable()?;112112+ ///113113+ /// let expected_rate = Hertz::from_ghz(1);114114+ ///115115+ /// if clk.rate() != expected_rate {116116+ /// clk.set_rate(expected_rate)?;117117+ /// }118118+ ///119119+ /// clk.disable_unprepare();120120+ /// Ok(())121121+ /// }122122+ /// ```123123+ ///124124+ /// [`struct clk`]: https://docs.kernel.org/driver-api/clk.html125125+ #[repr(transparent)]126126+ pub struct Clk(*mut bindings::clk);127127+128128+ impl Clk {129129+ /// Gets [`Clk`] corresponding to a [`Device`] and a connection id.130130+ ///131131+ /// Equivalent to the kernel's [`clk_get`] API.132132+ ///133133+ /// [`clk_get`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_get134134+ pub fn get(dev: &Device, name: Option<&CStr>) -> Result<Self> {135135+ let con_id = if let Some(name) = name {136136+ name.as_ptr()137137+ } else {138138+ ptr::null()139139+ };140140+141141+ // SAFETY: It is safe to call [`clk_get`] for a valid device pointer.142142+ //143143+ // INVARIANT: The reference-count is decremented when [`Clk`] goes out of scope.144144+ Ok(Self(from_err_ptr(unsafe {145145+ bindings::clk_get(dev.as_raw(), con_id)146146+ })?))147147+ }148148+149149+ /// Obtain the raw [`struct clk`] pointer.150150+ #[inline]151151+ pub fn as_raw(&self) -> *mut bindings::clk {152152+ self.0153153+ }154154+155155+ /// Enable the clock.156156+ ///157157+ /// Equivalent to the kernel's [`clk_enable`] API.158158+ ///159159+ /// [`clk_enable`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_enable160160+ #[inline]161161+ pub fn enable(&self) -> Result {162162+ // SAFETY: By the type invariants, self.as_raw() is a valid argument for163163+ // [`clk_enable`].164164+ to_result(unsafe { bindings::clk_enable(self.as_raw()) })165165+ }166166+167167+ /// Disable the clock.168168+ ///169169+ /// Equivalent to the kernel's [`clk_disable`] API.170170+ ///171171+ /// [`clk_disable`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_disable172172+ #[inline]173173+ pub fn disable(&self) {174174+ // SAFETY: By the type invariants, self.as_raw() is a valid argument for175175+ // [`clk_disable`].176176+ unsafe { bindings::clk_disable(self.as_raw()) };177177+ }178178+179179+ /// Prepare the clock.180180+ ///181181+ /// Equivalent to the kernel's [`clk_prepare`] API.182182+ ///183183+ /// [`clk_prepare`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_prepare184184+ #[inline]185185+ pub fn prepare(&self) -> Result {186186+ // SAFETY: By the type invariants, self.as_raw() is a valid argument for187187+ // [`clk_prepare`].188188+ to_result(unsafe { bindings::clk_prepare(self.as_raw()) })189189+ }190190+191191+ /// Unprepare the clock.192192+ ///193193+ /// Equivalent to the kernel's [`clk_unprepare`] API.194194+ ///195195+ /// [`clk_unprepare`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_unprepare196196+ #[inline]197197+ pub fn unprepare(&self) {198198+ // SAFETY: By the type invariants, self.as_raw() is a valid argument for199199+ // [`clk_unprepare`].200200+ unsafe { bindings::clk_unprepare(self.as_raw()) };201201+ }202202+203203+ /// Prepare and enable the clock.204204+ ///205205+ /// Equivalent to calling [`Clk::prepare`] followed by [`Clk::enable`].206206+ #[inline]207207+ pub fn prepare_enable(&self) -> Result {208208+ // SAFETY: By the type invariants, self.as_raw() is a valid argument for209209+ // [`clk_prepare_enable`].210210+ to_result(unsafe { bindings::clk_prepare_enable(self.as_raw()) })211211+ }212212+213213+ /// Disable and unprepare the clock.214214+ ///215215+ /// Equivalent to calling [`Clk::disable`] followed by [`Clk::unprepare`].216216+ #[inline]217217+ pub fn disable_unprepare(&self) {218218+ // SAFETY: By the type invariants, self.as_raw() is a valid argument for219219+ // [`clk_disable_unprepare`].220220+ unsafe { bindings::clk_disable_unprepare(self.as_raw()) };221221+ }222222+223223+ /// Get clock's rate.224224+ ///225225+ /// Equivalent to the kernel's [`clk_get_rate`] API.226226+ ///227227+ /// [`clk_get_rate`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_get_rate228228+ #[inline]229229+ pub fn rate(&self) -> Hertz {230230+ // SAFETY: By the type invariants, self.as_raw() is a valid argument for231231+ // [`clk_get_rate`].232232+ Hertz(unsafe { bindings::clk_get_rate(self.as_raw()) })233233+ }234234+235235+ /// Set clock's rate.236236+ ///237237+ /// Equivalent to the kernel's [`clk_set_rate`] API.238238+ ///239239+ /// [`clk_set_rate`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_set_rate240240+ #[inline]241241+ pub fn set_rate(&self, rate: Hertz) -> Result {242242+ // SAFETY: By the type invariants, self.as_raw() is a valid argument for243243+ // [`clk_set_rate`].244244+ to_result(unsafe { bindings::clk_set_rate(self.as_raw(), rate.as_hz()) })245245+ }246246+ }247247+248248+ impl Drop for Clk {249249+ fn drop(&mut self) {250250+ // SAFETY: By the type invariants, self.as_raw() is a valid argument for [`clk_put`].251251+ unsafe { bindings::clk_put(self.as_raw()) };252252+ }253253+ }254254+255255+ /// A reference-counted optional clock.256256+ ///257257+ /// A lightweight wrapper around an optional [`Clk`]. An [`OptionalClk`] represents a [`Clk`]258258+ /// that a driver can function without but may improve performance or enable additional259259+ /// features when available.260260+ ///261261+ /// # Invariants262262+ ///263263+ /// An [`OptionalClk`] instance encapsulates a [`Clk`] with either a valid [`struct clk`] or264264+ /// `NULL` pointer.265265+ ///266266+ /// Instances of this type are reference-counted. Calling [`OptionalClk::get`] ensures that the267267+ /// allocation remains valid for the lifetime of the [`OptionalClk`].268268+ ///269269+ /// ## Examples270270+ ///271271+ /// The following example demonstrates how to obtain and configure an optional clock for a272272+ /// device. The code functions correctly whether or not the clock is available.273273+ ///274274+ /// ```275275+ /// use kernel::c_str;276276+ /// use kernel::clk::{OptionalClk, Hertz};277277+ /// use kernel::device::Device;278278+ /// use kernel::error::Result;279279+ ///280280+ /// fn configure_clk(dev: &Device) -> Result {281281+ /// let clk = OptionalClk::get(dev, Some(c_str!("apb_clk")))?;282282+ ///283283+ /// clk.prepare_enable()?;284284+ ///285285+ /// let expected_rate = Hertz::from_ghz(1);286286+ ///287287+ /// if clk.rate() != expected_rate {288288+ /// clk.set_rate(expected_rate)?;289289+ /// }290290+ ///291291+ /// clk.disable_unprepare();292292+ /// Ok(())293293+ /// }294294+ /// ```295295+ ///296296+ /// [`struct clk`]: https://docs.kernel.org/driver-api/clk.html297297+ pub struct OptionalClk(Clk);298298+299299+ impl OptionalClk {300300+ /// Gets [`OptionalClk`] corresponding to a [`Device`] and a connection id.301301+ ///302302+ /// Equivalent to the kernel's [`clk_get_optional`] API.303303+ ///304304+ /// [`clk_get_optional`]:305305+ /// https://docs.kernel.org/core-api/kernel-api.html#c.clk_get_optional306306+ pub fn get(dev: &Device, name: Option<&CStr>) -> Result<Self> {307307+ let con_id = if let Some(name) = name {308308+ name.as_ptr()309309+ } else {310310+ ptr::null()311311+ };312312+313313+ // SAFETY: It is safe to call [`clk_get_optional`] for a valid device pointer.314314+ //315315+ // INVARIANT: The reference-count is decremented when [`OptionalClk`] goes out of316316+ // scope.317317+ Ok(Self(Clk(from_err_ptr(unsafe {318318+ bindings::clk_get_optional(dev.as_raw(), con_id)319319+ })?)))320320+ }321321+ }322322+323323+ // Make [`OptionalClk`] behave like [`Clk`].324324+ impl Deref for OptionalClk {325325+ type Target = Clk;326326+327327+ fn deref(&self) -> &Clk {328328+ &self.0329329+ }330330+ }331331+}332332+333333+#[cfg(CONFIG_COMMON_CLK)]334334+pub use common_clk::*;
+30
rust/kernel/cpu.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+//! Generic CPU definitions.44+//!55+//! C header: [`include/linux/cpu.h`](srctree/include/linux/cpu.h)66+77+use crate::{bindings, device::Device, error::Result, prelude::ENODEV};88+99+/// Creates a new instance of CPU's device.1010+///1111+/// # Safety1212+///1313+/// Reference counting is not implemented for the CPU device in the C code. When a CPU is1414+/// hot-unplugged, the corresponding CPU device is unregistered, but its associated memory1515+/// is not freed.1616+///1717+/// Callers must ensure that the CPU device is not used after it has been unregistered.1818+/// This can be achieved, for example, by registering a CPU hotplug notifier and removing1919+/// any references to the CPU device within the notifier's callback.2020+pub unsafe fn from_cpu(cpu: u32) -> Result<&'static Device> {2121+ // SAFETY: It is safe to call `get_cpu_device()` for any CPU.2222+ let ptr = unsafe { bindings::get_cpu_device(cpu) };2323+ if ptr.is_null() {2424+ return Err(ENODEV);2525+ }2626+2727+ // SAFETY: The pointer returned by `get_cpu_device()`, if not `NULL`, is a valid pointer to2828+ // a `struct device` and is never freed by the C code.2929+ Ok(unsafe { Device::as_ref(ptr) })3030+}
+1321
rust/kernel/cpufreq.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+//! CPU frequency scaling.44+//!55+//! This module provides rust abstractions for interacting with the cpufreq subsystem.66+//!77+//! C header: [`include/linux/cpufreq.h`](srctree/include/linux/cpufreq.h)88+//!99+//! Reference: <https://docs.kernel.org/admin-guide/pm/cpufreq.html>1010+1111+use crate::{1212+ clk::Hertz,1313+ cpumask,1414+ device::{Bound, Device},1515+ devres::Devres,1616+ error::{code::*, from_err_ptr, from_result, to_result, Result, VTABLE_DEFAULT_ERROR},1717+ ffi::{c_char, c_ulong},1818+ prelude::*,1919+ types::ForeignOwnable,2020+ types::Opaque,2121+};2222+2323+#[cfg(CONFIG_COMMON_CLK)]2424+use crate::clk::Clk;2525+2626+use core::{2727+ cell::UnsafeCell,2828+ marker::PhantomData,2929+ mem::MaybeUninit,3030+ ops::{Deref, DerefMut},3131+ pin::Pin,3232+ ptr,3333+};3434+3535+use macros::vtable;3636+3737+/// Maximum length of CPU frequency driver's name.3838+const CPUFREQ_NAME_LEN: usize = bindings::CPUFREQ_NAME_LEN as usize;3939+4040+/// Default transition latency value in nanoseconds.4141+pub const ETERNAL_LATENCY_NS: u32 = bindings::CPUFREQ_ETERNAL as u32;4242+4343+/// CPU frequency driver flags.4444+pub mod flags {4545+ /// Driver needs to update internal limits even if frequency remains unchanged.4646+ pub const NEED_UPDATE_LIMITS: u16 = 1 << 0;4747+4848+ /// Platform where constants like `loops_per_jiffy` are unaffected by frequency changes.4949+ pub const CONST_LOOPS: u16 = 1 << 1;5050+5151+ /// Register driver as a thermal cooling device automatically.5252+ pub const IS_COOLING_DEV: u16 = 1 << 2;5353+5454+ /// Supports multiple clock domains with per-policy governors in `cpu/cpuN/cpufreq/`.5555+ pub const HAVE_GOVERNOR_PER_POLICY: u16 = 1 << 3;5656+5757+ /// Allows post-change notifications outside of the `target()` routine.5858+ pub const ASYNC_NOTIFICATION: u16 = 1 << 4;5959+6060+ /// Ensure CPU starts at a valid frequency from the driver's freq-table.6161+ pub const NEED_INITIAL_FREQ_CHECK: u16 = 1 << 5;6262+6363+ /// Disallow governors with `dynamic_switching` capability.6464+ pub const NO_AUTO_DYNAMIC_SWITCHING: u16 = 1 << 6;6565+}6666+6767+/// Relations from the C code.6868+const CPUFREQ_RELATION_L: u32 = 0;6969+const CPUFREQ_RELATION_H: u32 = 1;7070+const CPUFREQ_RELATION_C: u32 = 2;7171+7272+/// Can be used with any of the above values.7373+const CPUFREQ_RELATION_E: u32 = 1 << 2;7474+7575+/// CPU frequency selection relations.7676+///7777+/// CPU frequency selection relations, each optionally marked as "efficient".7878+#[derive(Copy, Clone, Debug, Eq, PartialEq)]7979+pub enum Relation {8080+ /// Select the lowest frequency at or above target.8181+ Low(bool),8282+ /// Select the highest frequency below or at target.8383+ High(bool),8484+ /// Select the closest frequency to the target.8585+ Close(bool),8686+}8787+8888+impl Relation {8989+ // Construct from a C-compatible `u32` value.9090+ fn new(val: u32) -> Result<Self> {9191+ let efficient = val & CPUFREQ_RELATION_E != 0;9292+9393+ Ok(match val & !CPUFREQ_RELATION_E {9494+ CPUFREQ_RELATION_L => Self::Low(efficient),9595+ CPUFREQ_RELATION_H => Self::High(efficient),9696+ CPUFREQ_RELATION_C => Self::Close(efficient),9797+ _ => return Err(EINVAL),9898+ })9999+ }100100+}101101+102102+impl From<Relation> for u32 {103103+ // Convert to a C-compatible `u32` value.104104+ fn from(rel: Relation) -> Self {105105+ let (mut val, efficient) = match rel {106106+ Relation::Low(e) => (CPUFREQ_RELATION_L, e),107107+ Relation::High(e) => (CPUFREQ_RELATION_H, e),108108+ Relation::Close(e) => (CPUFREQ_RELATION_C, e),109109+ };110110+111111+ if efficient {112112+ val |= CPUFREQ_RELATION_E;113113+ }114114+115115+ val116116+ }117117+}118118+119119+/// Policy data.120120+///121121+/// Rust abstraction for the C `struct cpufreq_policy_data`.122122+///123123+/// # Invariants124124+///125125+/// A [`PolicyData`] instance always corresponds to a valid C `struct cpufreq_policy_data`.126126+///127127+/// The callers must ensure that the `struct cpufreq_policy_data` is valid for access and remains128128+/// valid for the lifetime of the returned reference.129129+#[repr(transparent)]130130+pub struct PolicyData(Opaque<bindings::cpufreq_policy_data>);131131+132132+impl PolicyData {133133+ /// Creates a mutable reference to an existing `struct cpufreq_policy_data` pointer.134134+ ///135135+ /// # Safety136136+ ///137137+ /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime138138+ /// of the returned reference.139139+ #[inline]140140+ pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy_data) -> &'a mut Self {141141+ // SAFETY: Guaranteed by the safety requirements of the function.142142+ //143143+ // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the144144+ // lifetime of the returned reference.145145+ unsafe { &mut *ptr.cast() }146146+ }147147+148148+ /// Returns a raw pointer to the underlying C `cpufreq_policy_data`.149149+ #[inline]150150+ pub fn as_raw(&self) -> *mut bindings::cpufreq_policy_data {151151+ let this: *const Self = self;152152+ this.cast_mut().cast()153153+ }154154+155155+ /// Wrapper for `cpufreq_generic_frequency_table_verify`.156156+ #[inline]157157+ pub fn generic_verify(&self) -> Result {158158+ // SAFETY: By the type invariant, the pointer stored in `self` is valid.159159+ to_result(unsafe { bindings::cpufreq_generic_frequency_table_verify(self.as_raw()) })160160+ }161161+}162162+163163+/// The frequency table index.164164+///165165+/// Represents index with a frequency table.166166+///167167+/// # Invariants168168+///169169+/// The index must correspond to a valid entry in the [`Table`] it is used for.170170+#[derive(Copy, Clone, PartialEq, Eq, Debug)]171171+pub struct TableIndex(usize);172172+173173+impl TableIndex {174174+ /// Creates an instance of [`TableIndex`].175175+ ///176176+ /// # Safety177177+ ///178178+ /// The caller must ensure that `index` correspond to a valid entry in the [`Table`] it is used179179+ /// for.180180+ pub unsafe fn new(index: usize) -> Self {181181+ // INVARIANT: The caller ensures that `index` correspond to a valid entry in the [`Table`].182182+ Self(index)183183+ }184184+}185185+186186+impl From<TableIndex> for usize {187187+ #[inline]188188+ fn from(index: TableIndex) -> Self {189189+ index.0190190+ }191191+}192192+193193+/// CPU frequency table.194194+///195195+/// Rust abstraction for the C `struct cpufreq_frequency_table`.196196+///197197+/// # Invariants198198+///199199+/// A [`Table`] instance always corresponds to a valid C `struct cpufreq_frequency_table`.200200+///201201+/// The callers must ensure that the `struct cpufreq_frequency_table` is valid for access and202202+/// remains valid for the lifetime of the returned reference.203203+///204204+/// ## Examples205205+///206206+/// The following example demonstrates how to read a frequency value from [`Table`].207207+///208208+/// ```209209+/// use kernel::cpufreq::{Policy, TableIndex};210210+///211211+/// fn show_freq(policy: &Policy) -> Result {212212+/// let table = policy.freq_table()?;213213+///214214+/// // SAFETY: Index is a valid entry in the table.215215+/// let index = unsafe { TableIndex::new(0) };216216+///217217+/// pr_info!("The frequency at index 0 is: {:?}\n", table.freq(index)?);218218+/// pr_info!("The flags at index 0 is: {}\n", table.flags(index));219219+/// pr_info!("The data at index 0 is: {}\n", table.data(index));220220+/// Ok(())221221+/// }222222+/// ```223223+#[repr(transparent)]224224+pub struct Table(Opaque<bindings::cpufreq_frequency_table>);225225+226226+impl Table {227227+ /// Creates a reference to an existing C `struct cpufreq_frequency_table` pointer.228228+ ///229229+ /// # Safety230230+ ///231231+ /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime232232+ /// of the returned reference.233233+ #[inline]234234+ pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_frequency_table) -> &'a Self {235235+ // SAFETY: Guaranteed by the safety requirements of the function.236236+ //237237+ // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the238238+ // lifetime of the returned reference.239239+ unsafe { &*ptr.cast() }240240+ }241241+242242+ /// Returns the raw mutable pointer to the C `struct cpufreq_frequency_table`.243243+ #[inline]244244+ pub fn as_raw(&self) -> *mut bindings::cpufreq_frequency_table {245245+ let this: *const Self = self;246246+ this.cast_mut().cast()247247+ }248248+249249+ /// Returns frequency at `index` in the [`Table`].250250+ #[inline]251251+ pub fn freq(&self, index: TableIndex) -> Result<Hertz> {252252+ // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is253253+ // guaranteed to be valid by its safety requirements.254254+ Ok(Hertz::from_khz(unsafe {255255+ (*self.as_raw().add(index.into())).frequency.try_into()?256256+ }))257257+ }258258+259259+ /// Returns flags at `index` in the [`Table`].260260+ #[inline]261261+ pub fn flags(&self, index: TableIndex) -> u32 {262262+ // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is263263+ // guaranteed to be valid by its safety requirements.264264+ unsafe { (*self.as_raw().add(index.into())).flags }265265+ }266266+267267+ /// Returns data at `index` in the [`Table`].268268+ #[inline]269269+ pub fn data(&self, index: TableIndex) -> u32 {270270+ // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is271271+ // guaranteed to be valid by its safety requirements.272272+ unsafe { (*self.as_raw().add(index.into())).driver_data }273273+ }274274+}275275+276276+/// CPU frequency table owned and pinned in memory, created from a [`TableBuilder`].277277+pub struct TableBox {278278+ entries: Pin<KVec<bindings::cpufreq_frequency_table>>,279279+}280280+281281+impl TableBox {282282+ /// Constructs a new [`TableBox`] from a [`KVec`] of entries.283283+ ///284284+ /// # Errors285285+ ///286286+ /// Returns `EINVAL` if the entries list is empty.287287+ #[inline]288288+ fn new(entries: KVec<bindings::cpufreq_frequency_table>) -> Result<Self> {289289+ if entries.is_empty() {290290+ return Err(EINVAL);291291+ }292292+293293+ Ok(Self {294294+ // Pin the entries to memory, since we are passing its pointer to the C code.295295+ entries: Pin::new(entries),296296+ })297297+ }298298+299299+ /// Returns a raw pointer to the underlying C `cpufreq_frequency_table`.300300+ #[inline]301301+ fn as_raw(&self) -> *const bindings::cpufreq_frequency_table {302302+ // The pointer is valid until the table gets dropped.303303+ self.entries.as_ptr()304304+ }305305+}306306+307307+impl Deref for TableBox {308308+ type Target = Table;309309+310310+ fn deref(&self) -> &Self::Target {311311+ // SAFETY: The caller owns TableBox, it is safe to deref.312312+ unsafe { Self::Target::from_raw(self.as_raw()) }313313+ }314314+}315315+316316+/// CPU frequency table builder.317317+///318318+/// This is used by the CPU frequency drivers to build a frequency table dynamically.319319+///320320+/// ## Examples321321+///322322+/// The following example demonstrates how to create a CPU frequency table.323323+///324324+/// ```325325+/// use kernel::cpufreq::{TableBuilder, TableIndex};326326+/// use kernel::clk::Hertz;327327+///328328+/// let mut builder = TableBuilder::new();329329+///330330+/// // Adds few entries to the table.331331+/// builder.add(Hertz::from_mhz(700), 0, 1).unwrap();332332+/// builder.add(Hertz::from_mhz(800), 2, 3).unwrap();333333+/// builder.add(Hertz::from_mhz(900), 4, 5).unwrap();334334+/// builder.add(Hertz::from_ghz(1), 6, 7).unwrap();335335+///336336+/// let table = builder.to_table().unwrap();337337+///338338+/// // SAFETY: Index values correspond to valid entries in the table.339339+/// let (index0, index2) = unsafe { (TableIndex::new(0), TableIndex::new(2)) };340340+///341341+/// assert_eq!(table.freq(index0), Ok(Hertz::from_mhz(700)));342342+/// assert_eq!(table.flags(index0), 0);343343+/// assert_eq!(table.data(index0), 1);344344+///345345+/// assert_eq!(table.freq(index2), Ok(Hertz::from_mhz(900)));346346+/// assert_eq!(table.flags(index2), 4);347347+/// assert_eq!(table.data(index2), 5);348348+/// ```349349+#[derive(Default)]350350+#[repr(transparent)]351351+pub struct TableBuilder {352352+ entries: KVec<bindings::cpufreq_frequency_table>,353353+}354354+355355+impl TableBuilder {356356+ /// Creates a new instance of [`TableBuilder`].357357+ #[inline]358358+ pub fn new() -> Self {359359+ Self {360360+ entries: KVec::new(),361361+ }362362+ }363363+364364+ /// Adds a new entry to the table.365365+ pub fn add(&mut self, freq: Hertz, flags: u32, driver_data: u32) -> Result {366366+ // Adds the new entry at the end of the vector.367367+ Ok(self.entries.push(368368+ bindings::cpufreq_frequency_table {369369+ flags,370370+ driver_data,371371+ frequency: freq.as_khz() as u32,372372+ },373373+ GFP_KERNEL,374374+ )?)375375+ }376376+377377+ /// Consumes the [`TableBuilder`] and returns [`TableBox`].378378+ pub fn to_table(mut self) -> Result<TableBox> {379379+ // Add last entry to the table.380380+ self.add(Hertz(c_ulong::MAX), 0, 0)?;381381+382382+ TableBox::new(self.entries)383383+ }384384+}385385+386386+/// CPU frequency policy.387387+///388388+/// Rust abstraction for the C `struct cpufreq_policy`.389389+///390390+/// # Invariants391391+///392392+/// A [`Policy`] instance always corresponds to a valid C `struct cpufreq_policy`.393393+///394394+/// The callers must ensure that the `struct cpufreq_policy` is valid for access and remains valid395395+/// for the lifetime of the returned reference.396396+///397397+/// ## Examples398398+///399399+/// The following example demonstrates how to create a CPU frequency table.400400+///401401+/// ```402402+/// use kernel::cpufreq::{ETERNAL_LATENCY_NS, Policy};403403+///404404+/// fn update_policy(policy: &mut Policy) {405405+/// policy406406+/// .set_dvfs_possible_from_any_cpu(true)407407+/// .set_fast_switch_possible(true)408408+/// .set_transition_latency_ns(ETERNAL_LATENCY_NS);409409+///410410+/// pr_info!("The policy details are: {:?}\n", (policy.cpu(), policy.cur()));411411+/// }412412+/// ```413413+#[repr(transparent)]414414+pub struct Policy(Opaque<bindings::cpufreq_policy>);415415+416416+impl Policy {417417+ /// Creates a reference to an existing `struct cpufreq_policy` pointer.418418+ ///419419+ /// # Safety420420+ ///421421+ /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime422422+ /// of the returned reference.423423+ #[inline]424424+ pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_policy) -> &'a Self {425425+ // SAFETY: Guaranteed by the safety requirements of the function.426426+ //427427+ // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the428428+ // lifetime of the returned reference.429429+ unsafe { &*ptr.cast() }430430+ }431431+432432+ /// Creates a mutable reference to an existing `struct cpufreq_policy` pointer.433433+ ///434434+ /// # Safety435435+ ///436436+ /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime437437+ /// of the returned reference.438438+ #[inline]439439+ pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy) -> &'a mut Self {440440+ // SAFETY: Guaranteed by the safety requirements of the function.441441+ //442442+ // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the443443+ // lifetime of the returned reference.444444+ unsafe { &mut *ptr.cast() }445445+ }446446+447447+ /// Returns a raw mutable pointer to the C `struct cpufreq_policy`.448448+ #[inline]449449+ fn as_raw(&self) -> *mut bindings::cpufreq_policy {450450+ let this: *const Self = self;451451+ this.cast_mut().cast()452452+ }453453+454454+ #[inline]455455+ fn as_ref(&self) -> &bindings::cpufreq_policy {456456+ // SAFETY: By the type invariant, the pointer stored in `self` is valid.457457+ unsafe { &*self.as_raw() }458458+ }459459+460460+ #[inline]461461+ fn as_mut_ref(&mut self) -> &mut bindings::cpufreq_policy {462462+ // SAFETY: By the type invariant, the pointer stored in `self` is valid.463463+ unsafe { &mut *self.as_raw() }464464+ }465465+466466+ /// Returns the primary CPU for the [`Policy`].467467+ #[inline]468468+ pub fn cpu(&self) -> u32 {469469+ self.as_ref().cpu470470+ }471471+472472+ /// Returns the minimum frequency for the [`Policy`].473473+ #[inline]474474+ pub fn min(&self) -> Hertz {475475+ Hertz::from_khz(self.as_ref().min as usize)476476+ }477477+478478+ /// Set the minimum frequency for the [`Policy`].479479+ #[inline]480480+ pub fn set_min(&mut self, min: Hertz) -> &mut Self {481481+ self.as_mut_ref().min = min.as_khz() as u32;482482+ self483483+ }484484+485485+ /// Returns the maximum frequency for the [`Policy`].486486+ #[inline]487487+ pub fn max(&self) -> Hertz {488488+ Hertz::from_khz(self.as_ref().max as usize)489489+ }490490+491491+ /// Set the maximum frequency for the [`Policy`].492492+ #[inline]493493+ pub fn set_max(&mut self, max: Hertz) -> &mut Self {494494+ self.as_mut_ref().max = max.as_khz() as u32;495495+ self496496+ }497497+498498+ /// Returns the current frequency for the [`Policy`].499499+ #[inline]500500+ pub fn cur(&self) -> Hertz {501501+ Hertz::from_khz(self.as_ref().cur as usize)502502+ }503503+504504+ /// Returns the suspend frequency for the [`Policy`].505505+ #[inline]506506+ pub fn suspend_freq(&self) -> Hertz {507507+ Hertz::from_khz(self.as_ref().suspend_freq as usize)508508+ }509509+510510+ /// Sets the suspend frequency for the [`Policy`].511511+ #[inline]512512+ pub fn set_suspend_freq(&mut self, freq: Hertz) -> &mut Self {513513+ self.as_mut_ref().suspend_freq = freq.as_khz() as u32;514514+ self515515+ }516516+517517+ /// Provides a wrapper to the generic suspend routine.518518+ #[inline]519519+ pub fn generic_suspend(&mut self) -> Result {520520+ // SAFETY: By the type invariant, the pointer stored in `self` is valid.521521+ to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_mut_ref()) })522522+ }523523+524524+ /// Provides a wrapper to the generic get routine.525525+ #[inline]526526+ pub fn generic_get(&self) -> Result<u32> {527527+ // SAFETY: By the type invariant, the pointer stored in `self` is valid.528528+ Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) })529529+ }530530+531531+ /// Provides a wrapper to the register with energy model using the OPP core.532532+ #[cfg(CONFIG_PM_OPP)]533533+ #[inline]534534+ pub fn register_em_opp(&mut self) {535535+ // SAFETY: By the type invariant, the pointer stored in `self` is valid.536536+ unsafe { bindings::cpufreq_register_em_with_opp(self.as_mut_ref()) };537537+ }538538+539539+ /// Gets [`cpumask::Cpumask`] for a cpufreq [`Policy`].540540+ #[inline]541541+ pub fn cpus(&mut self) -> &mut cpumask::Cpumask {542542+ // SAFETY: The pointer to `cpus` is valid for writing and remains valid for the lifetime of543543+ // the returned reference.544544+ unsafe { cpumask::CpumaskVar::as_mut_ref(&mut self.as_mut_ref().cpus) }545545+ }546546+547547+ /// Sets clock for the [`Policy`].548548+ ///549549+ /// # Safety550550+ ///551551+ /// The caller must guarantee that the returned [`Clk`] is not dropped while it is getting used552552+ /// by the C code.553553+ #[cfg(CONFIG_COMMON_CLK)]554554+ pub unsafe fn set_clk(&mut self, dev: &Device, name: Option<&CStr>) -> Result<Clk> {555555+ let clk = Clk::get(dev, name)?;556556+ self.as_mut_ref().clk = clk.as_raw();557557+ Ok(clk)558558+ }559559+560560+ /// Allows / disallows frequency switching code to run on any CPU.561561+ #[inline]562562+ pub fn set_dvfs_possible_from_any_cpu(&mut self, val: bool) -> &mut Self {563563+ self.as_mut_ref().dvfs_possible_from_any_cpu = val;564564+ self565565+ }566566+567567+ /// Returns if fast switching of frequencies is possible or not.568568+ #[inline]569569+ pub fn fast_switch_possible(&self) -> bool {570570+ self.as_ref().fast_switch_possible571571+ }572572+573573+ /// Enables / disables fast frequency switching.574574+ #[inline]575575+ pub fn set_fast_switch_possible(&mut self, val: bool) -> &mut Self {576576+ self.as_mut_ref().fast_switch_possible = val;577577+ self578578+ }579579+580580+ /// Sets transition latency (in nanoseconds) for the [`Policy`].581581+ #[inline]582582+ pub fn set_transition_latency_ns(&mut self, latency_ns: u32) -> &mut Self {583583+ self.as_mut_ref().cpuinfo.transition_latency = latency_ns;584584+ self585585+ }586586+587587+ /// Sets cpuinfo `min_freq`.588588+ #[inline]589589+ pub fn set_cpuinfo_min_freq(&mut self, min_freq: Hertz) -> &mut Self {590590+ self.as_mut_ref().cpuinfo.min_freq = min_freq.as_khz() as u32;591591+ self592592+ }593593+594594+ /// Sets cpuinfo `max_freq`.595595+ #[inline]596596+ pub fn set_cpuinfo_max_freq(&mut self, max_freq: Hertz) -> &mut Self {597597+ self.as_mut_ref().cpuinfo.max_freq = max_freq.as_khz() as u32;598598+ self599599+ }600600+601601+ /// Set `transition_delay_us`, i.e. the minimum time between successive frequency change602602+ /// requests.603603+ #[inline]604604+ pub fn set_transition_delay_us(&mut self, transition_delay_us: u32) -> &mut Self {605605+ self.as_mut_ref().transition_delay_us = transition_delay_us;606606+ self607607+ }608608+609609+ /// Returns reference to the CPU frequency [`Table`] for the [`Policy`].610610+ pub fn freq_table(&self) -> Result<&Table> {611611+ if self.as_ref().freq_table.is_null() {612612+ return Err(EINVAL);613613+ }614614+615615+ // SAFETY: The `freq_table` is guaranteed to be valid for reading and remains valid for the616616+ // lifetime of the returned reference.617617+ Ok(unsafe { Table::from_raw(self.as_ref().freq_table) })618618+ }619619+620620+ /// Sets the CPU frequency [`Table`] for the [`Policy`].621621+ ///622622+ /// # Safety623623+ ///624624+ /// The caller must guarantee that the [`Table`] is not dropped while it is getting used by the625625+ /// C code.626626+ #[inline]627627+ pub unsafe fn set_freq_table(&mut self, table: &Table) -> &mut Self {628628+ self.as_mut_ref().freq_table = table.as_raw();629629+ self630630+ }631631+632632+ /// Returns the [`Policy`]'s private data.633633+ pub fn data<T: ForeignOwnable>(&mut self) -> Option<<T>::Borrowed<'_>> {634634+ if self.as_ref().driver_data.is_null() {635635+ None636636+ } else {637637+ // SAFETY: The data is earlier set from [`set_data`].638638+ Some(unsafe { T::borrow(self.as_ref().driver_data) })639639+ }640640+ }641641+642642+ /// Sets the private data of the [`Policy`] using a foreign-ownable wrapper.643643+ ///644644+ /// # Errors645645+ ///646646+ /// Returns `EBUSY` if private data is already set.647647+ fn set_data<T: ForeignOwnable>(&mut self, data: T) -> Result {648648+ if self.as_ref().driver_data.is_null() {649649+ // Transfer the ownership of the data to the foreign interface.650650+ self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data) as _;651651+ Ok(())652652+ } else {653653+ Err(EBUSY)654654+ }655655+ }656656+657657+ /// Clears and returns ownership of the private data.658658+ fn clear_data<T: ForeignOwnable>(&mut self) -> Option<T> {659659+ if self.as_ref().driver_data.is_null() {660660+ None661661+ } else {662662+ let data = Some(663663+ // SAFETY: The data is earlier set by us from [`set_data`]. It is safe to take664664+ // back the ownership of the data from the foreign interface.665665+ unsafe { <T as ForeignOwnable>::from_foreign(self.as_ref().driver_data) },666666+ );667667+ self.as_mut_ref().driver_data = ptr::null_mut();668668+ data669669+ }670670+ }671671+}672672+673673+/// CPU frequency policy created from a CPU number.674674+///675675+/// This struct represents the CPU frequency policy obtained for a specific CPU, providing safe676676+/// access to the underlying `cpufreq_policy` and ensuring proper cleanup when the `PolicyCpu` is677677+/// dropped.678678+struct PolicyCpu<'a>(&'a mut Policy);679679+680680+impl<'a> PolicyCpu<'a> {681681+ fn from_cpu(cpu: u32) -> Result<Self> {682682+ // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU.683683+ let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) })?;684684+685685+ Ok(Self(686686+ // SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of687687+ // the returned reference.688688+ unsafe { Policy::from_raw_mut(ptr) },689689+ ))690690+ }691691+}692692+693693+impl<'a> Deref for PolicyCpu<'a> {694694+ type Target = Policy;695695+696696+ fn deref(&self) -> &Self::Target {697697+ self.0698698+ }699699+}700700+701701+impl<'a> DerefMut for PolicyCpu<'a> {702702+ fn deref_mut(&mut self) -> &mut Policy {703703+ self.0704704+ }705705+}706706+707707+impl<'a> Drop for PolicyCpu<'a> {708708+ fn drop(&mut self) {709709+ // SAFETY: The underlying pointer is guaranteed to be valid for the lifetime of `self`.710710+ unsafe { bindings::cpufreq_cpu_put(self.0.as_raw()) };711711+ }712712+}713713+714714+/// CPU frequency driver.715715+///716716+/// Implement this trait to provide a CPU frequency driver and its callbacks.717717+///718718+/// Reference: <https://docs.kernel.org/cpu-freq/cpu-drivers.html>719719+#[vtable]720720+pub trait Driver {721721+ /// Driver's name.722722+ const NAME: &'static CStr;723723+724724+ /// Driver's flags.725725+ const FLAGS: u16;726726+727727+ /// Boost support.728728+ const BOOST_ENABLED: bool;729729+730730+ /// Policy specific data.731731+ ///732732+ /// Require that `PData` implements `ForeignOwnable`. We guarantee to never move the underlying733733+ /// wrapped data structure.734734+ type PData: ForeignOwnable;735735+736736+ /// Driver's `init` callback.737737+ fn init(policy: &mut Policy) -> Result<Self::PData>;738738+739739+ /// Driver's `exit` callback.740740+ fn exit(_policy: &mut Policy, _data: Option<Self::PData>) -> Result {741741+ build_error!(VTABLE_DEFAULT_ERROR)742742+ }743743+744744+ /// Driver's `online` callback.745745+ fn online(_policy: &mut Policy) -> Result {746746+ build_error!(VTABLE_DEFAULT_ERROR)747747+ }748748+749749+ /// Driver's `offline` callback.750750+ fn offline(_policy: &mut Policy) -> Result {751751+ build_error!(VTABLE_DEFAULT_ERROR)752752+ }753753+754754+ /// Driver's `suspend` callback.755755+ fn suspend(_policy: &mut Policy) -> Result {756756+ build_error!(VTABLE_DEFAULT_ERROR)757757+ }758758+759759+ /// Driver's `resume` callback.760760+ fn resume(_policy: &mut Policy) -> Result {761761+ build_error!(VTABLE_DEFAULT_ERROR)762762+ }763763+764764+ /// Driver's `ready` callback.765765+ fn ready(_policy: &mut Policy) {766766+ build_error!(VTABLE_DEFAULT_ERROR)767767+ }768768+769769+ /// Driver's `verify` callback.770770+ fn verify(data: &mut PolicyData) -> Result;771771+772772+ /// Driver's `setpolicy` callback.773773+ fn setpolicy(_policy: &mut Policy) -> Result {774774+ build_error!(VTABLE_DEFAULT_ERROR)775775+ }776776+777777+ /// Driver's `target` callback.778778+ fn target(_policy: &mut Policy, _target_freq: u32, _relation: Relation) -> Result {779779+ build_error!(VTABLE_DEFAULT_ERROR)780780+ }781781+782782+ /// Driver's `target_index` callback.783783+ fn target_index(_policy: &mut Policy, _index: TableIndex) -> Result {784784+ build_error!(VTABLE_DEFAULT_ERROR)785785+ }786786+787787+ /// Driver's `fast_switch` callback.788788+ fn fast_switch(_policy: &mut Policy, _target_freq: u32) -> u32 {789789+ build_error!(VTABLE_DEFAULT_ERROR)790790+ }791791+792792+ /// Driver's `adjust_perf` callback.793793+ fn adjust_perf(_policy: &mut Policy, _min_perf: usize, _target_perf: usize, _capacity: usize) {794794+ build_error!(VTABLE_DEFAULT_ERROR)795795+ }796796+797797+ /// Driver's `get_intermediate` callback.798798+ fn get_intermediate(_policy: &mut Policy, _index: TableIndex) -> u32 {799799+ build_error!(VTABLE_DEFAULT_ERROR)800800+ }801801+802802+ /// Driver's `target_intermediate` callback.803803+ fn target_intermediate(_policy: &mut Policy, _index: TableIndex) -> Result {804804+ build_error!(VTABLE_DEFAULT_ERROR)805805+ }806806+807807+ /// Driver's `get` callback.808808+ fn get(_policy: &mut Policy) -> Result<u32> {809809+ build_error!(VTABLE_DEFAULT_ERROR)810810+ }811811+812812+ /// Driver's `update_limits` callback.813813+ fn update_limits(_policy: &mut Policy) {814814+ build_error!(VTABLE_DEFAULT_ERROR)815815+ }816816+817817+ /// Driver's `bios_limit` callback.818818+ fn bios_limit(_policy: &mut Policy, _limit: &mut u32) -> Result {819819+ build_error!(VTABLE_DEFAULT_ERROR)820820+ }821821+822822+ /// Driver's `set_boost` callback.823823+ fn set_boost(_policy: &mut Policy, _state: i32) -> Result {824824+ build_error!(VTABLE_DEFAULT_ERROR)825825+ }826826+827827+ /// Driver's `register_em` callback.828828+ fn register_em(_policy: &mut Policy) {829829+ build_error!(VTABLE_DEFAULT_ERROR)830830+ }831831+}832832+833833+/// CPU frequency driver Registration.834834+///835835+/// ## Examples836836+///837837+/// The following example demonstrates how to register a cpufreq driver.838838+///839839+/// ```840840+/// use kernel::{841841+/// cpufreq,842842+/// c_str,843843+/// device::{Core, Device},844844+/// macros::vtable,845845+/// of, platform,846846+/// sync::Arc,847847+/// };848848+/// struct SampleDevice;849849+///850850+/// #[derive(Default)]851851+/// struct SampleDriver;852852+///853853+/// #[vtable]854854+/// impl cpufreq::Driver for SampleDriver {855855+/// const NAME: &'static CStr = c_str!("cpufreq-sample");856856+/// const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;857857+/// const BOOST_ENABLED: bool = true;858858+///859859+/// type PData = Arc<SampleDevice>;860860+///861861+/// fn init(policy: &mut cpufreq::Policy) -> Result<Self::PData> {862862+/// // Initialize here863863+/// Ok(Arc::new(SampleDevice, GFP_KERNEL)?)864864+/// }865865+///866866+/// fn exit(_policy: &mut cpufreq::Policy, _data: Option<Self::PData>) -> Result {867867+/// Ok(())868868+/// }869869+///870870+/// fn suspend(policy: &mut cpufreq::Policy) -> Result {871871+/// policy.generic_suspend()872872+/// }873873+///874874+/// fn verify(data: &mut cpufreq::PolicyData) -> Result {875875+/// data.generic_verify()876876+/// }877877+///878878+/// fn target_index(policy: &mut cpufreq::Policy, index: cpufreq::TableIndex) -> Result {879879+/// // Update CPU frequency880880+/// Ok(())881881+/// }882882+///883883+/// fn get(policy: &mut cpufreq::Policy) -> Result<u32> {884884+/// policy.generic_get()885885+/// }886886+/// }887887+///888888+/// impl platform::Driver for SampleDriver {889889+/// type IdInfo = ();890890+/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;891891+///892892+/// fn probe(893893+/// pdev: &platform::Device<Core>,894894+/// _id_info: Option<&Self::IdInfo>,895895+/// ) -> Result<Pin<KBox<Self>>> {896896+/// cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?;897897+/// Ok(KBox::new(Self {}, GFP_KERNEL)?.into())898898+/// }899899+/// }900900+/// ```901901+#[repr(transparent)]902902+pub struct Registration<T: Driver>(KBox<UnsafeCell<bindings::cpufreq_driver>>, PhantomData<T>);903903+904904+/// SAFETY: `Registration` doesn't offer any methods or access to fields when shared between threads905905+/// or CPUs, so it is safe to share it.906906+unsafe impl<T: Driver> Sync for Registration<T> {}907907+908908+#[allow(clippy::non_send_fields_in_send_ty)]909909+/// SAFETY: Registration with and unregistration from the cpufreq subsystem can happen from any910910+/// thread.911911+unsafe impl<T: Driver> Send for Registration<T> {}912912+913913+impl<T: Driver> Registration<T> {914914+ const VTABLE: bindings::cpufreq_driver = bindings::cpufreq_driver {915915+ name: Self::copy_name(T::NAME),916916+ boost_enabled: T::BOOST_ENABLED,917917+ flags: T::FLAGS,918918+919919+ // Initialize mandatory callbacks.920920+ init: Some(Self::init_callback),921921+ verify: Some(Self::verify_callback),922922+923923+ // Initialize optional callbacks based on the traits of `T`.924924+ setpolicy: if T::HAS_SETPOLICY {925925+ Some(Self::setpolicy_callback)926926+ } else {927927+ None928928+ },929929+ target: if T::HAS_TARGET {930930+ Some(Self::target_callback)931931+ } else {932932+ None933933+ },934934+ target_index: if T::HAS_TARGET_INDEX {935935+ Some(Self::target_index_callback)936936+ } else {937937+ None938938+ },939939+ fast_switch: if T::HAS_FAST_SWITCH {940940+ Some(Self::fast_switch_callback)941941+ } else {942942+ None943943+ },944944+ adjust_perf: if T::HAS_ADJUST_PERF {945945+ Some(Self::adjust_perf_callback)946946+ } else {947947+ None948948+ },949949+ get_intermediate: if T::HAS_GET_INTERMEDIATE {950950+ Some(Self::get_intermediate_callback)951951+ } else {952952+ None953953+ },954954+ target_intermediate: if T::HAS_TARGET_INTERMEDIATE {955955+ Some(Self::target_intermediate_callback)956956+ } else {957957+ None958958+ },959959+ get: if T::HAS_GET {960960+ Some(Self::get_callback)961961+ } else {962962+ None963963+ },964964+ update_limits: if T::HAS_UPDATE_LIMITS {965965+ Some(Self::update_limits_callback)966966+ } else {967967+ None968968+ },969969+ bios_limit: if T::HAS_BIOS_LIMIT {970970+ Some(Self::bios_limit_callback)971971+ } else {972972+ None973973+ },974974+ online: if T::HAS_ONLINE {975975+ Some(Self::online_callback)976976+ } else {977977+ None978978+ },979979+ offline: if T::HAS_OFFLINE {980980+ Some(Self::offline_callback)981981+ } else {982982+ None983983+ },984984+ exit: if T::HAS_EXIT {985985+ Some(Self::exit_callback)986986+ } else {987987+ None988988+ },989989+ suspend: if T::HAS_SUSPEND {990990+ Some(Self::suspend_callback)991991+ } else {992992+ None993993+ },994994+ resume: if T::HAS_RESUME {995995+ Some(Self::resume_callback)996996+ } else {997997+ None998998+ },999999+ ready: if T::HAS_READY {10001000+ Some(Self::ready_callback)10011001+ } else {10021002+ None10031003+ },10041004+ set_boost: if T::HAS_SET_BOOST {10051005+ Some(Self::set_boost_callback)10061006+ } else {10071007+ None10081008+ },10091009+ register_em: if T::HAS_REGISTER_EM {10101010+ Some(Self::register_em_callback)10111011+ } else {10121012+ None10131013+ },10141014+ // SAFETY: All zeros is a valid value for `bindings::cpufreq_driver`.10151015+ ..unsafe { MaybeUninit::zeroed().assume_init() }10161016+ };10171017+10181018+ const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] {10191019+ let src = name.as_bytes_with_nul();10201020+ let mut dst = [0; CPUFREQ_NAME_LEN];10211021+10221022+ build_assert!(src.len() <= CPUFREQ_NAME_LEN);10231023+10241024+ let mut i = 0;10251025+ while i < src.len() {10261026+ dst[i] = src[i];10271027+ i += 1;10281028+ }10291029+10301030+ dst10311031+ }10321032+10331033+ /// Registers a CPU frequency driver with the cpufreq core.10341034+ pub fn new() -> Result<Self> {10351035+ // We can't use `&Self::VTABLE` directly because the cpufreq core modifies some fields in10361036+ // the C `struct cpufreq_driver`, which requires a mutable reference.10371037+ let mut drv = KBox::new(UnsafeCell::new(Self::VTABLE), GFP_KERNEL)?;10381038+10391039+ // SAFETY: `drv` is guaranteed to be valid for the lifetime of `Registration`.10401040+ to_result(unsafe { bindings::cpufreq_register_driver(drv.get_mut()) })?;10411041+10421042+ Ok(Self(drv, PhantomData))10431043+ }10441044+10451045+ /// Same as [`Registration::new`], but does not return a [`Registration`] instance.10461046+ ///10471047+ /// Instead the [`Registration`] is owned by [`Devres`] and will be revoked / dropped, once the10481048+ /// device is detached.10491049+ pub fn new_foreign_owned(dev: &Device<Bound>) -> Result {10501050+ Devres::new_foreign_owned(dev, Self::new()?, GFP_KERNEL)10511051+ }10521052+}10531053+10541054+/// CPU frequency driver callbacks.10551055+impl<T: Driver> Registration<T> {10561056+ /// Driver's `init` callback.10571057+ ///10581058+ /// SAFETY: Called from C. Inputs must be valid pointers.10591059+ extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {10601060+ from_result(|| {10611061+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the10621062+ // lifetime of `policy`.10631063+ let policy = unsafe { Policy::from_raw_mut(ptr) };10641064+10651065+ let data = T::init(policy)?;10661066+ policy.set_data(data)?;10671067+ Ok(0)10681068+ })10691069+ }10701070+10711071+ /// Driver's `exit` callback.10721072+ ///10731073+ /// SAFETY: Called from C. Inputs must be valid pointers.10741074+ extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) {10751075+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the10761076+ // lifetime of `policy`.10771077+ let policy = unsafe { Policy::from_raw_mut(ptr) };10781078+10791079+ let data = policy.clear_data();10801080+ let _ = T::exit(policy, data);10811081+ }10821082+10831083+ /// Driver's `online` callback.10841084+ ///10851085+ /// SAFETY: Called from C. Inputs must be valid pointers.10861086+ extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {10871087+ from_result(|| {10881088+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the10891089+ // lifetime of `policy`.10901090+ let policy = unsafe { Policy::from_raw_mut(ptr) };10911091+ T::online(policy).map(|()| 0)10921092+ })10931093+ }10941094+10951095+ /// Driver's `offline` callback.10961096+ ///10971097+ /// SAFETY: Called from C. Inputs must be valid pointers.10981098+ extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {10991099+ from_result(|| {11001100+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the11011101+ // lifetime of `policy`.11021102+ let policy = unsafe { Policy::from_raw_mut(ptr) };11031103+ T::offline(policy).map(|()| 0)11041104+ })11051105+ }11061106+11071107+ /// Driver's `suspend` callback.11081108+ ///11091109+ /// SAFETY: Called from C. Inputs must be valid pointers.11101110+ extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {11111111+ from_result(|| {11121112+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the11131113+ // lifetime of `policy`.11141114+ let policy = unsafe { Policy::from_raw_mut(ptr) };11151115+ T::suspend(policy).map(|()| 0)11161116+ })11171117+ }11181118+11191119+ /// Driver's `resume` callback.11201120+ ///11211121+ /// SAFETY: Called from C. Inputs must be valid pointers.11221122+ extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {11231123+ from_result(|| {11241124+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the11251125+ // lifetime of `policy`.11261126+ let policy = unsafe { Policy::from_raw_mut(ptr) };11271127+ T::resume(policy).map(|()| 0)11281128+ })11291129+ }11301130+11311131+ /// Driver's `ready` callback.11321132+ ///11331133+ /// SAFETY: Called from C. Inputs must be valid pointers.11341134+ extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) {11351135+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the11361136+ // lifetime of `policy`.11371137+ let policy = unsafe { Policy::from_raw_mut(ptr) };11381138+ T::ready(policy);11391139+ }11401140+11411141+ /// Driver's `verify` callback.11421142+ ///11431143+ /// SAFETY: Called from C. Inputs must be valid pointers.11441144+ extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> kernel::ffi::c_int {11451145+ from_result(|| {11461146+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the11471147+ // lifetime of `policy`.11481148+ let data = unsafe { PolicyData::from_raw_mut(ptr) };11491149+ T::verify(data).map(|()| 0)11501150+ })11511151+ }11521152+11531153+ /// Driver's `setpolicy` callback.11541154+ ///11551155+ /// SAFETY: Called from C. Inputs must be valid pointers.11561156+ extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {11571157+ from_result(|| {11581158+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the11591159+ // lifetime of `policy`.11601160+ let policy = unsafe { Policy::from_raw_mut(ptr) };11611161+ T::setpolicy(policy).map(|()| 0)11621162+ })11631163+ }11641164+11651165+ /// Driver's `target` callback.11661166+ ///11671167+ /// SAFETY: Called from C. Inputs must be valid pointers.11681168+ extern "C" fn target_callback(11691169+ ptr: *mut bindings::cpufreq_policy,11701170+ target_freq: u32,11711171+ relation: u32,11721172+ ) -> kernel::ffi::c_int {11731173+ from_result(|| {11741174+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the11751175+ // lifetime of `policy`.11761176+ let policy = unsafe { Policy::from_raw_mut(ptr) };11771177+ T::target(policy, target_freq, Relation::new(relation)?).map(|()| 0)11781178+ })11791179+ }11801180+11811181+ /// Driver's `target_index` callback.11821182+ ///11831183+ /// SAFETY: Called from C. Inputs must be valid pointers.11841184+ extern "C" fn target_index_callback(11851185+ ptr: *mut bindings::cpufreq_policy,11861186+ index: u32,11871187+ ) -> kernel::ffi::c_int {11881188+ from_result(|| {11891189+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the11901190+ // lifetime of `policy`.11911191+ let policy = unsafe { Policy::from_raw_mut(ptr) };11921192+11931193+ // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the11941194+ // frequency table.11951195+ let index = unsafe { TableIndex::new(index as usize) };11961196+11971197+ T::target_index(policy, index).map(|()| 0)11981198+ })11991199+ }12001200+12011201+ /// Driver's `fast_switch` callback.12021202+ ///12031203+ /// SAFETY: Called from C. Inputs must be valid pointers.12041204+ extern "C" fn fast_switch_callback(12051205+ ptr: *mut bindings::cpufreq_policy,12061206+ target_freq: u32,12071207+ ) -> kernel::ffi::c_uint {12081208+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the12091209+ // lifetime of `policy`.12101210+ let policy = unsafe { Policy::from_raw_mut(ptr) };12111211+ T::fast_switch(policy, target_freq)12121212+ }12131213+12141214+ /// Driver's `adjust_perf` callback.12151215+ extern "C" fn adjust_perf_callback(12161216+ cpu: u32,12171217+ min_perf: usize,12181218+ target_perf: usize,12191219+ capacity: usize,12201220+ ) {12211221+ if let Ok(mut policy) = PolicyCpu::from_cpu(cpu) {12221222+ T::adjust_perf(&mut policy, min_perf, target_perf, capacity);12231223+ }12241224+ }12251225+12261226+ /// Driver's `get_intermediate` callback.12271227+ ///12281228+ /// SAFETY: Called from C. Inputs must be valid pointers.12291229+ extern "C" fn get_intermediate_callback(12301230+ ptr: *mut bindings::cpufreq_policy,12311231+ index: u32,12321232+ ) -> kernel::ffi::c_uint {12331233+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the12341234+ // lifetime of `policy`.12351235+ let policy = unsafe { Policy::from_raw_mut(ptr) };12361236+12371237+ // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the12381238+ // frequency table.12391239+ let index = unsafe { TableIndex::new(index as usize) };12401240+12411241+ T::get_intermediate(policy, index)12421242+ }12431243+12441244+ /// Driver's `target_intermediate` callback.12451245+ ///12461246+ /// SAFETY: Called from C. Inputs must be valid pointers.12471247+ extern "C" fn target_intermediate_callback(12481248+ ptr: *mut bindings::cpufreq_policy,12491249+ index: u32,12501250+ ) -> kernel::ffi::c_int {12511251+ from_result(|| {12521252+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the12531253+ // lifetime of `policy`.12541254+ let policy = unsafe { Policy::from_raw_mut(ptr) };12551255+12561256+ // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the12571257+ // frequency table.12581258+ let index = unsafe { TableIndex::new(index as usize) };12591259+12601260+ T::target_intermediate(policy, index).map(|()| 0)12611261+ })12621262+ }12631263+12641264+ /// Driver's `get` callback.12651265+ extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint {12661266+ PolicyCpu::from_cpu(cpu).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f))12671267+ }12681268+12691269+ /// Driver's `update_limit` callback.12701270+ extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) {12711271+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the12721272+ // lifetime of `policy`.12731273+ let policy = unsafe { Policy::from_raw_mut(ptr) };12741274+ T::update_limits(policy);12751275+ }12761276+12771277+ /// Driver's `bios_limit` callback.12781278+ ///12791279+ /// SAFETY: Called from C. Inputs must be valid pointers.12801280+ extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int {12811281+ from_result(|| {12821282+ let mut policy = PolicyCpu::from_cpu(cpu as u32)?;12831283+12841284+ // SAFETY: `limit` is guaranteed by the C code to be valid.12851285+ T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0)12861286+ })12871287+ }12881288+12891289+ /// Driver's `set_boost` callback.12901290+ ///12911291+ /// SAFETY: Called from C. Inputs must be valid pointers.12921292+ extern "C" fn set_boost_callback(12931293+ ptr: *mut bindings::cpufreq_policy,12941294+ state: i32,12951295+ ) -> kernel::ffi::c_int {12961296+ from_result(|| {12971297+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the12981298+ // lifetime of `policy`.12991299+ let policy = unsafe { Policy::from_raw_mut(ptr) };13001300+ T::set_boost(policy, state).map(|()| 0)13011301+ })13021302+ }13031303+13041304+ /// Driver's `register_em` callback.13051305+ ///13061306+ /// SAFETY: Called from C. Inputs must be valid pointers.13071307+ extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) {13081308+ // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the13091309+ // lifetime of `policy`.13101310+ let policy = unsafe { Policy::from_raw_mut(ptr) };13111311+ T::register_em(policy);13121312+ }13131313+}13141314+13151315+impl<T: Driver> Drop for Registration<T> {13161316+ /// Unregisters with the cpufreq core.13171317+ fn drop(&mut self) {13181318+ // SAFETY: `self.0` is guaranteed to be valid for the lifetime of `Registration`.13191319+ unsafe { bindings::cpufreq_unregister_driver(self.0.get_mut()) };13201320+ }13211321+}
+330
rust/kernel/cpumask.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+//! CPU Mask abstractions.44+//!55+//! C header: [`include/linux/cpumask.h`](srctree/include/linux/cpumask.h)66+77+use crate::{88+ alloc::{AllocError, Flags},99+ prelude::*,1010+ types::Opaque,1111+};1212+1313+#[cfg(CONFIG_CPUMASK_OFFSTACK)]1414+use core::ptr::{self, NonNull};1515+1616+#[cfg(not(CONFIG_CPUMASK_OFFSTACK))]1717+use core::mem::MaybeUninit;1818+1919+use core::ops::{Deref, DerefMut};2020+2121+/// A CPU Mask.2222+///2323+/// Rust abstraction for the C `struct cpumask`.2424+///2525+/// # Invariants2626+///2727+/// A [`Cpumask`] instance always corresponds to a valid C `struct cpumask`.2828+///2929+/// The callers must ensure that the `struct cpumask` is valid for access and3030+/// remains valid for the lifetime of the returned reference.3131+///3232+/// ## Examples3333+///3434+/// The following example demonstrates how to update a [`Cpumask`].3535+///3636+/// ```3737+/// use kernel::bindings;3838+/// use kernel::cpumask::Cpumask;3939+///4040+/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: u32, clear_cpu: i32) {4141+/// // SAFETY: The `ptr` is valid for writing and remains valid for the lifetime of the4242+/// // returned reference.4343+/// let mask = unsafe { Cpumask::as_mut_ref(ptr) };4444+///4545+/// mask.set(set_cpu);4646+/// mask.clear(clear_cpu);4747+/// }4848+/// ```4949+#[repr(transparent)]5050+pub struct Cpumask(Opaque<bindings::cpumask>);5151+5252+impl Cpumask {5353+ /// Creates a mutable reference to an existing `struct cpumask` pointer.5454+ ///5555+ /// # Safety5656+ ///5757+ /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime5858+ /// of the returned reference.5959+ pub unsafe fn as_mut_ref<'a>(ptr: *mut bindings::cpumask) -> &'a mut Self {6060+ // SAFETY: Guaranteed by the safety requirements of the function.6161+ //6262+ // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the6363+ // lifetime of the returned reference.6464+ unsafe { &mut *ptr.cast() }6565+ }6666+6767+ /// Creates a reference to an existing `struct cpumask` pointer.6868+ ///6969+ /// # Safety7070+ ///7171+ /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime7272+ /// of the returned reference.7373+ pub unsafe fn as_ref<'a>(ptr: *const bindings::cpumask) -> &'a Self {7474+ // SAFETY: Guaranteed by the safety requirements of the function.7575+ //7676+ // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the7777+ // lifetime of the returned reference.7878+ unsafe { &*ptr.cast() }7979+ }8080+8181+ /// Obtain the raw `struct cpumask` pointer.8282+ pub fn as_raw(&self) -> *mut bindings::cpumask {8383+ let this: *const Self = self;8484+ this.cast_mut().cast()8585+ }8686+8787+ /// Set `cpu` in the cpumask.8888+ ///8989+ /// ATTENTION: Contrary to C, this Rust `set()` method is non-atomic.9090+ /// This mismatches kernel naming convention and corresponds to the C9191+ /// function `__cpumask_set_cpu()`.9292+ #[inline]9393+ pub fn set(&mut self, cpu: u32) {9494+ // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `__cpumask_set_cpu`.9595+ unsafe { bindings::__cpumask_set_cpu(cpu, self.as_raw()) };9696+ }9797+9898+ /// Clear `cpu` in the cpumask.9999+ ///100100+ /// ATTENTION: Contrary to C, this Rust `clear()` method is non-atomic.101101+ /// This mismatches kernel naming convention and corresponds to the C102102+ /// function `__cpumask_clear_cpu()`.103103+ #[inline]104104+ pub fn clear(&mut self, cpu: i32) {105105+ // SAFETY: By the type invariant, `self.as_raw` is a valid argument to106106+ // `__cpumask_clear_cpu`.107107+ unsafe { bindings::__cpumask_clear_cpu(cpu, self.as_raw()) };108108+ }109109+110110+ /// Test `cpu` in the cpumask.111111+ ///112112+ /// Equivalent to the kernel's `cpumask_test_cpu` API.113113+ #[inline]114114+ pub fn test(&self, cpu: i32) -> bool {115115+ // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_test_cpu`.116116+ unsafe { bindings::cpumask_test_cpu(cpu, self.as_raw()) }117117+ }118118+119119+ /// Set all CPUs in the cpumask.120120+ ///121121+ /// Equivalent to the kernel's `cpumask_setall` API.122122+ #[inline]123123+ pub fn setall(&mut self) {124124+ // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_setall`.125125+ unsafe { bindings::cpumask_setall(self.as_raw()) };126126+ }127127+128128+ /// Checks if cpumask is empty.129129+ ///130130+ /// Equivalent to the kernel's `cpumask_empty` API.131131+ #[inline]132132+ pub fn empty(&self) -> bool {133133+ // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_empty`.134134+ unsafe { bindings::cpumask_empty(self.as_raw()) }135135+ }136136+137137+ /// Checks if cpumask is full.138138+ ///139139+ /// Equivalent to the kernel's `cpumask_full` API.140140+ #[inline]141141+ pub fn full(&self) -> bool {142142+ // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_full`.143143+ unsafe { bindings::cpumask_full(self.as_raw()) }144144+ }145145+146146+ /// Get weight of the cpumask.147147+ ///148148+ /// Equivalent to the kernel's `cpumask_weight` API.149149+ #[inline]150150+ pub fn weight(&self) -> u32 {151151+ // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_weight`.152152+ unsafe { bindings::cpumask_weight(self.as_raw()) }153153+ }154154+155155+ /// Copy cpumask.156156+ ///157157+ /// Equivalent to the kernel's `cpumask_copy` API.158158+ #[inline]159159+ pub fn copy(&self, dstp: &mut Self) {160160+ // SAFETY: By the type invariant, `Self::as_raw` is a valid argument to `cpumask_copy`.161161+ unsafe { bindings::cpumask_copy(dstp.as_raw(), self.as_raw()) };162162+ }163163+}164164+165165+/// A CPU Mask pointer.166166+///167167+/// Rust abstraction for the C `struct cpumask_var_t`.168168+///169169+/// # Invariants170170+///171171+/// A [`CpumaskVar`] instance always corresponds to a valid C `struct cpumask_var_t`.172172+///173173+/// The callers must ensure that the `struct cpumask_var_t` is valid for access and remains valid174174+/// for the lifetime of [`CpumaskVar`].175175+///176176+/// ## Examples177177+///178178+/// The following example demonstrates how to create and update a [`CpumaskVar`].179179+///180180+/// ```181181+/// use kernel::cpumask::CpumaskVar;182182+///183183+/// let mut mask = CpumaskVar::new_zero(GFP_KERNEL).unwrap();184184+///185185+/// assert!(mask.empty());186186+/// mask.set(2);187187+/// assert!(mask.test(2));188188+/// mask.set(3);189189+/// assert!(mask.test(3));190190+/// assert_eq!(mask.weight(), 2);191191+///192192+/// let mask2 = CpumaskVar::try_clone(&mask).unwrap();193193+/// assert!(mask2.test(2));194194+/// assert!(mask2.test(3));195195+/// assert_eq!(mask2.weight(), 2);196196+/// ```197197+pub struct CpumaskVar {198198+ #[cfg(CONFIG_CPUMASK_OFFSTACK)]199199+ ptr: NonNull<Cpumask>,200200+ #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]201201+ mask: Cpumask,202202+}203203+204204+impl CpumaskVar {205205+ /// Creates a zero-initialized instance of the [`CpumaskVar`].206206+ pub fn new_zero(_flags: Flags) -> Result<Self, AllocError> {207207+ Ok(Self {208208+ #[cfg(CONFIG_CPUMASK_OFFSTACK)]209209+ ptr: {210210+ let mut ptr: *mut bindings::cpumask = ptr::null_mut();211211+212212+ // SAFETY: It is safe to call this method as the reference to `ptr` is valid.213213+ //214214+ // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of215215+ // scope.216216+ unsafe { bindings::zalloc_cpumask_var(&mut ptr, _flags.as_raw()) };217217+ NonNull::new(ptr.cast()).ok_or(AllocError)?218218+ },219219+220220+ #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]221221+ // SAFETY: FFI type is valid to be zero-initialized.222222+ //223223+ // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of scope.224224+ mask: unsafe { core::mem::zeroed() },225225+ })226226+ }227227+228228+ /// Creates an instance of the [`CpumaskVar`].229229+ ///230230+ /// # Safety231231+ ///232232+ /// The caller must ensure that the returned [`CpumaskVar`] is properly initialized before233233+ /// getting used.234234+ pub unsafe fn new(_flags: Flags) -> Result<Self, AllocError> {235235+ Ok(Self {236236+ #[cfg(CONFIG_CPUMASK_OFFSTACK)]237237+ ptr: {238238+ let mut ptr: *mut bindings::cpumask = ptr::null_mut();239239+240240+ // SAFETY: It is safe to call this method as the reference to `ptr` is valid.241241+ //242242+ // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of243243+ // scope.244244+ unsafe { bindings::alloc_cpumask_var(&mut ptr, _flags.as_raw()) };245245+ NonNull::new(ptr.cast()).ok_or(AllocError)?246246+ },247247+ #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]248248+ // SAFETY: Guaranteed by the safety requirements of the function.249249+ //250250+ // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of scope.251251+ mask: unsafe { MaybeUninit::uninit().assume_init() },252252+ })253253+ }254254+255255+ /// Creates a mutable reference to an existing `struct cpumask_var_t` pointer.256256+ ///257257+ /// # Safety258258+ ///259259+ /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime260260+ /// of the returned reference.261261+ pub unsafe fn as_mut_ref<'a>(ptr: *mut bindings::cpumask_var_t) -> &'a mut Self {262262+ // SAFETY: Guaranteed by the safety requirements of the function.263263+ //264264+ // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the265265+ // lifetime of the returned reference.266266+ unsafe { &mut *ptr.cast() }267267+ }268268+269269+ /// Creates a reference to an existing `struct cpumask_var_t` pointer.270270+ ///271271+ /// # Safety272272+ ///273273+ /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime274274+ /// of the returned reference.275275+ pub unsafe fn as_ref<'a>(ptr: *const bindings::cpumask_var_t) -> &'a Self {276276+ // SAFETY: Guaranteed by the safety requirements of the function.277277+ //278278+ // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the279279+ // lifetime of the returned reference.280280+ unsafe { &*ptr.cast() }281281+ }282282+283283+ /// Clones cpumask.284284+ pub fn try_clone(cpumask: &Cpumask) -> Result<Self> {285285+ // SAFETY: The returned cpumask_var is initialized right after this call.286286+ let mut cpumask_var = unsafe { Self::new(GFP_KERNEL) }?;287287+288288+ cpumask.copy(&mut cpumask_var);289289+ Ok(cpumask_var)290290+ }291291+}292292+293293+// Make [`CpumaskVar`] behave like a pointer to [`Cpumask`].294294+impl Deref for CpumaskVar {295295+ type Target = Cpumask;296296+297297+ #[cfg(CONFIG_CPUMASK_OFFSTACK)]298298+ fn deref(&self) -> &Self::Target {299299+ // SAFETY: The caller owns CpumaskVar, so it is safe to deref the cpumask.300300+ unsafe { &*self.ptr.as_ptr() }301301+ }302302+303303+ #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]304304+ fn deref(&self) -> &Self::Target {305305+ &self.mask306306+ }307307+}308308+309309+impl DerefMut for CpumaskVar {310310+ #[cfg(CONFIG_CPUMASK_OFFSTACK)]311311+ fn deref_mut(&mut self) -> &mut Cpumask {312312+ // SAFETY: The caller owns CpumaskVar, so it is safe to deref the cpumask.313313+ unsafe { self.ptr.as_mut() }314314+ }315315+316316+ #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]317317+ fn deref_mut(&mut self) -> &mut Cpumask {318318+ &mut self.mask319319+ }320320+}321321+322322+impl Drop for CpumaskVar {323323+ fn drop(&mut self) {324324+ #[cfg(CONFIG_CPUMASK_OFFSTACK)]325325+ // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `free_cpumask_var`.326326+ unsafe {327327+ bindings::free_cpumask_var(self.as_raw())328328+ };329329+ }330330+}
+88-2
rust/kernel/device.rs
···99 str::CStr,1010 types::{ARef, Opaque},1111};1212-use core::{fmt, ptr};1212+use core::{fmt, marker::PhantomData, ptr};13131414#[cfg(CONFIG_PRINTK)]1515use crate::c_str;···4242/// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be4343/// dropped from any thread.4444#[repr(transparent)]4545-pub struct Device(Opaque<bindings::device>);4545+pub struct Device<Ctx: DeviceContext = Normal>(Opaque<bindings::device>, PhantomData<Ctx>);46464747impl Device {4848 /// Creates a new reference-counted abstraction instance of an existing `struct device` pointer.···5959 // SAFETY: By the safety requirements ptr is valid6060 unsafe { Self::as_ref(ptr) }.into()6161 }6262+}62636464+impl<Ctx: DeviceContext> Device<Ctx> {6365 /// Obtain the raw `struct device *`.6466 pub(crate) fn as_raw(&self) -> *mut bindings::device {6567 self.0.get()···191189 }192190}193191192192+// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic193193+// argument.194194+kernel::impl_device_context_deref!(unsafe { Device });195195+kernel::impl_device_context_into_aref!(Device);196196+194197// SAFETY: Instances of `Device` are always reference-counted.195198unsafe impl crate::types::AlwaysRefCounted for Device {196199 fn inc_ref(&self) {···232225/// any of the bus callbacks, such as `probe()`.233226pub struct Core;234227228228+/// The [`Bound`] context is the context of a bus specific device reference when it is guaranteed to229229+/// be bound for the duration of its lifetime.230230+pub struct Bound;231231+235232mod private {236233 pub trait Sealed {}237234235235+ impl Sealed for super::Bound {}238236 impl Sealed for super::Core {}239237 impl Sealed for super::Normal {}240238}241239240240+impl DeviceContext for Bound {}242241impl DeviceContext for Core {}243242impl DeviceContext for Normal {}243243+244244+/// # Safety245245+///246246+/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the247247+/// generic argument of `$device`.248248+#[doc(hidden)]249249+#[macro_export]250250+macro_rules! __impl_device_context_deref {251251+ (unsafe { $device:ident, $src:ty => $dst:ty }) => {252252+ impl ::core::ops::Deref for $device<$src> {253253+ type Target = $device<$dst>;254254+255255+ fn deref(&self) -> &Self::Target {256256+ let ptr: *const Self = self;257257+258258+ // CAST: `$device<$src>` and `$device<$dst>` transparently wrap the same type by the259259+ // safety requirement of the macro.260260+ let ptr = ptr.cast::<Self::Target>();261261+262262+ // SAFETY: `ptr` was derived from `&self`.263263+ unsafe { &*ptr }264264+ }265265+ }266266+ };267267+}268268+269269+/// Implement [`core::ops::Deref`] traits for allowed [`DeviceContext`] conversions of a (bus270270+/// specific) device.271271+///272272+/// # Safety273273+///274274+/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the275275+/// generic argument of `$device`.276276+#[macro_export]277277+macro_rules! impl_device_context_deref {278278+ (unsafe { $device:ident }) => {279279+ // SAFETY: This macro has the exact same safety requirement as280280+ // `__impl_device_context_deref!`.281281+ ::kernel::__impl_device_context_deref!(unsafe {282282+ $device,283283+ $crate::device::Core => $crate::device::Bound284284+ });285285+286286+ // SAFETY: This macro has the exact same safety requirement as287287+ // `__impl_device_context_deref!`.288288+ ::kernel::__impl_device_context_deref!(unsafe {289289+ $device,290290+ $crate::device::Bound => $crate::device::Normal291291+ });292292+ };293293+}294294+295295+#[doc(hidden)]296296+#[macro_export]297297+macro_rules! __impl_device_context_into_aref {298298+ ($src:ty, $device:tt) => {299299+ impl ::core::convert::From<&$device<$src>> for $crate::types::ARef<$device> {300300+ fn from(dev: &$device<$src>) -> Self {301301+ (&**dev).into()302302+ }303303+ }304304+ };305305+}306306+307307+/// Implement [`core::convert::From`], such that all `&Device<Ctx>` can be converted to an308308+/// `ARef<Device>`.309309+#[macro_export]310310+macro_rules! impl_device_context_into_aref {311311+ ($device:tt) => {312312+ ::kernel::__impl_device_context_into_aref!($crate::device::Core, $device);313313+ ::kernel::__impl_device_context_into_aref!($crate::device::Bound, $device);314314+ };315315+}244316245317#[doc(hidden)]246318#[macro_export]
+7-10
rust/kernel/devres.rs
···88use crate::{99 alloc::Flags,1010 bindings,1111- device::Device,1111+ device::{Bound, Device},1212 error::{Error, Result},1313 ffi::c_void,1414 prelude::*,···4545/// # Example4646///4747/// ```no_run4848-/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{Io, IoRaw}};4848+/// # use kernel::{bindings, c_str, device::{Bound, Device}, devres::Devres, io::{Io, IoRaw}};4949/// # use core::ops::Deref;5050///5151/// // See also [`pci::Bar`] for a real example.···8383/// unsafe { Io::from_raw(&self.0) }8484/// }8585/// }8686-/// # fn no_run() -> Result<(), Error> {8787-/// # // SAFETY: Invalid usage; just for the example to get an `ARef<Device>` instance.8888-/// # let dev = unsafe { Device::get_device(core::ptr::null_mut()) };8989-///8686+/// # fn no_run(dev: &Device<Bound>) -> Result<(), Error> {9087/// // SAFETY: Invalid usage for example purposes.9188/// let iomem = unsafe { IoMem::<{ core::mem::size_of::<u32>() }>::new(0xBAAAAAAD)? };9292-/// let devres = Devres::new(&dev, iomem, GFP_KERNEL)?;8989+/// let devres = Devres::new(dev, iomem, GFP_KERNEL)?;9390///9491/// let res = devres.try_access().ok_or(ENXIO)?;9592/// res.write8(0x42, 0x0);···9699pub struct Devres<T>(Arc<DevresInner<T>>);9710098101impl<T> DevresInner<T> {9999- fn new(dev: &Device, data: T, flags: Flags) -> Result<Arc<DevresInner<T>>> {102102+ fn new(dev: &Device<Bound>, data: T, flags: Flags) -> Result<Arc<DevresInner<T>>> {100103 let inner = Arc::pin_init(101104 pin_init!( DevresInner {102105 dev: dev.into(),···168171impl<T> Devres<T> {169172 /// Creates a new [`Devres`] instance of the given `data`. The `data` encapsulated within the170173 /// returned `Devres` instance' `data` will be revoked once the device is detached.171171- pub fn new(dev: &Device, data: T, flags: Flags) -> Result<Self> {174174+ pub fn new(dev: &Device<Bound>, data: T, flags: Flags) -> Result<Self> {172175 let inner = DevresInner::new(dev, data, flags)?;173176174177 Ok(Devres(inner))···176179177180 /// Same as [`Devres::new`], but does not return a `Devres` instance. Instead the given `data`178181 /// is owned by devres and will be revoked / dropped, once the device is detached.179179- pub fn new_foreign_owned(dev: &Device, data: T, flags: Flags) -> Result {182182+ pub fn new_foreign_owned(dev: &Device<Bound>, data: T, flags: Flags) -> Result {180183 let _ = DevresInner::new(dev, data, flags)?;181184182185 Ok(())
+7
rust/kernel/lib.rs
···4242pub mod block;4343#[doc(hidden)]4444pub mod build_assert;4545+pub mod clk;4646+pub mod cpu;4747+#[cfg(CONFIG_CPU_FREQ)]4848+pub mod cpufreq;4949+pub mod cpumask;4550pub mod cred;4651pub mod device;4752pub mod device_id;···6964#[cfg(CONFIG_NET)]7065pub mod net;7166pub mod of;6767+#[cfg(CONFIG_PM_OPP)]6868+pub mod opp;7269pub mod page;7370#[cfg(CONFIG_PCI)]7471pub mod pci;
+1145
rust/kernel/opp.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+//! Operating performance points.44+//!55+//! This module provides rust abstractions for interacting with the OPP subsystem.66+//!77+//! C header: [`include/linux/pm_opp.h`](srctree/include/linux/pm_opp.h)88+//!99+//! Reference: <https://docs.kernel.org/power/opp.html>1010+1111+use crate::{1212+ clk::Hertz,1313+ cpumask::{Cpumask, CpumaskVar},1414+ device::Device,1515+ error::{code::*, from_err_ptr, from_result, to_result, Error, Result, VTABLE_DEFAULT_ERROR},1616+ ffi::c_ulong,1717+ prelude::*,1818+ str::CString,1919+ types::{ARef, AlwaysRefCounted, Opaque},2020+};2121+2222+#[cfg(CONFIG_CPU_FREQ)]2323+/// Frequency table implementation.2424+mod freq {2525+ use super::*;2626+ use crate::cpufreq;2727+ use core::ops::Deref;2828+2929+ /// OPP frequency table.3030+ ///3131+ /// A [`cpufreq::Table`] created from [`Table`].3232+ pub struct FreqTable {3333+ dev: ARef<Device>,3434+ ptr: *mut bindings::cpufreq_frequency_table,3535+ }3636+3737+ impl FreqTable {3838+ /// Creates a new instance of [`FreqTable`] from [`Table`].3939+ pub(crate) fn new(table: &Table) -> Result<Self> {4040+ let mut ptr: *mut bindings::cpufreq_frequency_table = ptr::null_mut();4141+4242+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety4343+ // requirements.4444+ to_result(unsafe {4545+ bindings::dev_pm_opp_init_cpufreq_table(table.dev.as_raw(), &mut ptr)4646+ })?;4747+4848+ Ok(Self {4949+ dev: table.dev.clone(),5050+ ptr,5151+ })5252+ }5353+5454+ /// Returns a reference to the underlying [`cpufreq::Table`].5555+ #[inline]5656+ fn table(&self) -> &cpufreq::Table {5757+ // SAFETY: The `ptr` is guaranteed by the C code to be valid.5858+ unsafe { cpufreq::Table::from_raw(self.ptr) }5959+ }6060+ }6161+6262+ impl Deref for FreqTable {6363+ type Target = cpufreq::Table;6464+6565+ #[inline]6666+ fn deref(&self) -> &Self::Target {6767+ self.table()6868+ }6969+ }7070+7171+ impl Drop for FreqTable {7272+ fn drop(&mut self) {7373+ // SAFETY: The pointer was created via `dev_pm_opp_init_cpufreq_table`, and is only7474+ // freed here.7575+ unsafe {7676+ bindings::dev_pm_opp_free_cpufreq_table(self.dev.as_raw(), &mut self.as_raw())7777+ };7878+ }7979+ }8080+}8181+8282+#[cfg(CONFIG_CPU_FREQ)]8383+pub use freq::FreqTable;8484+8585+use core::{marker::PhantomData, ptr};8686+8787+use macros::vtable;8888+8989+/// Creates a null-terminated slice of pointers to [`Cstring`]s.9090+fn to_c_str_array(names: &[CString]) -> Result<KVec<*const u8>> {9191+ // Allocated a null-terminated vector of pointers.9292+ let mut list = KVec::with_capacity(names.len() + 1, GFP_KERNEL)?;9393+9494+ for name in names.iter() {9595+ list.push(name.as_ptr() as _, GFP_KERNEL)?;9696+ }9797+9898+ list.push(ptr::null(), GFP_KERNEL)?;9999+ Ok(list)100100+}101101+102102+/// The voltage unit.103103+///104104+/// Represents voltage in microvolts, wrapping a [`c_ulong`] value.105105+///106106+/// ## Examples107107+///108108+/// ```109109+/// use kernel::opp::MicroVolt;110110+///111111+/// let raw = 90500;112112+/// let volt = MicroVolt(raw);113113+///114114+/// assert_eq!(usize::from(volt), raw);115115+/// assert_eq!(volt, MicroVolt(raw));116116+/// ```117117+#[derive(Copy, Clone, PartialEq, Eq, Debug)]118118+pub struct MicroVolt(pub c_ulong);119119+120120+impl From<MicroVolt> for c_ulong {121121+ #[inline]122122+ fn from(volt: MicroVolt) -> Self {123123+ volt.0124124+ }125125+}126126+127127+/// The power unit.128128+///129129+/// Represents power in microwatts, wrapping a [`c_ulong`] value.130130+///131131+/// ## Examples132132+///133133+/// ```134134+/// use kernel::opp::MicroWatt;135135+///136136+/// let raw = 1000000;137137+/// let power = MicroWatt(raw);138138+///139139+/// assert_eq!(usize::from(power), raw);140140+/// assert_eq!(power, MicroWatt(raw));141141+/// ```142142+#[derive(Copy, Clone, PartialEq, Eq, Debug)]143143+pub struct MicroWatt(pub c_ulong);144144+145145+impl From<MicroWatt> for c_ulong {146146+ #[inline]147147+ fn from(power: MicroWatt) -> Self {148148+ power.0149149+ }150150+}151151+152152+/// Handle for a dynamically created [`OPP`].153153+///154154+/// The associated [`OPP`] is automatically removed when the [`Token`] is dropped.155155+///156156+/// ## Examples157157+///158158+/// The following example demonstrates how to create an [`OPP`] dynamically.159159+///160160+/// ```161161+/// use kernel::clk::Hertz;162162+/// use kernel::device::Device;163163+/// use kernel::error::Result;164164+/// use kernel::opp::{Data, MicroVolt, Token};165165+/// use kernel::types::ARef;166166+///167167+/// fn create_opp(dev: &ARef<Device>, freq: Hertz, volt: MicroVolt, level: u32) -> Result<Token> {168168+/// let data = Data::new(freq, volt, level, false);169169+///170170+/// // OPP is removed once token goes out of scope.171171+/// data.add_opp(dev)172172+/// }173173+/// ```174174+pub struct Token {175175+ dev: ARef<Device>,176176+ freq: Hertz,177177+}178178+179179+impl Token {180180+ /// Dynamically adds an [`OPP`] and returns a [`Token`] that removes it on drop.181181+ fn new(dev: &ARef<Device>, mut data: Data) -> Result<Self> {182182+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety183183+ // requirements.184184+ to_result(unsafe { bindings::dev_pm_opp_add_dynamic(dev.as_raw(), &mut data.0) })?;185185+ Ok(Self {186186+ dev: dev.clone(),187187+ freq: data.freq(),188188+ })189189+ }190190+}191191+192192+impl Drop for Token {193193+ fn drop(&mut self) {194194+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety195195+ // requirements.196196+ unsafe { bindings::dev_pm_opp_remove(self.dev.as_raw(), self.freq.into()) };197197+ }198198+}199199+200200+/// OPP data.201201+///202202+/// Rust abstraction for the C `struct dev_pm_opp_data`, used to define operating performance203203+/// points (OPPs) dynamically.204204+///205205+/// ## Examples206206+///207207+/// The following example demonstrates how to create an [`OPP`] with [`Data`].208208+///209209+/// ```210210+/// use kernel::clk::Hertz;211211+/// use kernel::device::Device;212212+/// use kernel::error::Result;213213+/// use kernel::opp::{Data, MicroVolt, Token};214214+/// use kernel::types::ARef;215215+///216216+/// fn create_opp(dev: &ARef<Device>, freq: Hertz, volt: MicroVolt, level: u32) -> Result<Token> {217217+/// let data = Data::new(freq, volt, level, false);218218+///219219+/// // OPP is removed once token goes out of scope.220220+/// data.add_opp(dev)221221+/// }222222+/// ```223223+#[repr(transparent)]224224+pub struct Data(bindings::dev_pm_opp_data);225225+226226+impl Data {227227+ /// Creates a new instance of [`Data`].228228+ ///229229+ /// This can be used to define a dynamic OPP to be added to a device.230230+ pub fn new(freq: Hertz, volt: MicroVolt, level: u32, turbo: bool) -> Self {231231+ Self(bindings::dev_pm_opp_data {232232+ turbo,233233+ freq: freq.into(),234234+ u_volt: volt.into(),235235+ level,236236+ })237237+ }238238+239239+ /// Adds an [`OPP`] dynamically.240240+ ///241241+ /// Returns a [`Token`] that ensures the OPP is automatically removed242242+ /// when it goes out of scope.243243+ #[inline]244244+ pub fn add_opp(self, dev: &ARef<Device>) -> Result<Token> {245245+ Token::new(dev, self)246246+ }247247+248248+ /// Returns the frequency associated with this OPP data.249249+ #[inline]250250+ fn freq(&self) -> Hertz {251251+ Hertz(self.0.freq)252252+ }253253+}254254+255255+/// [`OPP`] search options.256256+///257257+/// ## Examples258258+///259259+/// Defines how to search for an [`OPP`] in a [`Table`] relative to a frequency.260260+///261261+/// ```262262+/// use kernel::clk::Hertz;263263+/// use kernel::error::Result;264264+/// use kernel::opp::{OPP, SearchType, Table};265265+/// use kernel::types::ARef;266266+///267267+/// fn find_opp(table: &Table, freq: Hertz) -> Result<ARef<OPP>> {268268+/// let opp = table.opp_from_freq(freq, Some(true), None, SearchType::Exact)?;269269+///270270+/// pr_info!("OPP frequency is: {:?}\n", opp.freq(None));271271+/// pr_info!("OPP voltage is: {:?}\n", opp.voltage());272272+/// pr_info!("OPP level is: {}\n", opp.level());273273+/// pr_info!("OPP power is: {:?}\n", opp.power());274274+///275275+/// Ok(opp)276276+/// }277277+/// ```278278+#[derive(Copy, Clone, Debug, Eq, PartialEq)]279279+pub enum SearchType {280280+ /// Match the exact frequency.281281+ Exact,282282+ /// Find the highest frequency less than or equal to the given value.283283+ Floor,284284+ /// Find the lowest frequency greater than or equal to the given value.285285+ Ceil,286286+}287287+288288+/// OPP configuration callbacks.289289+///290290+/// Implement this trait to customize OPP clock and regulator setup for your device.291291+#[vtable]292292+pub trait ConfigOps {293293+ /// This is typically used to scale clocks when transitioning between OPPs.294294+ #[inline]295295+ fn config_clks(_dev: &Device, _table: &Table, _opp: &OPP, _scaling_down: bool) -> Result {296296+ build_error!(VTABLE_DEFAULT_ERROR)297297+ }298298+299299+ /// This provides access to the old and new OPPs, allowing for safe regulator adjustments.300300+ #[inline]301301+ fn config_regulators(302302+ _dev: &Device,303303+ _opp_old: &OPP,304304+ _opp_new: &OPP,305305+ _data: *mut *mut bindings::regulator,306306+ _count: u32,307307+ ) -> Result {308308+ build_error!(VTABLE_DEFAULT_ERROR)309309+ }310310+}311311+312312+/// OPP configuration token.313313+///314314+/// Returned by the OPP core when configuration is applied to a [`Device`]. The associated315315+/// configuration is automatically cleared when the token is dropped.316316+pub struct ConfigToken(i32);317317+318318+impl Drop for ConfigToken {319319+ fn drop(&mut self) {320320+ // SAFETY: This is the same token value returned by the C code via `dev_pm_opp_set_config`.321321+ unsafe { bindings::dev_pm_opp_clear_config(self.0) };322322+ }323323+}324324+325325+/// OPP configurations.326326+///327327+/// Rust abstraction for the C `struct dev_pm_opp_config`.328328+///329329+/// ## Examples330330+///331331+/// The following example demonstrates how to set OPP property-name configuration for a [`Device`].332332+///333333+/// ```334334+/// use kernel::device::Device;335335+/// use kernel::error::Result;336336+/// use kernel::opp::{Config, ConfigOps, ConfigToken};337337+/// use kernel::str::CString;338338+/// use kernel::types::ARef;339339+/// use kernel::macros::vtable;340340+///341341+/// #[derive(Default)]342342+/// struct Driver;343343+///344344+/// #[vtable]345345+/// impl ConfigOps for Driver {}346346+///347347+/// fn configure(dev: &ARef<Device>) -> Result<ConfigToken> {348348+/// let name = CString::try_from_fmt(fmt!("{}", "slow"))?;349349+///350350+/// // The OPP configuration is cleared once the [`ConfigToken`] goes out of scope.351351+/// Config::<Driver>::new()352352+/// .set_prop_name(name)?353353+/// .set(dev)354354+/// }355355+/// ```356356+#[derive(Default)]357357+pub struct Config<T: ConfigOps>358358+where359359+ T: Default,360360+{361361+ clk_names: Option<KVec<CString>>,362362+ prop_name: Option<CString>,363363+ regulator_names: Option<KVec<CString>>,364364+ supported_hw: Option<KVec<u32>>,365365+366366+ // Tuple containing (required device, index)367367+ required_dev: Option<(ARef<Device>, u32)>,368368+ _data: PhantomData<T>,369369+}370370+371371+impl<T: ConfigOps + Default> Config<T> {372372+ /// Creates a new instance of [`Config`].373373+ #[inline]374374+ pub fn new() -> Self {375375+ Self::default()376376+ }377377+378378+ /// Initializes clock names.379379+ pub fn set_clk_names(mut self, names: KVec<CString>) -> Result<Self> {380380+ if self.clk_names.is_some() {381381+ return Err(EBUSY);382382+ }383383+384384+ if names.is_empty() {385385+ return Err(EINVAL);386386+ }387387+388388+ self.clk_names = Some(names);389389+ Ok(self)390390+ }391391+392392+ /// Initializes property name.393393+ pub fn set_prop_name(mut self, name: CString) -> Result<Self> {394394+ if self.prop_name.is_some() {395395+ return Err(EBUSY);396396+ }397397+398398+ self.prop_name = Some(name);399399+ Ok(self)400400+ }401401+402402+ /// Initializes regulator names.403403+ pub fn set_regulator_names(mut self, names: KVec<CString>) -> Result<Self> {404404+ if self.regulator_names.is_some() {405405+ return Err(EBUSY);406406+ }407407+408408+ if names.is_empty() {409409+ return Err(EINVAL);410410+ }411411+412412+ self.regulator_names = Some(names);413413+414414+ Ok(self)415415+ }416416+417417+ /// Initializes required devices.418418+ pub fn set_required_dev(mut self, dev: ARef<Device>, index: u32) -> Result<Self> {419419+ if self.required_dev.is_some() {420420+ return Err(EBUSY);421421+ }422422+423423+ self.required_dev = Some((dev, index));424424+ Ok(self)425425+ }426426+427427+ /// Initializes supported hardware.428428+ pub fn set_supported_hw(mut self, hw: KVec<u32>) -> Result<Self> {429429+ if self.supported_hw.is_some() {430430+ return Err(EBUSY);431431+ }432432+433433+ if hw.is_empty() {434434+ return Err(EINVAL);435435+ }436436+437437+ self.supported_hw = Some(hw);438438+ Ok(self)439439+ }440440+441441+ /// Sets the configuration with the OPP core.442442+ ///443443+ /// The returned [`ConfigToken`] will remove the configuration when dropped.444444+ pub fn set(self, dev: &Device) -> Result<ConfigToken> {445445+ let (_clk_list, clk_names) = match &self.clk_names {446446+ Some(x) => {447447+ let list = to_c_str_array(x)?;448448+ let ptr = list.as_ptr();449449+ (Some(list), ptr)450450+ }451451+ None => (None, ptr::null()),452452+ };453453+454454+ let (_regulator_list, regulator_names) = match &self.regulator_names {455455+ Some(x) => {456456+ let list = to_c_str_array(x)?;457457+ let ptr = list.as_ptr();458458+ (Some(list), ptr)459459+ }460460+ None => (None, ptr::null()),461461+ };462462+463463+ let prop_name = self464464+ .prop_name465465+ .as_ref()466466+ .map_or(ptr::null(), |p| p.as_char_ptr());467467+468468+ let (supported_hw, supported_hw_count) = self469469+ .supported_hw470470+ .as_ref()471471+ .map_or((ptr::null(), 0), |hw| (hw.as_ptr(), hw.len() as u32));472472+473473+ let (required_dev, required_dev_index) = self474474+ .required_dev475475+ .as_ref()476476+ .map_or((ptr::null_mut(), 0), |(dev, idx)| (dev.as_raw(), *idx));477477+478478+ let mut config = bindings::dev_pm_opp_config {479479+ clk_names,480480+ config_clks: if T::HAS_CONFIG_CLKS {481481+ Some(Self::config_clks)482482+ } else {483483+ None484484+ },485485+ prop_name,486486+ regulator_names,487487+ config_regulators: if T::HAS_CONFIG_REGULATORS {488488+ Some(Self::config_regulators)489489+ } else {490490+ None491491+ },492492+ supported_hw,493493+ supported_hw_count,494494+495495+ required_dev,496496+ required_dev_index,497497+ };498498+499499+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety500500+ // requirements. The OPP core guarantees not to access fields of [`Config`] after this call501501+ // and so we don't need to save a copy of them for future use.502502+ let ret = unsafe { bindings::dev_pm_opp_set_config(dev.as_raw(), &mut config) };503503+ if ret < 0 {504504+ Err(Error::from_errno(ret))505505+ } else {506506+ Ok(ConfigToken(ret))507507+ }508508+ }509509+510510+ /// Config's clk callback.511511+ ///512512+ /// SAFETY: Called from C. Inputs must be valid pointers.513513+ extern "C" fn config_clks(514514+ dev: *mut bindings::device,515515+ opp_table: *mut bindings::opp_table,516516+ opp: *mut bindings::dev_pm_opp,517517+ _data: *mut kernel::ffi::c_void,518518+ scaling_down: bool,519519+ ) -> kernel::ffi::c_int {520520+ from_result(|| {521521+ // SAFETY: 'dev' is guaranteed by the C code to be valid.522522+ let dev = unsafe { Device::get_device(dev) };523523+ T::config_clks(524524+ &dev,525525+ // SAFETY: 'opp_table' is guaranteed by the C code to be valid.526526+ &unsafe { Table::from_raw_table(opp_table, &dev) },527527+ // SAFETY: 'opp' is guaranteed by the C code to be valid.528528+ unsafe { OPP::from_raw_opp(opp)? },529529+ scaling_down,530530+ )531531+ .map(|()| 0)532532+ })533533+ }534534+535535+ /// Config's regulator callback.536536+ ///537537+ /// SAFETY: Called from C. Inputs must be valid pointers.538538+ extern "C" fn config_regulators(539539+ dev: *mut bindings::device,540540+ old_opp: *mut bindings::dev_pm_opp,541541+ new_opp: *mut bindings::dev_pm_opp,542542+ regulators: *mut *mut bindings::regulator,543543+ count: kernel::ffi::c_uint,544544+ ) -> kernel::ffi::c_int {545545+ from_result(|| {546546+ // SAFETY: 'dev' is guaranteed by the C code to be valid.547547+ let dev = unsafe { Device::get_device(dev) };548548+ T::config_regulators(549549+ &dev,550550+ // SAFETY: 'old_opp' is guaranteed by the C code to be valid.551551+ unsafe { OPP::from_raw_opp(old_opp)? },552552+ // SAFETY: 'new_opp' is guaranteed by the C code to be valid.553553+ unsafe { OPP::from_raw_opp(new_opp)? },554554+ regulators,555555+ count,556556+ )557557+ .map(|()| 0)558558+ })559559+ }560560+}561561+562562+/// A reference-counted OPP table.563563+///564564+/// Rust abstraction for the C `struct opp_table`.565565+///566566+/// # Invariants567567+///568568+/// The pointer stored in `Self` is non-null and valid for the lifetime of the [`Table`].569569+///570570+/// Instances of this type are reference-counted.571571+///572572+/// ## Examples573573+///574574+/// The following example demonstrates how to get OPP [`Table`] for a [`Cpumask`] and set its575575+/// frequency.576576+///577577+/// ```578578+/// use kernel::clk::Hertz;579579+/// use kernel::cpumask::Cpumask;580580+/// use kernel::device::Device;581581+/// use kernel::error::Result;582582+/// use kernel::opp::Table;583583+/// use kernel::types::ARef;584584+///585585+/// fn get_table(dev: &ARef<Device>, mask: &mut Cpumask, freq: Hertz) -> Result<Table> {586586+/// let mut opp_table = Table::from_of_cpumask(dev, mask)?;587587+///588588+/// if opp_table.opp_count()? == 0 {589589+/// return Err(EINVAL);590590+/// }591591+///592592+/// pr_info!("Max transition latency is: {} ns\n", opp_table.max_transition_latency_ns());593593+/// pr_info!("Suspend frequency is: {:?}\n", opp_table.suspend_freq());594594+///595595+/// opp_table.set_rate(freq)?;596596+/// Ok(opp_table)597597+/// }598598+/// ```599599+pub struct Table {600600+ ptr: *mut bindings::opp_table,601601+ dev: ARef<Device>,602602+ #[allow(dead_code)]603603+ em: bool,604604+ #[allow(dead_code)]605605+ of: bool,606606+ cpus: Option<CpumaskVar>,607607+}608608+609609+/// SAFETY: It is okay to send ownership of [`Table`] across thread boundaries.610610+unsafe impl Send for Table {}611611+612612+/// SAFETY: It is okay to access [`Table`] through shared references from other threads because613613+/// we're either accessing properties that don't change or that are properly synchronised by C code.614614+unsafe impl Sync for Table {}615615+616616+impl Table {617617+ /// Creates a new reference-counted [`Table`] from a raw pointer.618618+ ///619619+ /// # Safety620620+ ///621621+ /// Callers must ensure that `ptr` is valid and non-null.622622+ unsafe fn from_raw_table(ptr: *mut bindings::opp_table, dev: &ARef<Device>) -> Self {623623+ // SAFETY: By the safety requirements, ptr is valid and its refcount will be incremented.624624+ //625625+ // INVARIANT: The reference-count is decremented when [`Table`] goes out of scope.626626+ unsafe { bindings::dev_pm_opp_get_opp_table_ref(ptr) };627627+628628+ Self {629629+ ptr,630630+ dev: dev.clone(),631631+ em: false,632632+ of: false,633633+ cpus: None,634634+ }635635+ }636636+637637+ /// Creates a new reference-counted [`Table`] instance for a [`Device`].638638+ pub fn from_dev(dev: &Device) -> Result<Self> {639639+ // SAFETY: The requirements are satisfied by the existence of the [`Device`] and its safety640640+ // requirements.641641+ //642642+ // INVARIANT: The reference-count is incremented by the C code and is decremented when643643+ // [`Table`] goes out of scope.644644+ let ptr = from_err_ptr(unsafe { bindings::dev_pm_opp_get_opp_table(dev.as_raw()) })?;645645+646646+ Ok(Self {647647+ ptr,648648+ dev: dev.into(),649649+ em: false,650650+ of: false,651651+ cpus: None,652652+ })653653+ }654654+655655+ /// Creates a new reference-counted [`Table`] instance for a [`Device`] based on device tree656656+ /// entries.657657+ #[cfg(CONFIG_OF)]658658+ pub fn from_of(dev: &ARef<Device>, index: i32) -> Result<Self> {659659+ // SAFETY: The requirements are satisfied by the existence of the [`Device`] and its safety660660+ // requirements.661661+ //662662+ // INVARIANT: The reference-count is incremented by the C code and is decremented when663663+ // [`Table`] goes out of scope.664664+ to_result(unsafe { bindings::dev_pm_opp_of_add_table_indexed(dev.as_raw(), index) })?;665665+666666+ // Get the newly created [`Table`].667667+ let mut table = Self::from_dev(dev)?;668668+ table.of = true;669669+670670+ Ok(table)671671+ }672672+673673+ /// Remove device tree based [`Table`].674674+ #[cfg(CONFIG_OF)]675675+ #[inline]676676+ fn remove_of(&self) {677677+ // SAFETY: The requirements are satisfied by the existence of the [`Device`] and its safety678678+ // requirements. We took the reference from [`from_of`] earlier, it is safe to drop the679679+ // same now.680680+ unsafe { bindings::dev_pm_opp_of_remove_table(self.dev.as_raw()) };681681+ }682682+683683+ /// Creates a new reference-counted [`Table`] instance for a [`Cpumask`] based on device tree684684+ /// entries.685685+ #[cfg(CONFIG_OF)]686686+ pub fn from_of_cpumask(dev: &Device, cpumask: &mut Cpumask) -> Result<Self> {687687+ // SAFETY: The cpumask is valid and the returned pointer will be owned by the [`Table`]688688+ // instance.689689+ //690690+ // INVARIANT: The reference-count is incremented by the C code and is decremented when691691+ // [`Table`] goes out of scope.692692+ to_result(unsafe { bindings::dev_pm_opp_of_cpumask_add_table(cpumask.as_raw()) })?;693693+694694+ // Fetch the newly created table.695695+ let mut table = Self::from_dev(dev)?;696696+ table.cpus = Some(CpumaskVar::try_clone(cpumask)?);697697+698698+ Ok(table)699699+ }700700+701701+ /// Remove device tree based [`Table`] for a [`Cpumask`].702702+ #[cfg(CONFIG_OF)]703703+ #[inline]704704+ fn remove_of_cpumask(&self, cpumask: &Cpumask) {705705+ // SAFETY: The cpumask is valid and we took the reference from [`from_of_cpumask`] earlier,706706+ // it is safe to drop the same now.707707+ unsafe { bindings::dev_pm_opp_of_cpumask_remove_table(cpumask.as_raw()) };708708+ }709709+710710+ /// Returns the number of [`OPP`]s in the [`Table`].711711+ pub fn opp_count(&self) -> Result<u32> {712712+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety713713+ // requirements.714714+ let ret = unsafe { bindings::dev_pm_opp_get_opp_count(self.dev.as_raw()) };715715+ if ret < 0 {716716+ Err(Error::from_errno(ret))717717+ } else {718718+ Ok(ret as u32)719719+ }720720+ }721721+722722+ /// Returns max clock latency (in nanoseconds) of the [`OPP`]s in the [`Table`].723723+ #[inline]724724+ pub fn max_clock_latency_ns(&self) -> usize {725725+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety726726+ // requirements.727727+ unsafe { bindings::dev_pm_opp_get_max_clock_latency(self.dev.as_raw()) }728728+ }729729+730730+ /// Returns max volt latency (in nanoseconds) of the [`OPP`]s in the [`Table`].731731+ #[inline]732732+ pub fn max_volt_latency_ns(&self) -> usize {733733+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety734734+ // requirements.735735+ unsafe { bindings::dev_pm_opp_get_max_volt_latency(self.dev.as_raw()) }736736+ }737737+738738+ /// Returns max transition latency (in nanoseconds) of the [`OPP`]s in the [`Table`].739739+ #[inline]740740+ pub fn max_transition_latency_ns(&self) -> usize {741741+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety742742+ // requirements.743743+ unsafe { bindings::dev_pm_opp_get_max_transition_latency(self.dev.as_raw()) }744744+ }745745+746746+ /// Returns the suspend [`OPP`]'s frequency.747747+ #[inline]748748+ pub fn suspend_freq(&self) -> Hertz {749749+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety750750+ // requirements.751751+ Hertz(unsafe { bindings::dev_pm_opp_get_suspend_opp_freq(self.dev.as_raw()) })752752+ }753753+754754+ /// Synchronizes regulators used by the [`Table`].755755+ #[inline]756756+ pub fn sync_regulators(&self) -> Result {757757+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety758758+ // requirements.759759+ to_result(unsafe { bindings::dev_pm_opp_sync_regulators(self.dev.as_raw()) })760760+ }761761+762762+ /// Gets sharing CPUs.763763+ #[inline]764764+ pub fn sharing_cpus(dev: &Device, cpumask: &mut Cpumask) -> Result {765765+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety766766+ // requirements.767767+ to_result(unsafe { bindings::dev_pm_opp_get_sharing_cpus(dev.as_raw(), cpumask.as_raw()) })768768+ }769769+770770+ /// Sets sharing CPUs.771771+ pub fn set_sharing_cpus(&mut self, cpumask: &mut Cpumask) -> Result {772772+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety773773+ // requirements.774774+ to_result(unsafe {775775+ bindings::dev_pm_opp_set_sharing_cpus(self.dev.as_raw(), cpumask.as_raw())776776+ })?;777777+778778+ if let Some(mask) = self.cpus.as_mut() {779779+ // Update the cpumask as this will be used while removing the table.780780+ cpumask.copy(mask);781781+ }782782+783783+ Ok(())784784+ }785785+786786+ /// Gets sharing CPUs from device tree.787787+ #[cfg(CONFIG_OF)]788788+ #[inline]789789+ pub fn of_sharing_cpus(dev: &Device, cpumask: &mut Cpumask) -> Result {790790+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety791791+ // requirements.792792+ to_result(unsafe {793793+ bindings::dev_pm_opp_of_get_sharing_cpus(dev.as_raw(), cpumask.as_raw())794794+ })795795+ }796796+797797+ /// Updates the voltage value for an [`OPP`].798798+ #[inline]799799+ pub fn adjust_voltage(800800+ &self,801801+ freq: Hertz,802802+ volt: MicroVolt,803803+ volt_min: MicroVolt,804804+ volt_max: MicroVolt,805805+ ) -> Result {806806+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety807807+ // requirements.808808+ to_result(unsafe {809809+ bindings::dev_pm_opp_adjust_voltage(810810+ self.dev.as_raw(),811811+ freq.into(),812812+ volt.into(),813813+ volt_min.into(),814814+ volt_max.into(),815815+ )816816+ })817817+ }818818+819819+ /// Creates [`FreqTable`] from [`Table`].820820+ #[cfg(CONFIG_CPU_FREQ)]821821+ #[inline]822822+ pub fn cpufreq_table(&mut self) -> Result<FreqTable> {823823+ FreqTable::new(self)824824+ }825825+826826+ /// Configures device with [`OPP`] matching the frequency value.827827+ #[inline]828828+ pub fn set_rate(&self, freq: Hertz) -> Result {829829+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety830830+ // requirements.831831+ to_result(unsafe { bindings::dev_pm_opp_set_rate(self.dev.as_raw(), freq.into()) })832832+ }833833+834834+ /// Configures device with [`OPP`].835835+ #[inline]836836+ pub fn set_opp(&self, opp: &OPP) -> Result {837837+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety838838+ // requirements.839839+ to_result(unsafe { bindings::dev_pm_opp_set_opp(self.dev.as_raw(), opp.as_raw()) })840840+ }841841+842842+ /// Finds [`OPP`] based on frequency.843843+ pub fn opp_from_freq(844844+ &self,845845+ freq: Hertz,846846+ available: Option<bool>,847847+ index: Option<u32>,848848+ stype: SearchType,849849+ ) -> Result<ARef<OPP>> {850850+ let raw_dev = self.dev.as_raw();851851+ let index = index.unwrap_or(0);852852+ let mut rate = freq.into();853853+854854+ let ptr = from_err_ptr(match stype {855855+ SearchType::Exact => {856856+ if let Some(available) = available {857857+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and858858+ // its safety requirements. The returned pointer will be owned by the new859859+ // [`OPP`] instance.860860+ unsafe {861861+ bindings::dev_pm_opp_find_freq_exact_indexed(862862+ raw_dev, rate, index, available,863863+ )864864+ }865865+ } else {866866+ return Err(EINVAL);867867+ }868868+ }869869+870870+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety871871+ // requirements. The returned pointer will be owned by the new [`OPP`] instance.872872+ SearchType::Ceil => unsafe {873873+ bindings::dev_pm_opp_find_freq_ceil_indexed(raw_dev, &mut rate, index)874874+ },875875+876876+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety877877+ // requirements. The returned pointer will be owned by the new [`OPP`] instance.878878+ SearchType::Floor => unsafe {879879+ bindings::dev_pm_opp_find_freq_floor_indexed(raw_dev, &mut rate, index)880880+ },881881+ })?;882882+883883+ // SAFETY: The `ptr` is guaranteed by the C code to be valid.884884+ unsafe { OPP::from_raw_opp_owned(ptr) }885885+ }886886+887887+ /// Finds [`OPP`] based on level.888888+ pub fn opp_from_level(&self, mut level: u32, stype: SearchType) -> Result<ARef<OPP>> {889889+ let raw_dev = self.dev.as_raw();890890+891891+ let ptr = from_err_ptr(match stype {892892+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety893893+ // requirements. The returned pointer will be owned by the new [`OPP`] instance.894894+ SearchType::Exact => unsafe { bindings::dev_pm_opp_find_level_exact(raw_dev, level) },895895+896896+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety897897+ // requirements. The returned pointer will be owned by the new [`OPP`] instance.898898+ SearchType::Ceil => unsafe {899899+ bindings::dev_pm_opp_find_level_ceil(raw_dev, &mut level)900900+ },901901+902902+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety903903+ // requirements. The returned pointer will be owned by the new [`OPP`] instance.904904+ SearchType::Floor => unsafe {905905+ bindings::dev_pm_opp_find_level_floor(raw_dev, &mut level)906906+ },907907+ })?;908908+909909+ // SAFETY: The `ptr` is guaranteed by the C code to be valid.910910+ unsafe { OPP::from_raw_opp_owned(ptr) }911911+ }912912+913913+ /// Finds [`OPP`] based on bandwidth.914914+ pub fn opp_from_bw(&self, mut bw: u32, index: i32, stype: SearchType) -> Result<ARef<OPP>> {915915+ let raw_dev = self.dev.as_raw();916916+917917+ let ptr = from_err_ptr(match stype {918918+ // The OPP core doesn't support this yet.919919+ SearchType::Exact => return Err(EINVAL),920920+921921+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety922922+ // requirements. The returned pointer will be owned by the new [`OPP`] instance.923923+ SearchType::Ceil => unsafe {924924+ bindings::dev_pm_opp_find_bw_ceil(raw_dev, &mut bw, index)925925+ },926926+927927+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety928928+ // requirements. The returned pointer will be owned by the new [`OPP`] instance.929929+ SearchType::Floor => unsafe {930930+ bindings::dev_pm_opp_find_bw_floor(raw_dev, &mut bw, index)931931+ },932932+ })?;933933+934934+ // SAFETY: The `ptr` is guaranteed by the C code to be valid.935935+ unsafe { OPP::from_raw_opp_owned(ptr) }936936+ }937937+938938+ /// Enables the [`OPP`].939939+ #[inline]940940+ pub fn enable_opp(&self, freq: Hertz) -> Result {941941+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety942942+ // requirements.943943+ to_result(unsafe { bindings::dev_pm_opp_enable(self.dev.as_raw(), freq.into()) })944944+ }945945+946946+ /// Disables the [`OPP`].947947+ #[inline]948948+ pub fn disable_opp(&self, freq: Hertz) -> Result {949949+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety950950+ // requirements.951951+ to_result(unsafe { bindings::dev_pm_opp_disable(self.dev.as_raw(), freq.into()) })952952+ }953953+954954+ /// Registers with the Energy model.955955+ #[cfg(CONFIG_OF)]956956+ pub fn of_register_em(&mut self, cpumask: &mut Cpumask) -> Result {957957+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety958958+ // requirements.959959+ to_result(unsafe {960960+ bindings::dev_pm_opp_of_register_em(self.dev.as_raw(), cpumask.as_raw())961961+ })?;962962+963963+ self.em = true;964964+ Ok(())965965+ }966966+967967+ /// Unregisters with the Energy model.968968+ #[cfg(all(CONFIG_OF, CONFIG_ENERGY_MODEL))]969969+ #[inline]970970+ fn of_unregister_em(&self) {971971+ // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety972972+ // requirements. We registered with the EM framework earlier, it is safe to unregister now.973973+ unsafe { bindings::em_dev_unregister_perf_domain(self.dev.as_raw()) };974974+ }975975+}976976+977977+impl Drop for Table {978978+ fn drop(&mut self) {979979+ // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe980980+ // to relinquish it now.981981+ unsafe { bindings::dev_pm_opp_put_opp_table(self.ptr) };982982+983983+ #[cfg(CONFIG_OF)]984984+ {985985+ #[cfg(CONFIG_ENERGY_MODEL)]986986+ if self.em {987987+ self.of_unregister_em();988988+ }989989+990990+ if self.of {991991+ self.remove_of();992992+ } else if let Some(cpumask) = self.cpus.take() {993993+ self.remove_of_cpumask(&cpumask);994994+ }995995+ }996996+ }997997+}998998+999999+/// A reference-counted Operating performance point (OPP).10001000+///10011001+/// Rust abstraction for the C `struct dev_pm_opp`.10021002+///10031003+/// # Invariants10041004+///10051005+/// The pointer stored in `Self` is non-null and valid for the lifetime of the [`OPP`].10061006+///10071007+/// Instances of this type are reference-counted. The reference count is incremented by the10081008+/// `dev_pm_opp_get` function and decremented by `dev_pm_opp_put`. The Rust type `ARef<OPP>`10091009+/// represents a pointer that owns a reference count on the [`OPP`].10101010+///10111011+/// A reference to the [`OPP`], &[`OPP`], isn't refcounted by the Rust code.10121012+///10131013+/// ## Examples10141014+///10151015+/// The following example demonstrates how to get [`OPP`] corresponding to a frequency value and10161016+/// configure the device with it.10171017+///10181018+/// ```10191019+/// use kernel::clk::Hertz;10201020+/// use kernel::error::Result;10211021+/// use kernel::opp::{SearchType, Table};10221022+///10231023+/// fn configure_opp(table: &Table, freq: Hertz) -> Result {10241024+/// let opp = table.opp_from_freq(freq, Some(true), None, SearchType::Exact)?;10251025+///10261026+/// if opp.freq(None) != freq {10271027+/// return Err(EINVAL);10281028+/// }10291029+///10301030+/// table.set_opp(&opp)10311031+/// }10321032+/// ```10331033+#[repr(transparent)]10341034+pub struct OPP(Opaque<bindings::dev_pm_opp>);10351035+10361036+/// SAFETY: It is okay to send the ownership of [`OPP`] across thread boundaries.10371037+unsafe impl Send for OPP {}10381038+10391039+/// SAFETY: It is okay to access [`OPP`] through shared references from other threads because we're10401040+/// either accessing properties that don't change or that are properly synchronised by C code.10411041+unsafe impl Sync for OPP {}10421042+10431043+/// SAFETY: The type invariants guarantee that [`OPP`] is always refcounted.10441044+unsafe impl AlwaysRefCounted for OPP {10451045+ fn inc_ref(&self) {10461046+ // SAFETY: The existence of a shared reference means that the refcount is nonzero.10471047+ unsafe { bindings::dev_pm_opp_get(self.0.get()) };10481048+ }10491049+10501050+ unsafe fn dec_ref(obj: ptr::NonNull<Self>) {10511051+ // SAFETY: The safety requirements guarantee that the refcount is nonzero.10521052+ unsafe { bindings::dev_pm_opp_put(obj.cast().as_ptr()) }10531053+ }10541054+}10551055+10561056+impl OPP {10571057+ /// Creates an owned reference to a [`OPP`] from a valid pointer.10581058+ ///10591059+ /// The refcount is incremented by the C code and will be decremented by `dec_ref` when the10601060+ /// [`ARef`] object is dropped.10611061+ ///10621062+ /// # Safety10631063+ ///10641064+ /// The caller must ensure that `ptr` is valid and the refcount of the [`OPP`] is incremented.10651065+ /// The caller must also ensure that it doesn't explicitly drop the refcount of the [`OPP`], as10661066+ /// the returned [`ARef`] object takes over the refcount increment on the underlying object and10671067+ /// the same will be dropped along with it.10681068+ pub unsafe fn from_raw_opp_owned(ptr: *mut bindings::dev_pm_opp) -> Result<ARef<Self>> {10691069+ let ptr = ptr::NonNull::new(ptr).ok_or(ENODEV)?;10701070+10711071+ // SAFETY: The safety requirements guarantee the validity of the pointer.10721072+ //10731073+ // INVARIANT: The reference-count is decremented when [`OPP`] goes out of scope.10741074+ Ok(unsafe { ARef::from_raw(ptr.cast()) })10751075+ }10761076+10771077+ /// Creates a reference to a [`OPP`] from a valid pointer.10781078+ ///10791079+ /// The refcount is not updated by the Rust API unless the returned reference is converted to10801080+ /// an [`ARef`] object.10811081+ ///10821082+ /// # Safety10831083+ ///10841084+ /// The caller must ensure that `ptr` is valid and remains valid for the duration of `'a`.10851085+ #[inline]10861086+ pub unsafe fn from_raw_opp<'a>(ptr: *mut bindings::dev_pm_opp) -> Result<&'a Self> {10871087+ // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the10881088+ // duration of 'a. The cast is okay because [`OPP`] is `repr(transparent)`.10891089+ Ok(unsafe { &*ptr.cast() })10901090+ }10911091+10921092+ #[inline]10931093+ fn as_raw(&self) -> *mut bindings::dev_pm_opp {10941094+ self.0.get()10951095+ }10961096+10971097+ /// Returns the frequency of an [`OPP`].10981098+ pub fn freq(&self, index: Option<u32>) -> Hertz {10991099+ let index = index.unwrap_or(0);11001100+11011101+ // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to11021102+ // use it.11031103+ Hertz(unsafe { bindings::dev_pm_opp_get_freq_indexed(self.as_raw(), index) })11041104+ }11051105+11061106+ /// Returns the voltage of an [`OPP`].11071107+ #[inline]11081108+ pub fn voltage(&self) -> MicroVolt {11091109+ // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to11101110+ // use it.11111111+ MicroVolt(unsafe { bindings::dev_pm_opp_get_voltage(self.as_raw()) })11121112+ }11131113+11141114+ /// Returns the level of an [`OPP`].11151115+ #[inline]11161116+ pub fn level(&self) -> u32 {11171117+ // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to11181118+ // use it.11191119+ unsafe { bindings::dev_pm_opp_get_level(self.as_raw()) }11201120+ }11211121+11221122+ /// Returns the power of an [`OPP`].11231123+ #[inline]11241124+ pub fn power(&self) -> MicroWatt {11251125+ // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to11261126+ // use it.11271127+ MicroWatt(unsafe { bindings::dev_pm_opp_get_power(self.as_raw()) })11281128+ }11291129+11301130+ /// Returns the required pstate of an [`OPP`].11311131+ #[inline]11321132+ pub fn required_pstate(&self, index: u32) -> u32 {11331133+ // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to11341134+ // use it.11351135+ unsafe { bindings::dev_pm_opp_get_required_pstate(self.as_raw(), index) }11361136+ }11371137+11381138+ /// Returns true if the [`OPP`] is turbo.11391139+ #[inline]11401140+ pub fn is_turbo(&self) -> bool {11411141+ // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to11421142+ // use it.11431143+ unsafe { bindings::dev_pm_opp_is_turbo(self.as_raw()) }11441144+ }11451145+}
+11-22
rust/kernel/pci.rs
···360360 }361361}362362363363-impl Device {363363+impl<Ctx: device::DeviceContext> Device<Ctx> {364364 fn as_raw(&self) -> *mut bindings::pci_dev {365365 self.0.get()366366 }367367+}367368369369+impl Device {368370 /// Returns the PCI vendor ID.369371 pub fn vendor_id(&self) -> u16 {370372 // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`.···390388 // - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`.391389 Ok(unsafe { bindings::pci_resource_len(self.as_raw(), bar.try_into()?) })392390 }391391+}393392393393+impl Device<device::Bound> {394394 /// Mapps an entire PCI-BAR after performing a region-request on it. I/O operation bound checks395395 /// can be performed on compile time for offsets (plus the requested type size) < SIZE.396396 pub fn iomap_region_sized<const SIZE: usize>(···426422 }427423}428424429429-impl Deref for Device<device::Core> {430430- type Target = Device;431431-432432- fn deref(&self) -> &Self::Target {433433- let ptr: *const Self = self;434434-435435- // CAST: `Device<Ctx>` is a transparent wrapper of `Opaque<bindings::pci_dev>`.436436- let ptr = ptr.cast::<Device>();437437-438438- // SAFETY: `ptr` was derived from `&self`.439439- unsafe { &*ptr }440440- }441441-}442442-443443-impl From<&Device<device::Core>> for ARef<Device> {444444- fn from(dev: &Device<device::Core>) -> Self {445445- (&**dev).into()446446- }447447-}425425+// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic426426+// argument.427427+kernel::impl_device_context_deref!(unsafe { Device });428428+kernel::impl_device_context_into_aref!(Device);448429449430// SAFETY: Instances of `Device` are always reference-counted.450431unsafe impl crate::types::AlwaysRefCounted for Device {···444455 }445456}446457447447-impl AsRef<device::Device> for Device {448448- fn as_ref(&self) -> &device::Device {458458+impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {459459+ fn as_ref(&self) -> &device::Device<Ctx> {449460 // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid450461 // `struct pci_dev`.451462 let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) };
+8-24
rust/kernel/platform.rs
···1010 of,1111 prelude::*,1212 str::CStr,1313- types::{ARef, ForeignOwnable, Opaque},1313+ types::{ForeignOwnable, Opaque},1414 ThisModule,1515};16161717use core::{1818 marker::PhantomData,1919- ops::Deref,2019 ptr::{addr_of_mut, NonNull},2120};2221···183184 PhantomData<Ctx>,184185);185186186186-impl Device {187187+impl<Ctx: device::DeviceContext> Device<Ctx> {187188 fn as_raw(&self) -> *mut bindings::platform_device {188189 self.0.get()189190 }190191}191192192192-impl Deref for Device<device::Core> {193193- type Target = Device;194194-195195- fn deref(&self) -> &Self::Target {196196- let ptr: *const Self = self;197197-198198- // CAST: `Device<Ctx>` is a transparent wrapper of `Opaque<bindings::platform_device>`.199199- let ptr = ptr.cast::<Device>();200200-201201- // SAFETY: `ptr` was derived from `&self`.202202- unsafe { &*ptr }203203- }204204-}205205-206206-impl From<&Device<device::Core>> for ARef<Device> {207207- fn from(dev: &Device<device::Core>) -> Self {208208- (&**dev).into()209209- }210210-}193193+// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic194194+// argument.195195+kernel::impl_device_context_deref!(unsafe { Device });196196+kernel::impl_device_context_into_aref!(Device);211197212198// SAFETY: Instances of `Device` are always reference-counted.213199unsafe impl crate::types::AlwaysRefCounted for Device {···207223 }208224}209225210210-impl AsRef<device::Device> for Device {211211- fn as_ref(&self) -> &device::Device {226226+impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {227227+ fn as_ref(&self) -> &device::Device<Ctx> {212228 // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid213229 // `struct platform_device`.214230 let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) };
+12-8
rust/macros/module.rs
···185185186186 let info = ModuleInfo::parse(&mut it);187187188188- let mut modinfo = ModInfoBuilder::new(info.name.as_ref());188188+ // Rust does not allow hyphens in identifiers, use underscore instead.189189+ let ident = info.name.replace('-', "_");190190+ let mut modinfo = ModInfoBuilder::new(ident.as_ref());189191 if let Some(author) = info.author {190192 modinfo.emit("author", &author);191193 }···312310 #[doc(hidden)]313311 #[link_section = \"{initcall_section}\"]314312 #[used]315315- pub static __{name}_initcall: extern \"C\" fn() -> kernel::ffi::c_int = __{name}_init;313313+ pub static __{ident}_initcall: extern \"C\" fn() ->314314+ kernel::ffi::c_int = __{ident}_init;316315317316 #[cfg(not(MODULE))]318317 #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]319318 core::arch::global_asm!(320319 r#\".section \"{initcall_section}\", \"a\"321321- __{name}_initcall:322322- .long __{name}_init - .320320+ __{ident}_initcall:321321+ .long __{ident}_init - .323322 .previous324323 \"#325324 );···328325 #[cfg(not(MODULE))]329326 #[doc(hidden)]330327 #[no_mangle]331331- pub extern \"C\" fn __{name}_init() -> kernel::ffi::c_int {{328328+ pub extern \"C\" fn __{ident}_init() -> kernel::ffi::c_int {{332329 // SAFETY: This function is inaccessible to the outside due to the double333330 // module wrapping it. It is called exactly once by the C side via its334331 // placement above in the initcall section.···338335 #[cfg(not(MODULE))]339336 #[doc(hidden)]340337 #[no_mangle]341341- pub extern \"C\" fn __{name}_exit() {{338338+ pub extern \"C\" fn __{ident}_exit() {{342339 // SAFETY:343340 // - This function is inaccessible to the outside due to the double344341 // module wrapping it. It is called exactly once by the C side via its345342 // unique name,346346- // - furthermore it is only called after `__{name}_init` has returned `0`347347- // (which delegates to `__init`).343343+ // - furthermore it is only called after `__{ident}_init` has344344+ // returned `0` (which delegates to `__init`).348345 unsafe {{ __exit() }}349346 }}350347···384381 ",385382 type_ = info.type_,386383 name = info.name,384384+ ident = ident,387385 modinfo = modinfo.buffer,388386 initcall_section = ".initcall6.init"389387 )