X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_power%2Fpower_acpi_cpufreq.c;h=84a9d75207df9033ebcfe749467a7b2f06c90a08;hb=841dfdd06d37cb00a49a56a180c287efc021a842;hp=cd5978d5b312c831ec55a4bb2a5efc337e9e12ef;hpb=185109906b809007a15db1d018100dc74ec37447;p=dpdk.git diff --git a/lib/librte_power/power_acpi_cpufreq.c b/lib/librte_power/power_acpi_cpufreq.c index cd5978d5b3..84a9d75207 100644 --- a/lib/librte_power/power_acpi_cpufreq.c +++ b/lib/librte_power/power_acpi_cpufreq.c @@ -13,7 +13,8 @@ #include #include -#include +#include +#include #include "power_acpi_cpufreq.h" #include "power_common.h" @@ -28,7 +29,7 @@ #define FOPEN_OR_ERR_RET(f, retval) do { \ if ((f) == NULL) { \ - RTE_LOG(ERR, POWER, "File not openned\n"); \ + RTE_LOG(ERR, POWER, "File not opened\n"); \ return retval; \ } \ } while (0) @@ -57,6 +58,7 @@ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_available_frequencies" #define POWER_SYSFILE_SETSPEED \ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_setspeed" +#define POWER_ACPI_DRIVER "acpi-cpufreq" /* * MSR related @@ -83,7 +85,7 @@ struct rte_power_info { FILE *f; /**< FD of scaling_setspeed */ char governor_ori[32]; /**< Original governor name */ uint32_t curr_idx; /**< Freq index in freqs array */ - volatile uint32_t state; /**< Power in use state */ + uint32_t state; /**< Power in use state */ uint16_t turbo_available; /**< Turbo Boost available */ uint16_t turbo_enable; /**< Turbo Boost enable/disable */ } __rte_cache_aligned; @@ -107,7 +109,7 @@ set_freq_internal(struct rte_power_info *pi, uint32_t idx) if (idx == pi->curr_idx) return 0; - POWER_DEBUG_TRACE("Freqency[%u] %u to be set for lcore %u\n", + POWER_DEBUG_TRACE("Frequency[%u] %u to be set for lcore %u\n", idx, pi->freqs[idx], pi->lcore_id); if (fseek(pi->f, 0, SEEK_SET) < 0) { RTE_LOG(ERR, POWER, "Fail to set file position indicator to 0 " @@ -147,6 +149,8 @@ power_set_governor_userspace(struct rte_power_info *pi) s = fgets(buf, sizeof(buf), f); FOPS_OR_NULL_GOTO(s, out); + /* Strip off terminating '\n' */ + strtok(buf, "\n"); /* Check if current governor is userspace */ if (strncmp(buf, POWER_GOVERNOR_USERSPACE, @@ -157,7 +161,7 @@ power_set_governor_userspace(struct rte_power_info *pi) goto out; } /* Save the original governor */ - snprintf(pi->governor_ori, sizeof(pi->governor_ori), "%s", buf); + strlcpy(pi->governor_ori, buf, sizeof(pi->governor_ori)); /* Write 'userspace' to the governor */ val = fseek(f, 0, SEEK_SET); @@ -166,6 +170,10 @@ power_set_governor_userspace(struct rte_power_info *pi) val = fputs(POWER_GOVERNOR_USERSPACE, f); FOPS_OR_ERR_GOTO(val, out); + /* We need to flush to see if the fputs succeeds */ + val = fflush(f); + FOPS_OR_ERR_GOTO(val, out); + ret = 0; RTE_LOG(INFO, POWER, "Power management governor of lcore %u has been " "set to user space successfully\n", pi->lcore_id); @@ -281,10 +289,17 @@ out: return -1; } +int +power_acpi_cpufreq_check_supported(void) +{ + return cpufreq_check_scaling_driver(POWER_ACPI_DRIVER); +} + int power_acpi_cpufreq_init(unsigned int lcore_id) { struct rte_power_info *pi; + uint32_t exp_state; if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Lcore id %u can not exceeds %u\n", @@ -293,8 +308,16 @@ power_acpi_cpufreq_init(unsigned int lcore_id) } pi = &lcore_power_info[lcore_id]; - if (rte_atomic32_cmpset(&(pi->state), POWER_IDLE, POWER_ONGOING) - == 0) { + exp_state = POWER_IDLE; + /* The power in use state works as a guard variable between + * the CPU frequency control initialization and exit process. + * The ACQUIRE memory ordering here pairs with the RELEASE + * ordering below as lock to make sure the frequency operations + * in the critical section are done under the correct state. + */ + if (!__atomic_compare_exchange_n(&(pi->state), &exp_state, + POWER_ONGOING, 0, + __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) { RTE_LOG(INFO, POWER, "Power management of lcore %u is " "in use\n", lcore_id); return -1; @@ -331,12 +354,16 @@ power_acpi_cpufreq_init(unsigned int lcore_id) RTE_LOG(INFO, POWER, "Initialized successfully for lcore %u " "power management\n", lcore_id); - rte_atomic32_cmpset(&(pi->state), POWER_ONGOING, POWER_USED); + exp_state = POWER_ONGOING; + __atomic_compare_exchange_n(&(pi->state), &exp_state, POWER_USED, + 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED); return 0; fail: - rte_atomic32_cmpset(&(pi->state), POWER_ONGOING, POWER_UNKNOWN); + exp_state = POWER_ONGOING; + __atomic_compare_exchange_n(&(pi->state), &exp_state, POWER_UNKNOWN, + 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED); return -1; } @@ -393,6 +420,7 @@ int power_acpi_cpufreq_exit(unsigned int lcore_id) { struct rte_power_info *pi; + uint32_t exp_state; if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Lcore id %u can not exceeds %u\n", @@ -400,8 +428,16 @@ power_acpi_cpufreq_exit(unsigned int lcore_id) return -1; } pi = &lcore_power_info[lcore_id]; - if (rte_atomic32_cmpset(&(pi->state), POWER_USED, POWER_ONGOING) - == 0) { + exp_state = POWER_USED; + /* The power in use state works as a guard variable between + * the CPU frequency control initialization and exit process. + * The ACQUIRE memory ordering here pairs with the RELEASE + * ordering below as lock to make sure the frequency operations + * in the critical section are done under the correct state. + */ + if (!__atomic_compare_exchange_n(&(pi->state), &exp_state, + POWER_ONGOING, 0, + __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) { RTE_LOG(INFO, POWER, "Power management of lcore %u is " "not used\n", lcore_id); return -1; @@ -421,12 +457,16 @@ power_acpi_cpufreq_exit(unsigned int lcore_id) RTE_LOG(INFO, POWER, "Power management of lcore %u has exited from " "'userspace' mode and been set back to the " "original\n", lcore_id); - rte_atomic32_cmpset(&(pi->state), POWER_ONGOING, POWER_IDLE); + exp_state = POWER_ONGOING; + __atomic_compare_exchange_n(&(pi->state), &exp_state, POWER_IDLE, + 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED); return 0; fail: - rte_atomic32_cmpset(&(pi->state), POWER_ONGOING, POWER_UNKNOWN); + exp_state = POWER_ONGOING; + __atomic_compare_exchange_n(&(pi->state), &exp_state, POWER_UNKNOWN, + 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED); return -1; } @@ -436,8 +476,13 @@ power_acpi_cpufreq_freqs(unsigned int lcore_id, uint32_t *freqs, uint32_t num) { struct rte_power_info *pi; - if (lcore_id >= RTE_MAX_LCORE || !freqs) { - RTE_LOG(ERR, POWER, "Invalid input parameter\n"); + if (lcore_id >= RTE_MAX_LCORE) { + RTE_LOG(ERR, POWER, "Invalid lcore ID\n"); + return 0; + } + + if (freqs == NULL) { + RTE_LOG(ERR, POWER, "NULL buffer supplied\n"); return 0; } @@ -502,7 +547,8 @@ power_acpi_cpufreq_freq_up(unsigned int lcore_id) } pi = &lcore_power_info[lcore_id]; - if (pi->curr_idx == 0) + if (pi->curr_idx == 0 || + (pi->curr_idx == 1 && pi->turbo_available && !pi->turbo_enable)) return 0; /* Frequencies in the array are from high to low. */