The "struct device" is only used in sysfs.c.
The other .c files including the private header "cpuidle.h"
do not need to pull the entire headers tree from there as they
don't manipulate the "struct device".
This patch fix this by moving the header inclusion to sysfs.c
and adding a forward declaration for the struct device.
The number of lines generated by the preprocesor:
Without this patch : 17269 loc
With this patch : 16446 loc
Signed-off-by: Daniel Lezcano <daniel.lezcano(a)linaro.org>
---
drivers/cpuidle/cpuidle.h | 5 +++--
drivers/cpuidle/sysfs.c | 1 +
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h
index 2120d9e..f6b0923 100644
--- a/drivers/cpuidle/cpuidle.h
+++ b/drivers/cpuidle/cpuidle.h
@@ -5,8 +5,6 @@
#ifndef __DRIVER_CPUIDLE_H
#define __DRIVER_CPUIDLE_H
-#include <linux/device.h>
-
/* For internal use only */
extern struct cpuidle_governor *cpuidle_curr_governor;
extern struct list_head cpuidle_governors;
@@ -25,6 +23,9 @@ extern void cpuidle_uninstall_idle_handler(void);
extern int cpuidle_switch_governor(struct cpuidle_governor *gov);
/* sysfs */
+
+struct device;
+
extern int cpuidle_add_interface(struct device *dev);
extern void cpuidle_remove_interface(struct device *dev);
extern int cpuidle_add_state_sysfs(struct cpuidle_device *device);
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index ed87399..860a686 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/capability.h>
+#include <linux/device.h>
#include "cpuidle.h"
--
1.7.5.4
The variables here are really not used uninitialized.
arch/arm/mm/alignment.c: In function 'do_alignment':
arch/arm/mm/alignment.c:327:15: warning: 'offset.un' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arm/mm/alignment.c:748:21: note: 'offset.un' was declared here
Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
---
arch/arm/mm/alignment.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index b9f60eb..223b4aa 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
static int
do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
- union offset_union offset;
+ union offset_union uninitialized_var(offset);
unsigned long instr = 0, instrptr;
int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
unsigned int type;
--
1.7.12.rc2.18.g61b472e
This patchset uses the per-entity-load-tracking patchset which will soon be
available in the kernel.It is based on the tip/master tree before the
(HEAD at b654f92c06e562c)integration of per-entity-load-tracking patchset.
The first 8 latest patches of sched:per-entity-load-tracking alone have
been imported to the tree from the quilt series of Peter(when they were
present) to avoid the complexities of task groups and to hold back the
optimizations of this patchset for now.This patchset is based at this level.
Refer https://lkml.org/lkml/2012/10/12/9.This series is a continuation
of the patchset in this link.
This patchset is an attempt to begin the integration of PJT's
metric with the load balancer in a step wise fashion,and progress based
on the consequences.This patchset has been tested with the config excluding
CONFIG_FAIR_GROUP_SCHED.
The following issues have been considered towards this:
[NOTE:an x% task referred to in the logs and below is calculated over a
duty cycle of 10ms.]
1.Consider a scenario,where there are two 10% tasks running on a cpu.The
present code will consider the load on this queue to be 2048,while
using PJT's metric the load is calculated to be <1000,rarely exceeding this
limit.Although the tasks are not contributing much to the cpu load,they are
decided to be moved by the scheduler.
But one could argue that 'not moving one of these tasks could throttle
them.If there was an idle cpu,perhaps we could have moved them'.While the
power save mode would have been fine with not moving the task,the
performance mode would prefer not to throttle the tasks.We could strive
to strike a balance by making this decision tunable with certain parameters.
This patchset includes such tunables.This issue is addressed in Patch[1/2].
*The advantage of this behavior of PJT's metric has been demonstrated via
an experiment*.Please see the reply to this cover letter to be posted right
away.
2.We need to be able to do this cautiously,as the scheduler code is too
complex.This patchset is an attempt to begin the integration of PJT's
metric with the load balancer in a step wise fashion,and progress based on
the consequences.
*What this patchset essentially does is in two primary places of the
scheduler,PJT's metric has replaced the existing metric to make decisions for load
balancing*.
1.load_balance()
2.select_task_rq_fair()
This description of the patches are below:
Patch[1/13]: This patch aims at detecting short running tasks and
prevent their movement.In update_sg_lb_stats,dismiss a sched group
as a candidate for load balancing,if load calculated by PJT's metric
says that the average load on the sched_group <= 1024+(.15*1024).
This is a tunable,which can be varied after sufficient experiments.
Patch[2/13]:In the current scheduler greater load would be analogous
to more number of tasks.Therefore when the busiest group is picked
from the sched domain in update_sd_lb_stats,only the loads of the
groups are compared between them.If we were to use PJT's metric,a
higher load does not necessarily mean more number of tasks.This
patch addresses this issue.
Patch[3/13] to Patch[13/13] : Replacement of the existing metrics
deciding load balancing and selecting a runqueue for load
placement,with the PJT's metric and subsequent usage of PJT's metric
for schduling.
3.The Primary advantage that I see in integrating PJT's metric with the core
scheduler is listed below:
1. Excluding short running tasks from being candidates for load balancing.
This would avoid unnecessary migrations when the CPU is not sufficiently
loaded.This advantage has been portrayed in the results of the
experiment.
Run the workload attached.There are 8 threads spwaned each being 10%
tasks.
The number of migrations was measured from /proc/schedstat
Machine: 1 socket 4 core pre-nehalem.
Experimental Setup:
cat /proc/schedstat > stat_initial
gcc -Wall -Wshadow -lpthread -o test test.c
cat /proc/schedstat > stat_final
The difference in the number of pull requests from both these files have
been calculated and are as below:
Observations:
With_Patchset Without_patchset
---------------------------------------------------------------------
Average_number_of_migrations 0 46
Average_number_of_records/s 9,71,114 9,45,158
With more memory intensive workloads, a higher difference in the number of
migrations is seen without any performance compromise.
---
Preeti U Murthy (13):
sched:Prevent movement of short running tasks during load balancing
sched:Pick the apt busy sched group during load balancing
sched:Decide whether there be transfer of loads based on the PJT's metric
sched:Decide group_imb using PJT's metric
sched:Calculate imbalance using PJT's metric
sched:Changing find_busiest_queue to use PJT's metric
sched:Change move_tasks to use PJT's metric
sched:Some miscallaneous changes in load_balance
sched:Modify check_asym_packing to use PJT's metric
sched:Modify fix_small_imbalance to use PJT's metric
sched:Modify find_idlest_group to use PJT's metric
sched:Modify find_idlest_cpu to use PJT's metric
sched:Modifying wake_affine to use PJT's metric
kernel/sched/fair.c | 262 ++++++++++++++++++++++++++++++++++++---------------
1 file changed, 186 insertions(+), 76 deletions(-)
--
Preeti U Murthy
The discussion about having different cpus on the system with
different latencies bring us to a first attemp by adding a
pointer in the cpuidle_device to the states array.
But as Rafael suggested, it would make more sense to create a
driver per cpu [1].
This patch adds support for multiple cpuidle drivers.
It creates a per cpu cpuidle driver pointer.
In order to not break the different drivers, the function cpuidle_register_driver
assign for each cpu, the driver.
The multiple driver support is optional and if it is not set, the cpuide driver
core code remains the same (except some code reorganisation).
I did the following tests compiled, booted, tested without/with CONFIG_CPU_IDLE,
with/without CONFIG_CPU_IDLE_MULTIPLE_DRIVERS.
Tested on Core2 Duo T9500 with acpi_idle [and intel_idle]
Tested on ARM Dual Cortex-A9 U8500 (aka Snowball)
V1 tested on Tegra3 and Vexpress TC2
[1] http://www.spinics.net/lists/linux-acpi/msg37921.html
Changelog:
V2:
* fixed sysfs output : /sys/devices/system/cpu/cpu[0-9]/driver/name
* fixed ifdefs in driver.c
* fixed register_driver function loop when unregistering
* removed WARN under spinlock
* fixed changelog for patch [2/4]
* changed cpuidle_get_cpu_driver function parameter
* removed cpuidle_for_each_driver function
* replaced smp_processor_id() by get_cpu/put_cpu
Daniel Lezcano (4):
cpuidle: move driver's refcount to cpuidle
cpuidle: move driver checking within the lock section
cpuidle: prepare the driver core to be multi drivers aware
cpuidle: support multiple drivers
drivers/cpuidle/Kconfig | 9 ++
drivers/cpuidle/cpuidle.c | 36 +++++---
drivers/cpuidle/cpuidle.h | 4 +-
drivers/cpuidle/driver.c | 209 ++++++++++++++++++++++++++++++++++++++------
drivers/cpuidle/sysfs.c | 174 ++++++++++++++++++++++++++++++++++++--
include/linux/cpuidle.h | 8 ++-
6 files changed, 388 insertions(+), 52 deletions(-)
--
1.7.5.4
From: Shiraz Hashim <shiraz.hashim(a)st.com>
pinctrl subsystem needs gpio chip base to prepare set of gpio pin ranges, which
a given pinctrl driver can handle. This is important to handle pinctrl gpio
request calls in order to program a given pin properly for gpio operation.
As gpio base is allocated dynamically during gpiochip registration, presently
there exists no clean way to pass this information to the pinctrl subsystem.
After few discussions from [1], it was concluded that may be gpio controller
reporting the pin range it supports, is a better way than pinctrl subsystem
directly registering it.
[1] http://comments.gmane.org/gmane.linux.ports.arm.kernel/184816
Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
Signed-off-by: Shiraz Hashim <shiraz.hashim(a)st.com>
---
Hi Linus,
Its been almost two months when this stuff was last discussed. Here is another
attempt to fix open issues in it.
V1->V2:
------
- Add non-DT routines to register gpio ranges
- Update Documentation/gpio.txt
- of_gpiochip_add_pin_range() rearranged a bit
- use devm_kzalloc() instead of kzalloc()
- few other minor fixes
Bad part is, this code doesn't compile currently :(
It depends on a routine: pinctrl_remove_gpio_range() which was recently removed
by another patch, thinking that there might not be any more users of that
routine. It was removed as the removal of ranges was done in unregister of
pinctrl.
But because we are registering stuff from gpiolib now, we may remove and insert
a gpio module multiple times. So, we need that again. I will add that patch to
this series once you are okay with this one.
I know you might be attending connect now, please review it if you have some
spare time.
Documentation/devicetree/bindings/gpio/gpio.txt | 36 ++++++++++++++++
Documentation/gpio.txt | 26 ++++++++++++
drivers/gpio/gpiolib-of.c | 56 +++++++++++++++++++++++++
drivers/gpio/gpiolib.c | 43 +++++++++++++++++++
drivers/pinctrl/core.c | 13 ++++++
drivers/pinctrl/devicetree.c | 13 ++++++
include/asm-generic/gpio.h | 23 ++++++++++
include/linux/gpio.h | 3 ++
include/linux/pinctrl/pinctrl.h | 16 +++++++
9 files changed, 229 insertions(+)
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index 4e16ba4..a336287 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
gpio-controller;
};
+2.1) gpio-controller and pinctrl subsystem
+------------------------------------------
+gpio-controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with optional gpio feature.
+
+While the pin allocation is totally managed by the pin ctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to
+request the corresponding pin before any gpio usage.
+
+For this, the gpio controller can use a pinctrl phandle and pins to
+announce the pinrange to the pin ctrl subsystem. For example,
+
+ qe_pio_e: gpio-controller@1460 {
+ #gpio-cells = <2>;
+ compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+ reg = <0x1460 0x18>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
+
+ }
+
+where,
+ &pinctrl1 and &pinctrl2 is the phandle to the pinctrl DT node.
+
+ Next values specify the base pin and number of pins for the range
+ handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
+ pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
+ by this gpio controller.
+
+The pinctrl node must have "#gpio-range-cells" property to show number of
+arguments to pass with phandle from gpio controllers node.
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index e08a883..77f233c 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -439,6 +439,32 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its
signaling rate accordingly.
+gpio-controller and pinctrl subsystem
+------------------------------------------
+
+gpio-controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with optional gpio feature.
+
+While the pin allocation is totally managed by the pin ctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to
+request the corresponding pin before any gpio usage.
+
+For this, the gpio controller can register its pin range with pinctrl subsystem.
+There are two ways of doing it currently with or without DT.
+
+For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
+
+For non-DT support, user can call gpiochip_add_pin_range() with appropriate
+parameters to register a range of gpio pins with a pinctrl driver. For this
+exact name string of pinctrl device has to be passed as one of the argument to
+this routine.
+
+
What do these conventions omit?
===============================
One of the biggest things these conventions omit is pin multiplexing, since
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index f1a4599..a5b90c8 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -19,6 +19,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
/* Private data structure for of_gpiochip_find_and_xlate */
@@ -216,6 +217,58 @@ err0:
}
EXPORT_SYMBOL(of_mm_gpiochip_add);
+#ifdef CONFIG_PINCTRL
+void of_gpiochip_add_pin_range(struct gpio_chip *chip)
+{
+ struct device_node *np = chip->of_node;
+ struct gpio_pin_range *pin_range;
+ struct of_phandle_args pinspec;
+ int index = 0, ret;
+
+ if (!np)
+ return;
+
+ do {
+ ret = of_parse_phandle_with_args(np, "gpio-ranges",
+ "#gpio-range-cells", index, &pinspec);
+ if (ret)
+ break;
+
+ pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range),
+ GFP_KERNEL);
+ if (!pin_range) {
+ pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
+ chip->label);
+ break;
+ }
+
+ pin_range->range.name = chip->label;
+ pin_range->range.base = chip->base;
+ pin_range->range.pin_base = pinspec.args[0];
+ pin_range->range.npins = pinspec.args[1];
+ pin_range->pctldev = of_pinctrl_add_gpio_range(pinspec.np,
+ &pin_range->range);
+
+ list_add_tail(&pin_range->node, &chip->pin_ranges);
+
+ } while (index++);
+}
+
+void of_gpiochip_remove_pin_range(struct gpio_chip *chip)
+{
+ struct gpio_pin_range *pin_range, *tmp;
+
+ list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
+ list_del(&pin_range->node);
+ pinctrl_remove_gpio_range(pin_range->pctldev,
+ &pin_range->range);
+ }
+}
+#else
+void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
+void of_gpiochip_remove_pin_range(struct gpio_chip *chip) {}
+#endif
+
void of_gpiochip_add(struct gpio_chip *chip)
{
if ((!chip->of_node) && (chip->dev))
@@ -229,11 +282,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
chip->of_xlate = of_gpio_simple_xlate;
}
+ of_gpiochip_add_pin_range(chip);
of_node_get(chip->of_node);
}
void of_gpiochip_remove(struct gpio_chip *chip)
{
+ of_gpiochip_remove_pin_range(chip);
+
if (chip->of_node)
of_node_put(chip->of_node);
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index d5f9742..6456bc0 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1088,6 +1088,10 @@ int gpiochip_add(struct gpio_chip *chip)
}
}
+#ifdef CONFIG_PINCTRL
+ INIT_LIST_HEAD(&chip->pin_ranges);
+#endif
+
of_gpiochip_add(chip);
unlock:
@@ -1185,6 +1189,45 @@ struct gpio_chip *gpiochip_find(void *data,
}
EXPORT_SYMBOL_GPL(gpiochip_find);
+#ifdef CONFIG_PINCTRL
+void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+ unsigned int pin_base, unsigned int npins)
+{
+ struct gpio_pin_range *pin_range;
+
+ pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range), GFP_KERNEL);
+ if (!pin_range) {
+ pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
+ chip->label);
+ return;
+ }
+
+ pin_range->range.name = chip->label;
+ pin_range->range.base = chip->base;
+ pin_range->range.pin_base = pin_base;
+ pin_range->range.npins = npins;
+ pin_range->pctldev = find_pinctrl_and_add_gpio_range(pinctl_name,
+ &pin_range->range);
+
+ list_add_tail(&pin_range->node, &chip->pin_ranges);
+}
+
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+ struct gpio_pin_range *pin_range, *tmp;
+
+ list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
+ list_del(&pin_range->node);
+ pinctrl_remove_gpio_range(pin_range->pctldev,
+ &pin_range->range);
+ }
+}
+#else
+void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+ unsigned int pin_base, unsigned int npins) {}
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip) {}
+#endif
+
/* These "optional" allocation calls help prevent drivers from stomping
* on each other, and help provide better diagnostics in debugfs.
* They're called even less than the "set direction" calls.
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index cec6072..620259e 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -345,6 +345,19 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
}
EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
+struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
+ struct pinctrl_gpio_range *range)
+{
+ struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname);
+
+ if (!pctldev)
+ return NULL;
+
+ pinctrl_add_gpio_range(pctldev, range);
+ return pctldev;
+}
+EXPORT_SYMBOL_GPL(find_pinctrl_and_add_gpio_range);
+
/**
* pinctrl_get_group_selector() - returns the group selector for a group
* @pctldev: the pin controller handling the group
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index fcb1de4..6728ec7 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -106,6 +106,19 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
return NULL;
}
+struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
+ struct pinctrl_gpio_range *range)
+{
+ struct pinctrl_dev *pctldev;
+
+ pctldev = find_pinctrl_by_of_node(np);
+ if (!pctldev)
+ return NULL;
+
+ pinctrl_add_gpio_range(pctldev, range);
+ return pctldev;
+}
+
static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
struct device_node *np_config)
{
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index a9432fc..77eb1c1 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -5,6 +5,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
#ifdef CONFIG_GPIOLIB
@@ -48,6 +49,19 @@ struct module;
struct device_node;
/**
+ * struct gpio_pin_range - pin range controlled by a gpio chip
+ * @head: list for maintaining set of pin ranges, used internally
+ * @pctldev: pinctrl device which handles corresponding pins
+ * @range: actual range of pins controlled by a gpio controller
+ */
+
+struct gpio_pin_range {
+ struct list_head node;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_gpio_range range;
+};
+
+/**
* struct gpio_chip - abstract a GPIO controller
* @label: for diagnostics
* @dev: optional device providing the GPIOs
@@ -134,6 +148,15 @@ struct gpio_chip {
int (*of_xlate)(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags);
#endif
+#ifdef CONFIG_PINCTRL
+ /*
+ * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
+ * describe the actual pin range which they serve in an SoC. This
+ * information would be used by pinctrl subsystem to configure
+ * corresponding pins for gpio usage.
+ */
+ struct list_head pin_ranges;
+#endif
};
extern const char *gpiochip_is_requested(struct gpio_chip *chip,
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 2e31e8b..a284459 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -231,6 +231,9 @@ static inline int irq_to_gpio(unsigned irq)
return -EINVAL;
}
+void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+ unsigned int pin_base, unsigned int npins);
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
#endif
#endif /* __LINUX_GPIO_H */
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 7d087f0..273df69 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -134,6 +134,22 @@ extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *ranges,
unsigned nranges);
+extern struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
+ struct pinctrl_gpio_range *range);
+
+#ifdef CONFIG_OF
+extern struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
+ struct pinctrl_gpio_range *range);
+#else
+static inline
+struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
+ struct pinctrl_gpio_range *range)
+{
+ return NULL;
+}
+
+#endif /* CONFIG_OF */
+
extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
#else
--
1.7.12.rc2.18.g61b472e
Hi Rafael,
__cpufreq_driver_target() must not pass target frequency beyond the limits of
current policy.
Today most of cpufreq platform drivers are doing this check in their target
routines. Why not move it to __cpufreq_driver_target().
I wanted to get your opinion on this before making changes in all driver files.
That's why this is an RFC.
Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
---
drivers/cpufreq/cpufreq.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index f552d5f..59264f1 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1470,12 +1470,19 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
unsigned int relation)
{
int retval = -EINVAL;
+ unsigned int old_target_freq = target_freq;
if (cpufreq_disabled())
return -ENODEV;
- pr_debug("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
- target_freq, relation);
+ /* Make sure that target_freq is within supported range */
+ if (target_freq > policy->max)
+ target_freq = policy->max;
+ if (target_freq < policy->min)
+ target_freq = policy->min;
+
+ pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
+ policy->cpu, target_freq, relation, old_target_freq);
if (cpu_online(policy->cpu) && cpufreq_driver->target)
retval = cpufreq_driver->target(policy, target_freq, relation);
--
1.7.12.rc2.18.g61b472e