@@ -12,6 +12,7 @@
#include <rte_memcpy.h>
+#include "rte_power_pmd_mgmt.h"
#include "power_pstate_cpufreq.h"
#include "power_common.h"
@@ -354,6 +355,7 @@ power_get_available_freqs(struct pstate_power_info *pi)
FILE *f_min = NULL, *f_max = NULL;
int ret = -1;
uint32_t sys_min_freq = 0, sys_max_freq = 0, base_max_freq = 0;
+ int config_min_freq, config_max_freq;
uint32_t i, num_freqs = 0;
/* open all files */
@@ -388,6 +390,18 @@ power_get_available_freqs(struct pstate_power_info *pi)
goto out;
}
+ /* check for config set by user or application to limit frequency range */
+ config_min_freq = rte_power_pmd_mgmt_get_scaling_freq_min(pi->lcore_id);
+ if (config_min_freq < 0)
+ goto out;
+ config_max_freq = rte_power_pmd_mgmt_get_scaling_freq_max(pi->lcore_id);
+ if (config_max_freq < 0)
+ goto out;
+
+ sys_min_freq = RTE_MAX(sys_min_freq, (uint32_t)config_min_freq);
+ if (config_max_freq > 0) /* Only use config_max_freq if a value has been set */
+ sys_max_freq = RTE_MIN(sys_max_freq, (uint32_t)config_max_freq);
+
if (sys_max_freq < sys_min_freq)
goto out;
@@ -411,8 +425,8 @@ power_get_available_freqs(struct pstate_power_info *pi)
/* If turbo is available then there is one extra freq bucket
* to store the sys max freq which value is base_max +1
*/
- num_freqs = (base_max_freq - sys_min_freq) / BUS_FREQ + 1 +
- pi->turbo_available;
+ num_freqs = (RTE_MIN(base_max_freq, sys_max_freq) - sys_min_freq) / BUS_FREQ
+ + 1 + pi->turbo_available;
if (num_freqs >= RTE_MAX_LCORE_FREQS) {
RTE_LOG(ERR, POWER, "Too many available frequencies: %d\n",
num_freqs);
@@ -427,10 +441,10 @@ power_get_available_freqs(struct pstate_power_info *pi)
*/
for (i = 0, pi->nb_freqs = 0; i < num_freqs; i++) {
if ((i == 0) && pi->turbo_available)
- pi->freqs[pi->nb_freqs++] = base_max_freq + 1;
+ pi->freqs[pi->nb_freqs++] = RTE_MIN(base_max_freq, sys_max_freq) + 1;
else
- pi->freqs[pi->nb_freqs++] =
- base_max_freq - (i - pi->turbo_available) * BUS_FREQ;
+ pi->freqs[pi->nb_freqs++] = RTE_MIN(base_max_freq, sys_max_freq) -
+ (i - pi->turbo_available) * BUS_FREQ;
}
ret = 0;
@@ -10,9 +10,12 @@
#include <rte_power_intrinsics.h>
#include "rte_power_pmd_mgmt.h"
+#include "power_common.h"
unsigned int emptypoll_max;
unsigned int pause_duration;
+unsigned int scale_freq_min[RTE_MAX_LCORE];
+unsigned int scale_freq_max[RTE_MAX_LCORE];
/* store some internal state */
static struct pmd_conf_data {
@@ -693,8 +696,77 @@ rte_power_pmd_mgmt_get_pause_duration(void)
return pause_duration;
}
+int
+rte_power_pmd_mgmt_set_scaling_freq_min(unsigned int lcore, unsigned int min)
+{
+ if (lcore >= RTE_MAX_LCORE) {
+ RTE_LOG(ERR, POWER, "Invalid lcore ID: %u\n", lcore);
+ return -EINVAL;
+ }
+
+ if (min > scale_freq_max[lcore]) {
+ RTE_LOG(ERR, POWER, "Invalid min frequency: Cannot be greater than max frequency");
+ return -EINVAL;
+ }
+ scale_freq_min[lcore] = min;
+
+ return 0;
+}
+
+int
+rte_power_pmd_mgmt_set_scaling_freq_max(unsigned int lcore, unsigned int max)
+{
+ if (lcore >= RTE_MAX_LCORE) {
+ RTE_LOG(ERR, POWER, "Invalid lcore ID: %u\n", lcore);
+ return -EINVAL;
+ }
+
+ /* Zero means 'not set'. Use UINT32_MAX to enable RTE_MIN/MAX macro use when scaling. */
+ if (max == 0)
+ max = UINT32_MAX;
+ if (max < scale_freq_min[lcore]) {
+ RTE_LOG(ERR, POWER, "Invalid max frequency: Cannot be less than min frequency");
+ return -EINVAL;
+ }
+
+ scale_freq_max[lcore] = max;
+
+ return 0;
+}
+
+int
+rte_power_pmd_mgmt_get_scaling_freq_min(unsigned int lcore)
+{
+ if (lcore >= RTE_MAX_LCORE) {
+ RTE_LOG(ERR, POWER, "Invalid lcore ID: %u\n", lcore);
+ return -EINVAL;
+ }
+
+ if (scale_freq_max[lcore] == 0)
+ RTE_LOG(DEBUG, POWER, "Scaling freq min config not set. Using sysfs min freq.\n");
+
+ return scale_freq_min[lcore];
+}
+
+int
+rte_power_pmd_mgmt_get_scaling_freq_max(unsigned int lcore)
+{
+ if (lcore >= RTE_MAX_LCORE) {
+ RTE_LOG(ERR, POWER, "Invalid lcore ID: %u\n", lcore);
+ return -EINVAL;
+ }
+
+ if (scale_freq_max[lcore] == UINT32_MAX) {
+ RTE_LOG(DEBUG, POWER, "Scaling freq max config not set. Using sysfs max freq.\n");
+ return 0;
+ }
+
+ return scale_freq_max[lcore];
+}
+
RTE_INIT(rte_power_ethdev_pmgmt_init) {
size_t i;
+ int j;
/* initialize all tailqs */
for (i = 0; i < RTE_DIM(lcore_cfgs); i++) {
@@ -705,4 +777,9 @@ RTE_INIT(rte_power_ethdev_pmgmt_init) {
/* initialize config defaults */
emptypoll_max = 512;
pause_duration = 1;
+ /* scaling defaults out of range to ensure not used unless set by user or app */
+ for (j = 0; j < RTE_MAX_LCORE; j++) {
+ scale_freq_min[j] = 0;
+ scale_freq_max[j] = UINT32_MAX;
+ }
}
@@ -148,6 +148,87 @@ __rte_experimental
unsigned int
rte_power_pmd_mgmt_get_pause_duration(void);
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice.
+ *
+ * Set the min frequency to be used for frequency scaling or zero to use defaults.
+ *
+ * @note Supported by: Pstate mode.
+ *
+ * @param lcore
+ * The ID of the lcore to set the min frequency for.
+ * @param min
+ * The value, in KiloHertz, to set the minimum frequency to.
+ * @return
+ * 0 on success
+ * <0 on error
+ */
+__rte_experimental
+int
+rte_power_pmd_mgmt_set_scaling_freq_min(unsigned int lcore, unsigned int min);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice.
+ *
+ * Set the max frequency to be used for frequency scaling or zero to use defaults.
+ *
+ * @note Supported by: Pstate mode.
+ *
+ * @param lcore
+ * The ID of the lcore to set the max frequency for.
+ * @param max
+ * The value, in KiloHertz, to set the maximum frequency to.
+ * If 'max' is 0, it is considered 'not set'.
+ * @return
+ * 0 on success
+ * <0 on error
+ */
+__rte_experimental
+int
+rte_power_pmd_mgmt_set_scaling_freq_max(unsigned int lcore, unsigned int max);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice.
+ *
+ * Get the current configured min frequency used for frequency scaling.
+ *
+ * @note Supported by: Pstate mode.
+ *
+ * @param lcore
+ * The ID of the lcore to get the min frequency for.
+ * @return
+ * 0 if no value has been configured via the 'set' API.
+ * >0 if a minimum frequency has been configured. Value is the minimum frequency
+ * , in KiloHertz, used for frequency scaling.
+ * <0 on error
+ */
+__rte_experimental
+int
+rte_power_pmd_mgmt_get_scaling_freq_min(unsigned int lcore);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice.
+ *
+ * Get the current configured max frequency used for frequency scaling.
+ *
+ * @note Supported by: Pstate mode.
+ *
+ * @param lcore
+ * The ID of the lcore to get the max frequency for.
+ * @return
+ * 0 if no value has been configured via the 'set' API.
+ * >0 if a maximum frequency has been configured. Value is the maximum frequency
+ * , in KiloHertz, used for frequency scaling.
+ * <0 on error
+ */
+__rte_experimental
+int
+rte_power_pmd_mgmt_get_scaling_freq_max(unsigned int lcore);
+
#ifdef __cplusplus
}
#endif
@@ -42,6 +42,10 @@ EXPERIMENTAL {
# added in 22.07
rte_power_pmd_mgmt_get_emptypoll_max;
rte_power_pmd_mgmt_get_pause_duration;
+ rte_power_pmd_mgmt_get_scaling_freq_max;
+ rte_power_pmd_mgmt_get_scaling_freq_min;
rte_power_pmd_mgmt_set_emptypoll_max;
rte_power_pmd_mgmt_set_pause_duration;
+ rte_power_pmd_mgmt_set_scaling_freq_max;
+ rte_power_pmd_mgmt_set_scaling_freq_min;
};