Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1228359 > unrolled thread

[PATCH v2 0/5] Support CPR on MSM8916

Started byStephen Boyd <sboyd@codeaurora.org>
First post2015-09-19 03:00 +0200
Last post2015-09-20 02:40 +0200
Articles 6 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 0/5] Support CPR on MSM8916 Stephen Boyd <sboyd@codeaurora.org> - 2015-09-19 03:00 +0200
    [PATCH v2 1/5] regulator: smd: Add floor and corner operations Stephen Boyd <sboyd@codeaurora.org> - 2015-09-19 03:00 +0200
      Re: [PATCH v2 1/5] regulator: smd: Add floor and corner operations Mark Brown <broonie@kernel.org> - 2015-09-20 02:40 +0200
    [PATCH v2 2/5] PM / OPP: Support adjusting OPP voltages at runtime Stephen Boyd <sboyd@codeaurora.org> - 2015-09-19 03:00 +0200
    [PATCH v2 4/5] cpufreq-dt: Handle OPP voltage adjust events Stephen Boyd <sboyd@codeaurora.org> - 2015-09-19 03:00 +0200
    Re: [PATCH v2 0/5] Support CPR on MSM8916 Mark Brown <broonie@kernel.org> - 2015-09-20 02:40 +0200

#1228359 — [PATCH v2 0/5] Support CPR on MSM8916

FromStephen Boyd <sboyd@codeaurora.org>
Date2015-09-19 03:00 +0200
Subject[PATCH v2 0/5] Support CPR on MSM8916
Message-ID<qaeFr-2wF-5@gated-at.bofh.it>
This patch series adds support for CPR on MSM8916. The first
patch exposes a corner voting API to the CPR driver so that we can
change the corner for the MX regulator. If possible I would
like to make this patch prettier, but I don't have any great
ideas right now. The next patch adds support to adjust voltages in the OPP
layer, and then hooks that up to cpufreq-dt so that we can adjust
the voltage in response to what CPR tells us to do. I've also thrown
in a patch to make RCU lockdep warnings go away, but I'm not sure if it's
right. There's still work to do.

The final patch adds the CPR driver. This still has some rough edges. With
the OPPv2 bindings I'm thinking of moving the frequency tables into DT
and adding a custom vendor property to describe which fuse corner to use for
each frequency.

Once you have these patches in place along with a CPU clock driver you
can eanble enable cpufreq-dt and add the cpufreq-dt device (maybe the
CPR driver should add the cpufreq-dt device?) and you'll see interrupts
for CPR and OPP voltage adjustments triggering CPUfreq to modify voltages.

Andy Gross (1):
  regulator: smd: Add floor and corner operations

Stephen Boyd (4):
  PM / OPP: Support adjusting OPP voltages at runtime
  OPP: Allow notifiers to call dev_pm_opp_get_{voltage,freq} RCU-free
  cpufreq-dt: Handle OPP voltage adjust events
  power: avs: Add support for CPR (Core Power Reduction)

 .../devicetree/bindings/power/avs/qcom,cpr.txt     |  125 ++
 drivers/base/power/opp.c                           |   96 +-
 drivers/cpufreq/cpufreq-dt.c                       |   63 +-
 drivers/power/avs/Kconfig                          |   15 +
 drivers/power/avs/Makefile                         |    1 +
 drivers/power/avs/qcom-cpr.c                       | 1999 ++++++++++++++++++++
 drivers/regulator/qcom_smd-regulator.c             |   52 +
 include/linux/pm_opp.h                             |   11 +
 include/linux/regulator/qcom_smd-regulator.h       |   30 +
 9 files changed, 2378 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
 create mode 100644 drivers/power/avs/qcom-cpr.c
 create mode 100644 include/linux/regulator/qcom_smd-regulator.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1228360 — [PATCH v2 1/5] regulator: smd: Add floor and corner operations

