cregit-Linux how code gets into the kernel

Release 4.11 drivers/cpuidle/cpuidle-cps.c

Directory: drivers/cpuidle
/*
 * Copyright (C) 2014 Imagination Technologies
 * Author: Paul Burton <paul.burton@imgtec.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#include <linux/cpu_pm.h>
#include <linux/cpuidle.h>
#include <linux/init.h>

#include <asm/idle.h>
#include <asm/pm-cps.h>

/* Enumeration of the various idle states this driver may enter */

enum cps_idle_state {
	
STATE_WAIT = 0,		/* MIPS wait instruction, coherent */
	
STATE_NC_WAIT,		/* MIPS wait instruction, non-coherent */
	
STATE_CLOCK_GATED,	/* Core clock gated */
	
STATE_POWER_GATED,	/* Core power gated */
	
STATE_COUNT
};


static int cps_nc_enter(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { enum cps_pm_state pm_state; int err; /* * At least one core must remain powered up & clocked in order for the * system to have any hope of functioning. * * TODO: don't treat core 0 specially, just prevent the final core * TODO: remap interrupt affinity temporarily */ if (!cpu_data[dev->cpu].core && (index > STATE_NC_WAIT)) index = STATE_NC_WAIT; /* Select the appropriate cps_pm_state */ switch (index) { case STATE_NC_WAIT: pm_state = CPS_PM_NC_WAIT; break; case STATE_CLOCK_GATED: pm_state = CPS_PM_CLOCK_GATED; break; case STATE_POWER_GATED: pm_state = CPS_PM_POWER_GATED; break; default: BUG(); return -EINVAL; } /* Notify listeners the CPU is about to power down */ if ((pm_state == CPS_PM_POWER_GATED) && cpu_pm_enter()) return -EINTR; /* Enter that state */ err = cps_pm_enter_state(pm_state); /* Notify listeners the CPU is back up */ if (pm_state == CPS_PM_POWER_GATED) cpu_pm_exit(); return err ?: index; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Burton128100.00%1100.00%
Total128100.00%1100.00%

static struct cpuidle_driver cps_driver = { .name = "cpc_cpuidle", .owner = THIS_MODULE, .states = { [STATE_WAIT] = MIPS_CPUIDLE_WAIT_STATE, [STATE_NC_WAIT] = { .enter = cps_nc_enter, .exit_latency = 200, .target_residency = 450, .name = "nc-wait", .desc = "non-coherent MIPS wait", }, [STATE_CLOCK_GATED] = { .enter = cps_nc_enter, .exit_latency = 300, .target_residency = 700, .flags = CPUIDLE_FLAG_TIMER_STOP, .name = "clock-gated", .desc = "core clock gated", }, [STATE_POWER_GATED] = { .enter = cps_nc_enter, .exit_latency = 600, .target_residency = 1000, .flags = CPUIDLE_FLAG_TIMER_STOP, .name = "power-gated", .desc = "core power gated", }, }, .state_count = STATE_COUNT, .safe_state_index = 0, };
static void __init cps_cpuidle_unregister(void) { int cpu; struct cpuidle_device *device; for_each_possible_cpu(cpu) { device = &per_cpu(cpuidle_dev, cpu); cpuidle_unregister_device(device); } cpuidle_unregister_driver(&cps_driver); }

Contributors

PersonTokensPropCommitsCommitProp
Paul Burton44100.00%1100.00%
Total44100.00%1100.00%


static int __init cps_cpuidle_init(void) { int err, cpu, core, i; struct cpuidle_device *device; /* Detect supported states */ if (!cps_pm_support_state(CPS_PM_POWER_GATED)) cps_driver.state_count = STATE_CLOCK_GATED + 1; if (!cps_pm_support_state(CPS_PM_CLOCK_GATED)) cps_driver.state_count = STATE_NC_WAIT + 1; if (!cps_pm_support_state(CPS_PM_NC_WAIT)) cps_driver.state_count = STATE_WAIT + 1; /* Inform the user if some states are unavailable */ if (cps_driver.state_count < STATE_COUNT) { pr_info("cpuidle-cps: limited to "); switch (cps_driver.state_count - 1) { case STATE_WAIT: pr_cont("coherent wait\n"); break; case STATE_NC_WAIT: pr_cont("non-coherent wait\n"); break; case STATE_CLOCK_GATED: pr_cont("clock gating\n"); break; } } /* * Set the coupled flag on the appropriate states if this system * requires it. */ if (coupled_coherence) for (i = STATE_NC_WAIT; i < cps_driver.state_count; i++) cps_driver.states[i].flags |= CPUIDLE_FLAG_COUPLED; err = cpuidle_register_driver(&cps_driver); if (err) { pr_err("Failed to register CPS cpuidle driver\n"); return err; } for_each_possible_cpu(cpu) { core = cpu_data[cpu].core; device = &per_cpu(cpuidle_dev, cpu); device->cpu = cpu; #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED cpumask_copy(&device->coupled_cpus, &cpu_sibling_map[cpu]); #endif err = cpuidle_register_device(device); if (err) { pr_err("Failed to register CPU%d cpuidle device\n", cpu); goto err_out; } } return 0; err_out: cps_cpuidle_unregister(); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Burton26199.62%150.00%
Matt Redfearn10.38%150.00%
Total262100.00%2100.00%

device_initcall(cps_cpuidle_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
Paul Burton61699.84%150.00%
Matt Redfearn10.16%150.00%
Total617100.00%2100.00%
Directory: drivers/cpuidle
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.