From 9d31c676c6019df0c078950a0ddca87da4706b14 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Tue, 29 Apr 2014 15:33:06 -0700 Subject: powercap / RAPL: further relax energy counter checks Energy counters may roll slowly for some RAPL domains, checking all of them can be time consuming and takes unpredictable amount of time. Therefore, we relax the sanity check by only checking availability of the MSRs and non-zero value of the energy status counters. It has been shown sufficient for all the platforms tested to filter out inactive domains. Signed-off-by: Jacob Pan Acked-by: Durgadoss R Signed-off-by: Rafael J. Wysocki --- drivers/powercap/intel_rapl.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index d9a0770..1c987d2 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c @@ -1124,8 +1124,7 @@ err_cleanup_package: static int rapl_check_domain(int cpu, int domain) { unsigned msr; - u64 val1, val2 = 0; - int retry = 0; + u64 val = 0; switch (domain) { case RAPL_DOMAIN_PACKAGE: @@ -1144,26 +1143,13 @@ static int rapl_check_domain(int cpu, int domain) pr_err("invalid domain id %d\n", domain); return -EINVAL; } - if (rdmsrl_safe_on_cpu(cpu, msr, &val1)) - return -ENODEV; - - /* PP1/uncore/graphics domain may not be active at the time of - * driver loading. So skip further checks. + /* make sure domain counters are available and contains non-zero + * values, otherwise skip it. */ - if (domain == RAPL_DOMAIN_PP1) - return 0; - /* energy counters roll slowly on some domains */ - while (++retry < 10) { - usleep_range(10000, 15000); - rdmsrl_safe_on_cpu(cpu, msr, &val2); - if ((val1 & ENERGY_STATUS_MASK) != (val2 & ENERGY_STATUS_MASK)) - return 0; - } - /* if energy counter does not change, report as bad domain */ - pr_info("domain %s energy ctr %llu:%llu not working, skip\n", - rapl_domain_names[domain], val1, val2); + if (rdmsrl_safe_on_cpu(cpu, msr, &val) || !val) + return -ENODEV; - return -ENODEV; + return 0; } /* Detect active and valid domains for the given CPU, caller must @@ -1180,6 +1166,9 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu) /* use physical package id to read counters */ if (!rapl_check_domain(cpu, i)) rp->domain_map |= 1 << i; + else + pr_warn("RAPL domain %s detection failed\n", + rapl_domain_names[i]); } rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX); if (!rp->nr_domains) { -- cgit v1.1 From a97ac35b5d9e948ccfcbc04c69e9d2c94e788e94 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Tue, 29 Apr 2014 15:33:07 -0700 Subject: powercap / RAPL: add new CPU IDs Add support for Broadwell model 0x3d and Haswell model (0x3c). Signed-off-by: Jacob Pan Signed-off-by: Rafael J. Wysocki --- drivers/powercap/intel_rapl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index 1c987d2..b1cda6f 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c @@ -951,7 +951,9 @@ static const struct x86_cpu_id rapl_ids[] = { { X86_VENDOR_INTEL, 6, 0x2d},/* Sandy Bridge EP */ { X86_VENDOR_INTEL, 6, 0x37},/* Valleyview */ { X86_VENDOR_INTEL, 6, 0x3a},/* Ivy Bridge */ - { X86_VENDOR_INTEL, 6, 0x45},/* Haswell */ + { X86_VENDOR_INTEL, 6, 0x3c},/* Haswell */ + { X86_VENDOR_INTEL, 6, 0x3d},/* Broadwell */ + { X86_VENDOR_INTEL, 6, 0x45},/* Haswell ULT */ /* TODO: Add more CPU IDs after testing */ {} }; -- cgit v1.1 From ff73b80d64bb2d3324ae85c3b7e953a0a17d7171 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Sat, 10 May 2014 12:47:15 +0200 Subject: PNP / resources: remove positive test on unsigned values irq and dma are both resource_size_t (derived from phys_addr_t <-> unsigned) Signed-off-by: Fabian Frederick Signed-off-by: Rafael J. Wysocki --- drivers/pnp/resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 01712cb..782e822 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -360,7 +360,7 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) return 1; /* check if the resource is valid */ - if (*irq < 0 || *irq > 15) + if (*irq > 15) return 0; /* check if the resource is reserved */ @@ -424,7 +424,7 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) return 1; /* check if the resource is valid */ - if (*dma < 0 || *dma == 4 || *dma > 7) + if (*dma == 4 || *dma > 7) return 0; /* check if the resource is reserved */ -- cgit v1.1 From 086abb58590a4df73e8a6ed71fd418826937cd46 Mon Sep 17 00:00:00 2001 From: Chander Kashyap Date: Fri, 16 May 2014 16:21:17 +0530 Subject: PM / OPP: fix incorrect OPP count handling in of_init_opp_table In of_init_opp_table function, if a failure to add an OPP is detected, the count of OPPs, yet to be added is not updated. Fix this by decrementing this count on failure as well. Signed-off-by: Chander Kashyap Signed-off-by: Inderpal Singh Acked-by: Viresh Kumar Cc: 3.7+ # 3.7+ Acked-by: Nishanth Menon Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index 2553867..c539d70 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -734,11 +734,9 @@ int of_init_opp_table(struct device *dev) unsigned long freq = be32_to_cpup(val++) * 1000; unsigned long volt = be32_to_cpup(val++); - if (dev_pm_opp_add(dev, freq, volt)) { + if (dev_pm_opp_add(dev, freq, volt)) dev_warn(dev, "%s: Failed to add OPP %ld\n", __func__, freq); - continue; - } nr -= 2; } -- cgit v1.1 From 64ce854578de82e9e16280298562721ced971668 Mon Sep 17 00:00:00 2001 From: Chander Kashyap Date: Thu, 22 May 2014 10:36:26 +0530 Subject: PM / OPP: discard duplicate OPPs We don't have any protection against addition of duplicate OPPs currently and in case some code tries to add them, it will end up corrupting OPP tables. We need to handle some duplication cases separately as returning error might not be the right thing always. The new list of return values for dev_pm_opp_add() are: 0: On success OR Duplicate OPPs (both freq and volt are same) and opp->available -EEXIST: Freq are same and volt are different OR Duplicate OPPs (both freq and volt are same) and !opp->available -ENOMEM: Memory allocation failure Acked-by: Nishanth Menon Signed-off-by: Chander Kashyap Signed-off-by: Inderpal Singh Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index c539d70..39412c1 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -394,6 +394,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor); * to keep the integrity of the internal data structures. Callers should ensure * that this function is *NOT* called under RCU protection or in contexts where * mutex cannot be locked. + * + * Return: + * 0: On success OR + * Duplicate OPPs (both freq and volt are same) and opp->available + * -EEXIST: Freq are same and volt are different OR + * Duplicate OPPs (both freq and volt are same) and !opp->available + * -ENOMEM: Memory allocation failure */ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) { @@ -443,15 +450,31 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) new_opp->u_volt = u_volt; new_opp->available = true; - /* Insert new OPP in order of increasing frequency */ + /* + * Insert new OPP in order of increasing frequency + * and discard if already present + */ head = &dev_opp->opp_list; list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) { - if (new_opp->rate < opp->rate) + if (new_opp->rate <= opp->rate) break; else head = &opp->node; } + /* Duplicate OPPs ? */ + if (new_opp->rate == opp->rate) { + int ret = opp->available && new_opp->u_volt == opp->u_volt ? + 0 : -EEXIST; + + dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n", + __func__, opp->rate, opp->u_volt, opp->available, + new_opp->rate, new_opp->u_volt, new_opp->available); + mutex_unlock(&dev_opp_list_lock); + kfree(new_opp); + return ret; + } + list_add_rcu(&new_opp->node, head); mutex_unlock(&dev_opp_list_lock); -- cgit v1.1