FromStephen Boyd <sboyd@codeaurora.org>
Date2015-09-19 03:00 +0200
Subject[PATCH v2 1/5] regulator: smd: Add floor and corner operations
Message-ID<qaeFs-2wF-13@gated-at.bofh.it>
In reply to#1228359
From: Andy Gross <agross@codeaurora.org>

This patch addes the Qualcomm specific functions for setting the floor and
corner voltages on the regulators.

Signed-off-by: Andy Gross <agross@codeaurora.org>
[georgi.djakov@linaro.org: Make work with struct regulator]
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/regulator/qcom_smd-regulator.c       | 52 ++++++++++++++++++++++++++++
 include/linux/regulator/qcom_smd-regulator.h | 30 ++++++++++++++++
 2 files changed, 82 insertions(+)
 create mode 100644 include/linux/regulator/qcom_smd-regulator.h

diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
index 9c6167dd2c8b..cd4a0deb578e 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -20,6 +20,9 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/soc/qcom/smd-rpm.h>
+#include <linux/regulator/qcom_smd-regulator.h>
+
+#include "internal.h"
 
 struct qcom_rpm_reg {
 	struct device *dev;
@@ -44,6 +47,11 @@ struct rpm_regulator_req {
 #define RPM_KEY_SWEN	0x6e657773 /* "swen" */
 #define RPM_KEY_UV	0x00007675 /* "uv" */
 #define RPM_KEY_MA	0x0000616d /* "ma" */
+#define RPM_KEY_FLOOR	0x00636676 /* "vfc" */
+#define RPM_KEY_CORNER	0x6e726f63 /* "corn" */
+
+#define RPM_MIN_FLOOR_CORNER	0
+#define RPM_MAX_FLOOR_CORNER	6
 
 static int rpm_reg_write_active(struct qcom_rpm_reg *vreg,
 				struct rpm_regulator_req *req,
@@ -56,6 +64,50 @@ static int rpm_reg_write_active(struct qcom_rpm_reg *vreg,
 				  req, size);
 }
 
+int qcom_rpm_set_floor(struct regulator *regulator, int floor)
+{
+	struct regulator_dev *rdev = regulator->rdev;
+	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+	struct rpm_regulator_req req;
+	int ret;
+
+	req.key = RPM_KEY_FLOOR;
+	req.nbytes = sizeof(u32);
+	req.value = floor;
+
+	if (floor < RPM_MIN_FLOOR_CORNER || floor > RPM_MAX_FLOOR_CORNER)
+		return -EINVAL;
+
+	ret = rpm_reg_write_active(vreg, &req, sizeof(req));
+	if (ret)
+		dev_err(rdev_get_dev(rdev), "Failed to set floor %d\n", floor);
+
+	return ret;
+}
+EXPORT_SYMBOL(qcom_rpm_set_floor);
+
+int qcom_rpm_set_corner(struct regulator *regulator, int corner)
+{
+	struct regulator_dev *rdev = regulator->rdev;
+	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+	struct rpm_regulator_req req;
+	int ret;
+
+	req.key = RPM_KEY_CORNER;
+	req.nbytes = sizeof(u32);
+	req.value = corner;
+
+	if (corner < RPM_MIN_FLOOR_CORNER || corner > RPM_MAX_FLOOR_CORNER)
+		return -EINVAL;
+
+	ret = rpm_reg_write_active(vreg, &req, sizeof(req));
+	if (ret)
+		dev_err(rdev_get_dev(rdev), "Failed to set corner %d\n", corner);
+
+	return ret;
+}
+EXPORT_SYMBOL(qcom_rpm_set_corner);
+
 static int rpm_reg_enable(struct regulator_dev *rdev)
 {
 	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
diff --git a/include/linux/regulator/qcom_smd-regulator.h b/include/linux/regulator/qcom_smd-regulator.h
new file mode 100644
index 000000000000..a71b6adc64ba
--- /dev/null
+++ b/include/linux/regulator/qcom_smd-regulator.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __QCOM_SMD_REGULATOR_H_
+#define __QCOM_SMD_REGULATOR_H_
+
+#ifdef CONFIG_REGULATOR_QCOM_SMD_RPM
+int qcom_rpm_set_floor(struct regulator *regulator, int floor);
+int qcom_rpm_set_corner(struct regulator *regulator, int corner);
+#else
+static inline int qcom_rpm_set_floor(struct regulator *regulator, int floor)
+{
+	return -EINVAL;
+}
+
+static inline int qcom_rpm_set_corner(struct regulator *regulator, int corner)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1228802 — Re: [PATCH v2 1/5] regulator: smd: Add floor and corner operations

FromMark Brown <broonie@kernel.org>
Date2015-09-20 02:40 +0200
SubjectRe: [PATCH v2 1/5] regulator: smd: Add floor and corner operations
Message-ID<qaAPF-JA-31@gated-at.bofh.it>
In reply to#1228360

[Multipart message — attachments visible in raw view] — view raw

On Fri, Sep 18, 2015 at 05:52:05PM -0700, Stephen Boyd wrote:

> +EXPORT_SYMBOL(qcom_rpm_set_floor);

The entire regulator API is EXPORT_SYMBOL_GPL(), adding plain
EXPORT_SYMBOL() exports is not good.

[toc] | [prev] | [next] | [standalone]


#1228361 — [PATCH v2 2/5] PM / OPP: Support adjusting OPP voltages at runtime

FromStephen Boyd <sboyd@codeaurora.org>
Date2015-09-19 03:00 +0200
Subject[PATCH v2 2/5] PM / OPP: Support adjusting OPP voltages at runtime
Message-ID<qaeFs-2wF-15@gated-at.bofh.it>
In reply to#1228359
On some SoCs the Adaptive Voltage Scaling (AVS) technique is
employed to optimize the operating voltage of a device. At a
given frequency, the hardware monitors dynamic factors and either
makes a suggestion for how much to adjust a voltage for the
current frequency, or it automatically adjusts the voltage
without software intervention. Add an API to the OPP library for
the former case, so that AVS type devices can update the voltages
for an OPP when the hardware determines the voltage should
change. The assumption is that drivers like CPUfreq or devfreq
will register for the OPP notifiers and adjust the voltage
according to suggestions that AVS makes.

Cc: Nishanth Menon <nm@ti.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/base/power/opp.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   | 11 +++++++
 2 files changed, 88 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 28cd75c535b0..35b66c46dcb7 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -1136,6 +1136,83 @@ unlock:
 }
 
 /**
+ * dev_pm_opp_adjust_voltage() - helper to change the voltage of an OPP
+ * @dev:		device for which we do this operation
+ * @freq:		OPP frequency to adjust voltage of
+ * @u_volt:		new OPP voltage
+ *
+ * Change the voltage of an OPP with an RCU operation.
+ *
+ * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks 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 locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
+			      unsigned long u_volt)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+	int r = 0;
+
+	/* keep the node allocated */
+	new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL);
+	if (!new_opp)
+		return -ENOMEM;
+
+	mutex_lock(&dev_opp_list_lock);
+
+	/* Find the device_opp */
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		r = PTR_ERR(dev_opp);
+		dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+		goto unlock;
+	}
+
+	/* Do we have the frequency? */
+	list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) {
+		if (tmp_opp->rate == freq) {
+			opp = tmp_opp;
+			break;
+		}
+	}
+	if (IS_ERR(opp)) {
+		r = PTR_ERR(opp);
+		goto unlock;
+	}
+
+	/* Is update really needed? */
+	if (opp->u_volt == u_volt)
+		goto unlock;
+	/* copy the old data over */
+	*new_opp = *opp;
+
+	/* plug in new node */
+	new_opp->u_volt = u_volt;
+
+	list_replace_rcu(&opp->node, &new_opp->node);
+	mutex_unlock(&dev_opp_list_lock);
+	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
+
+	/* Notify the change of the OPP */
+	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADJUST_VOLTAGE,
+				 new_opp);
+
+	return 0;
+
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+	kfree(new_opp);
+	return r;
+}
+
+/**
  * dev_pm_opp_enable() - Enable a specific OPP
  * @dev:	device for which we do this operation
  * @freq:	OPP frequency to enable
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index e817722ee3f0..f7a4a2245f53 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -22,6 +22,7 @@ struct device;
 
 enum dev_pm_opp_event {
 	OPP_EVENT_ADD, OPP_EVENT_REMOVE, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
+	OPP_EVENT_ADJUST_VOLTAGE,
 };
 
 #if defined(CONFIG_PM_OPP)
@@ -50,6 +51,9 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq,
 		   unsigned long u_volt);
 void dev_pm_opp_remove(struct device *dev, unsigned long freq);
 
+int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
+			      unsigned long u_volt);
+
 int dev_pm_opp_enable(struct device *dev, unsigned long freq);
 
 int dev_pm_opp_disable(struct device *dev, unsigned long freq);
@@ -114,6 +118,13 @@ static inline void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 {
 }
 
+static inline int
+dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
+			  unsigned long u_volt)
+{
+	return 0;
+}
+
 static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq)
 {
 	return 0;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1228362 — [PATCH v2 4/5] cpufreq-dt: Handle OPP voltage adjust events

FromStephen Boyd <sboyd@codeaurora.org>
Date2015-09-19 03:00 +0200
Subject[PATCH v2 4/5] cpufreq-dt: Handle OPP voltage adjust events
Message-ID<qaeFt-2wF-17@gated-at.bofh.it>
In reply to#1228359
On some SoCs the Adaptive Voltage Scaling (AVS) technique is
employed to optimize the operating voltage of a device. At a
given frequency, the hardware monitors dynamic factors and either
makes a suggestion for how much to adjust a voltage for the
current frequency, or it automatically adjusts the voltage
without software intervention.

In the former case, an AVS driver will call
dev_pm_opp_modify_voltage() and update the voltage for the
particular OPP the CPUs are using. Add an OPP notifier to
cpufreq-dt so that we can adjust the voltage of the CPU when AVS
updates the OPP.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/cpufreq/cpufreq-dt.c | 63 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 57 insertions(+), 6 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 7c0d70e2a861..1bf3ae4d4ee1 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -34,6 +34,9 @@ struct private_data {
 	struct regulator *cpu_reg;
 	struct thermal_cooling_device *cdev;
 	unsigned int voltage_tolerance; /* in percentage */
