
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBC4SJ -------------------------------- Trigger the highest frequency bandwidth regularly, judge the bandwidth change ratio and the corresponding frequency ratio, and abstract the judgment logic through accuracy loss. If the conditions are not met, the conditions are reset. Signed-off-by: Xiangwei Li <liwei728@huawei.com> --- drivers/devfreq/event/hisi-uncore-l3c.c | 38 +++++++++++++++++++-- drivers/devfreq/event/hisi-uncore.h | 11 +++++++ drivers/devfreq/hisi_uncore_freq.c | 44 ++++++++++++++----------- 3 files changed, 71 insertions(+), 22 deletions(-) diff --git a/drivers/devfreq/event/hisi-uncore-l3c.c b/drivers/devfreq/event/hisi-uncore-l3c.c index fa6252227acf..a7104649fac7 100644 --- a/drivers/devfreq/event/hisi-uncore-l3c.c +++ b/drivers/devfreq/event/hisi-uncore-l3c.c @@ -16,22 +16,51 @@ #include "hisi-uncore.h" -HISI_UNCORE_EVENT_TYPE_ATTR; -HISI_UNCORE_EVENT_CONFIG_ATTR; +#define CORRECT_PERIOD (10) +#define CALC_PRECSION (1000) + +static HISI_UNCORE_EVENT_TYPE_ATTR; +static HISI_UNCORE_EVENT_CONFIG_ATTR; static int l3c_get_events(struct devfreq_event_dev *edev, struct devfreq_event_data *edata) { u64 load; - struct hisi_uncore_event_info *info = devfreq_event_get_drvdata(edev); + static int period; + static u64 last_load; + int f0, f1, p0, p1, per_step; + struct hisi_uncore_event_info *info; + info = devfreq_event_get_drvdata(edev); load = get_pmu_monitor_status(info); + per_step = info->freq_domain->per_step; if (info->is_reset) { info->is_reset = false; info->max_load = 0; + period = 0; + return 0; + } + + period++; + if (period == CORRECT_PERIOD) { + edata->load_count = info->max_load; + edata->total_count = info->max_load; + last_load = load; return 0; } + if (period > CORRECT_PERIOD) { + period = 0; + p0 = (CALC_PRECSION * load) / last_load; + p1 = (CALC_PRECSION * last_load) / info->max_load; + f0 = (CALC_PRECSION * load) / (info->max_load * per_step); + f1 = (CALC_PRECSION * last_load) / (info->max_load * per_step); + + if (p1 < per_step || p0 > (f0 * (CALC_PRECSION * info->freq_domain->freq_max)) / + (f1 * (info->freq_domain->freq_max - info->freq_domain->freq_step))) + info->max_load = load; + } + info->max_load = max(info->max_load, load); edata->load_count = load; edata->total_count = info->max_load; @@ -71,6 +100,9 @@ static int hisi_l3c_event_probe(struct platform_device *pdev) desc->driver_data = data; desc->name = data->name; data->desc = desc; + data->freq_domain = pdev->dev.platform_data; + data->freq_domain->per_step = + CALC_PRECSION / (data->freq_domain->freq_max / data->freq_domain->freq_step); edev = devm_devfreq_event_add_edev(dev, desc); if (IS_ERR(edev)) { diff --git a/drivers/devfreq/event/hisi-uncore.h b/drivers/devfreq/event/hisi-uncore.h index 551a533f5191..7a4a41e36a87 100644 --- a/drivers/devfreq/event/hisi-uncore.h +++ b/drivers/devfreq/event/hisi-uncore.h @@ -31,6 +31,16 @@ #define EVENT_CONFIG_MAX_CNT (2) #define EVENT_CONFIG_INVALID_VAL (0xffff) +/* + * tunable domain + */ +struct freq_domain { + int per_step; + unsigned long freq_min; + unsigned long freq_max; + unsigned long freq_step; +}; + /* * The signle uncore pmu info. */ @@ -50,6 +60,7 @@ struct hisi_uncore_event_info { int config_cnt; __u64 configs[EVENT_CONFIG_MAX_CNT]; u64 max_load; + struct freq_domain *freq_domain; struct device *dev; struct devfreq_event_dev *edev; struct devfreq_event_desc *desc; diff --git a/drivers/devfreq/hisi_uncore_freq.c b/drivers/devfreq/hisi_uncore_freq.c index 89e969f5f114..511e17d70cd6 100644 --- a/drivers/devfreq/hisi_uncore_freq.c +++ b/drivers/devfreq/hisi_uncore_freq.c @@ -21,6 +21,7 @@ #include <linux/property.h> #include <linux/topology.h> #include <linux/devfreq-event.h> +#include "event/hisi-uncore.h" #include <acpi/pcc.h> @@ -44,9 +45,7 @@ struct hisi_uncore_freq { struct pcc_mbox_chan *pchan; void __iomem *pcc_shmem_addr; int chan_id; - unsigned long freq_min; - unsigned long freq_max; - unsigned long freq_step; + struct freq_domain freq_domain; struct devfreq *devfreq; int related_package; struct cpumask related_cpus; @@ -228,11 +227,12 @@ static int hisi_uncore_target(struct device *dev, unsigned long *freq, u32 data = *freq / HZ_PER_MHZ; if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) - data = roundup(data, uncore->freq_step); + data = roundup(data, uncore->freq_domain.freq_step); else - data = rounddown(data, uncore->freq_step); + data = rounddown(data, uncore->freq_domain.freq_step); - data = clamp((unsigned long)data, uncore->freq_min, uncore->freq_max); + data = clamp((unsigned long)data, + uncore->freq_domain.freq_min, uncore->freq_domain.freq_max); return hisi_uncore_cmd_send(uncore, HUCF_PCC_CMD_SET_FREQ, &data); } @@ -255,10 +255,16 @@ static int hisi_uncore_get_dev_status(struct device *dev, if (rc) return rc; - if (ratio <= edata.load_count * 1000 / edata.total_count) { + if (edata.load_count == edata.total_count) { stat->busy_time = edata.load_count; stat->total_time = edata.total_count; - ratio = edata.load_count * 1000 / edata.total_count; + return 0; + } + + if (ratio <= edata.load_count * 100 / edata.total_count) { + stat->busy_time = edata.load_count; + stat->total_time = edata.total_count; + ratio = edata.load_count * 100 / edata.total_count; } } @@ -286,28 +292,28 @@ static int hisi_uncore_add_opp(struct hisi_uncore_freq *uncore) rc = hisi_uncore_cmd_send(uncore, HUCF_PCC_CMD_GET_PLAT_FREQ_MIN, &data); if (rc) return rc; - uncore->freq_min = data; + uncore->freq_domain.freq_min = data; rc = hisi_uncore_cmd_send(uncore, HUCF_PCC_CMD_GET_PLAT_FREQ_MAX, &data); if (rc) return rc; - uncore->freq_max = data; + uncore->freq_domain.freq_max = data; rc = hisi_uncore_cmd_send(uncore, HUCF_PCC_CMD_GET_PLAT_FREQ_STEP, &data); if (rc) return rc; - uncore->freq_step = data; + uncore->freq_domain.freq_step = data; - for (freq_mhz = uncore->freq_min; freq_mhz <= uncore->freq_max; - freq_mhz += uncore->freq_step) { + for (freq_mhz = uncore->freq_domain.freq_min; freq_mhz <= uncore->freq_domain.freq_max; + freq_mhz += uncore->freq_domain.freq_step) { rc = dev_pm_opp_add(uncore->dev, freq_mhz * HZ_PER_MHZ, DEF_OPP_VOLT_UV); if (rc) { unsigned long freq_curr = freq_mhz; dev_err(uncore->dev, "Add OPP %lu failed (%d)\n", freq_mhz, rc); - for (freq_mhz = uncore->freq_min; freq_mhz < freq_curr; - freq_mhz += uncore->freq_step) + for (freq_mhz = uncore->freq_domain.freq_min; freq_mhz < freq_curr; + freq_mhz += uncore->freq_domain.freq_step) dev_pm_opp_remove(uncore->dev, freq_mhz * HZ_PER_MHZ); break; @@ -321,8 +327,8 @@ static void hisi_uncore_remove_opp(struct hisi_uncore_freq *uncore) { unsigned long freq_mhz; - for (freq_mhz = uncore->freq_min; freq_mhz <= uncore->freq_max; - freq_mhz += uncore->freq_step) + for (freq_mhz = uncore->freq_domain.freq_min; freq_mhz <= uncore->freq_domain.freq_max; + freq_mhz += uncore->freq_domain.freq_step) dev_pm_opp_remove(uncore->dev, freq_mhz * HZ_PER_MHZ); } @@ -483,8 +489,8 @@ static int creat_related_event(struct hisi_uncore_freq *uncore, char *name) uncore->dev, dev_name, uncore->related_package, - NULL, - 0); + &(uncore->freq_domain), + sizeof(uncore->freq_domain)); if (IS_ERR(event->pdev)) return PTR_ERR(event->pdev); -- 2.25.1