+	struct notifier_block opp_nb;
+	struct mutex lock;
+	unsigned long opp_freq;
 };
 
 static struct freq_attr *cpufreq_dt_attr[] = {
@@ -42,6 +45,33 @@ static struct freq_attr *cpufreq_dt_attr[] = {
 	NULL,
 };
 
+static int opp_notifier(struct notifier_block *nb, unsigned long event,
+			void *data)
+{
+	struct dev_pm_opp *opp = data;
+	struct private_data *priv = container_of(nb, struct private_data,
+						 opp_nb);
+	struct device *cpu_dev = priv->cpu_dev;
+	struct regulator *cpu_reg = priv->cpu_reg;
+	unsigned long volt, tol, freq;
+	int ret = 0;
+
+	if (event == OPP_EVENT_ADJUST_VOLTAGE) {
+		volt = dev_pm_opp_get_voltage(opp);
+		freq = dev_pm_opp_get_freq(opp);
+		tol = volt * priv->voltage_tolerance / 100;
+
+		mutex_lock(&priv->lock);
+		if (freq == priv->opp_freq)
+			ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
+		mutex_unlock(&priv->lock);
+		if (ret)
+			dev_err(cpu_dev, "failed to scale voltage: %d\n", ret);
+	}
+
+	return notifier_from_errno(ret);
+}
+
 static int set_target(struct cpufreq_policy *policy, unsigned int index)
 {
 	struct dev_pm_opp *opp;
@@ -53,6 +83,7 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
 	unsigned long volt = 0, volt_old = 0, tol = 0;
 	unsigned int old_freq, new_freq;
 	long freq_Hz, freq_exact;
+	unsigned long opp_freq = 0;
 	int ret;
 
 	freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
@@ -63,8 +94,8 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
 	new_freq = freq_Hz / 1000;
 	old_freq = clk_get_rate(cpu_clk) / 1000;
 
+	mutex_lock(&priv->lock);
 	if (!IS_ERR(cpu_reg)) {
-		unsigned long opp_freq;
 
 		rcu_read_lock();
 		opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
@@ -72,7 +103,8 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
 			rcu_read_unlock();
 			dev_err(cpu_dev, "failed to find OPP for %ld\n",
 				freq_Hz);
-			return PTR_ERR(opp);
+			ret = PTR_ERR(opp);
+			goto out;
 		}
 		volt = dev_pm_opp_get_voltage(opp);
 		opp_freq = dev_pm_opp_get_freq(opp);
@@ -93,7 +125,7 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
 		if (ret) {
 			dev_err(cpu_dev, "failed to scale voltage up: %d\n",
 				ret);
-			return ret;
+			goto out;
 		}
 	}
 
@@ -102,7 +134,7 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
 		dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
 		if (!IS_ERR(cpu_reg) && volt_old > 0)
 			regulator_set_voltage_tol(cpu_reg, volt_old, tol);
-		return ret;
+		goto out;
 	}
 
 	/* scaling down?  scale voltage after frequency */
@@ -112,9 +144,12 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
 			dev_err(cpu_dev, "failed to scale voltage down: %d\n",
 				ret);
 			clk_set_rate(cpu_clk, old_freq * 1000);
+			goto out;
 		}
 	}
-
+	priv->opp_freq = opp_freq;
+out:
+	mutex_unlock(&priv->lock);
 	return ret;
 }
 
@@ -201,6 +236,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	unsigned int transition_latency;
 	bool need_update = false;
 	int ret;
+	struct srcu_notifier_head *opp_srcu_head;
 
 	ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
 	if (ret) {
@@ -277,6 +313,19 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		goto out_free_opp;
 	}
 
+	mutex_init(&priv->lock);
+
+	opp_srcu_head = dev_pm_opp_get_notifier(cpu_dev);
+	if (IS_ERR(opp_srcu_head)) {
+		ret = PTR_ERR(opp_srcu_head);
+		goto out_free_priv;
+	}
+
+	priv->opp_nb.notifier_call = opp_notifier;
+	ret = srcu_notifier_chain_register(opp_srcu_head, &priv->opp_nb);
+	if (ret)
+		goto out_free_priv;
+
 	of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
 
 	if (!transition_latency)
@@ -326,7 +375,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
 	if (ret) {
 		pr_err("failed to init cpufreq table: %d\n", ret);
-		goto out_free_priv;
+		goto out_unregister_nb;
 	}
 
 	priv->cpu_dev = cpu_dev;
@@ -365,6 +414,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 
 out_free_cpufreq_table:
 	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+out_unregister_nb:
+	srcu_notifier_chain_unregister(opp_srcu_head, &priv->opp_nb);
 out_free_priv:
 	kfree(priv);
 out_free_opp:
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1228804

FromMark Brown <broonie@kernel.org>
Date2015-09-20 02:40 +0200
Message-ID<qaAPF-JA-37@gated-at.bofh.it>
In reply to#1228359

[Multipart message — attachments visible in raw view] — view raw

On Fri, Sep 18, 2015 at 05:52:04PM -0700, Stephen Boyd wrote:
> This patch series adds support for CPR on MSM8916. The first
> patch exposes a corner voting API to the CPR driver so that we can

You might want to expand on the acronym CPR since I'm reasonably sure
that you don't in fact mean the normal expansion cardiopulmonary
resuscitation.

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web