* [RFC PATCH 0/5] arm64: Signal context expansion
From: Dave Martin @ 2016-09-12 11:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <d7fa9069-f952-0642-9668-2fea640cdb20@redhat.com>
On Fri, Sep 09, 2016 at 07:01:12PM +0200, Florian Weimer wrote:
> On 09/09/2016 05:21 PM, Dave Martin wrote:
>
> >>Do you add this extra information only if the stack is sufficiently large?
> >>
> >>x86_64 adds the new information even for small stacks set up with
> >>sigaltstack, leading to memory corruption on bleeding-edge hardware:
> >>
> >> <https://bugzilla.kernel.org/show_bug.cgi?id=153531>
> >
> >Hmmm, not yet. We already check that the whole frame is writable user
> >memory, but this isn't sufficient to avoid user corruption in the case
> >of alternate signal stacks. I'll fix this -- thanks for flagging it.
> >
> >If the stack isn't large enough, we'll still have to SEGV the task
> >though.
>
> You could skip copying the data and not install a pointer to it in the
> existing signal context.
We could, but then we'd corrupt the task state in sigreturn, since
we wouldn't have been able to save/restore part of the state.
> >We can (and should) bump up the SIG{,MIN}STKSZ constants when adding
> >the SVE support proper to the kernel,
>
> That's a userspace ABI change (libraries use these constants to size struct
> members), and not a good idea. You might get away with at this stage, but
> you can't do this every time you add some new process state you want to add
> to signal handlers.
For internal interfaces within a single component that's tolerable,
since a single value would be used for each of these constants
throughout the build of that component.
A quick search on sources.debian.org suggests that the total number of
packages that expose {,MIN}SIGSTKSZ dependent definitions in their
public interfaces is small (I couldn't find any after paging through
dozens of pages of results -- so the total is maybe in the range 0-10)
-- hopefully few enough to eyeball.
> >I wonder whether we should make the signal stack size runtime
> >discoverable through sysconf() instead...
I will likely suggest this for the future, but of course it doesn't help
for current binaries.
Note that MINSIGSTKSZ stared life wrong for arm64, and has since gone
through a few ABI breaking changes. I don't condone this, but we have
form in this area :/
sigaltstack() already fails with ENOMEM for software that passes
ss_size = MINSIGSTKSZ, and is built against glibc<2.22 [1], [2], running
on linux>=4.3 [3], which is an ABI break in case where sigaltstack() is
otherwise guaranteed to succeed.
The bottom line here is that the sigaltstack() API is broken with regard
to extensibility, so we cannot extend the amount of signal state without
breaking something.
The least-wrong thing I can think of to do is:
* deprecate but continue to support the existing sigaltstack API/ABI
with today's {,MIN}SIGSTKSZ definitions
* guarantee (as much as possible) that software using this ABI continues
to work (by saving/restoring only data that _must_ be saved/restored at
each signal, which may be small enough to fit)
* providing a clean failure mode (fatal signal) when this proves
impossible at signal delivery/return time;
* define a new interface for runtime-querying the required signal stack
size;
* define a new syscall or new stack_t.ss_flags flags (say, SS_STRICT)
that permits the kernel to enforce a runtime-determined minimum greater
than MINSIGSTKSZ when calling sigaltstack().
Another option would be:
* define a new interface for runtime-querying the required signal stack
size, and
* support the current API/ABI, but make a call to sigaltstack() SEGV or
SIGILL the caller if it specifies ss_stack >= MINSIGSTKSZ but smaller
than the actual runtime minimum.
(this would cause old software to break immediately in an obvious way on
new systems, forcing people to fix their software -- which they might or
might not actually bother to do).
Thoughts?
Cheers
---Dave
[1] https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b763f6ae859ecea70a5dacb8ad45c71d5f667e2e
[2] https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/bits/sigstack.h;h=e143034ce24dc383016b4882b89cfebc7a6a62d7;hb=b8079dd0d360648e4e8de48656c5c38972621072
[3] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c9692657c0321fec7bcb3ca8c6db56c08c640ace
^ permalink raw reply
* [PATCH 1/2] ARM: dts: imx6ul: Add DTS for liteSOM module
From: Marcin Niestroj @ 2016-09-12 11:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5Cp_ihOa9Z1r5_NiDqiGB+ZfpUn4n5xG95DMA27T=WX0A@mail.gmail.com>
On 12.09.2016 12:36, Fabio Estevam wrote:
> On Mon, Sep 12, 2016 at 5:34 AM, Marcin Niestroj
> <m.niestroj@grinn-global.com> wrote:
>
>>> Is it possible to use a dual GPLv2/X11 license?
>>
>> It is possible. But why should we do that?
>
> So that non-Linux users could reuse the dts. There are many dual
> licence examples in arch/arm/boot/dts.
We are including imx6ul.dtsi which is GPLv2 only. Do you plan to
relicense it?
What do you mean by non-Linux users? What other projects are using dts?
--
Marcin Niestroj
^ permalink raw reply
* [PATCH v5 2/3] mfd: add support for Allwinner SoCs ADC
From: Quentin Schulz @ 2016-09-12 11:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160912095923.GD1873@dell>
On 12/09/2016 11:59, Lee Jones wrote:
> On Mon, 12 Sep 2016, Quentin Schulz wrote:
>
>> On 12/09/2016 11:18, Lee Jones wrote:
>>> On Thu, 08 Sep 2016, Quentin Schulz wrote:
>>>
>> [...]
>
> [...]
>
>>>> +++ b/drivers/mfd/sun4i-gpadc-mfd.c
>
> [...]
>
>>>> +static struct mfd_cell sun4i_gpadc_mfd_cells[] = {
>>>> + {
>>>> + .name = "sun4i-a10-gpadc-iio",
>>>> + .resources = adc_resources,
>>>> + .num_resources = ARRAY_SIZE(adc_resources),
>>>> + }, {
>>>> + .name = "iio_hwmon",
>>>> + }
>>>
>>> Single line please
>>>
>>> { .name = "iio_hwmon" }
>>>
>>
>> + {
>> + .name = "sun4i-a10-gpadc-iio",
>> + .resources = adc_resources,
>> + .num_resources = ARRAY_SIZE(adc_resources),
>> + }, { .name = "iio_hwmon" }
>>
>> or
>>
>> + {
>> + .name = "sun4i-a10-gpadc-iio",
>> + .resources = adc_resources,
>> + .num_resources = ARRAY_SIZE(adc_resources),
>> + },
>> + { .name = "iio_hwmon" }
>>
>> ?
>
> The latter.
>
> [...]
>
>>>> +static const struct of_device_id sun4i_gpadc_mfd_of_match[] = {
>>>> + {
>>>> + .compatible = "allwinner,sun4i-a10-ts",
>>>> + .data = &sun4i_gpadc_mfd_cells,
>>>> + }, {
>>>> + .compatible = "allwinner,sun5i-a13-ts",
>>>> + .data = &sun5i_gpadc_mfd_cells,
>>>> + }, {
>>>> + .compatible = "allwinner,sun6i-a31-ts",
>>>> + .data = &sun6i_gpadc_mfd_cells,
>>>> + }, { /* sentinel */ }
>>>> +};
>>>
>>> Don't mix OF and MFD functionality.
>>>
>>> Why don't you create a node for "iio_hwmon" and have
>>> platform_of_populate() do your bidding?
>>>
>>
>> We are using a stable binding which we cannot modify. This means, the DT
>> in its current state can only be modified to add features, which is not
>> the case of this driver (it is a rewriting of an existing driver which
>> uses the rtp node).
>
> Then use .data = <defined model ID> and set up a switch() in .probe().
>
>>>> +static int sun4i_gpadc_mfd_probe(struct platform_device *pdev)
>>>
>>> Remove all mention of "mfd" from this file.
>>>
>>> (Accept the calls to the MFD API of course).
>>>
>> [...]
>>>> +
>>>> +MODULE_DEVICE_TABLE(of, sun4i_gpadc_mfd_of_match);
>>>
>>> Place this directly under the table.
>>>
>>>> +static struct platform_driver sun4i_gpadc_mfd_driver = {
>>>> + .driver = {
>>>> + .name = "sun4i-adc-mfd",
>>>> + .of_match_table = of_match_ptr(sun4i_gpadc_mfd_of_match),
>>>> + },
>>>> + .probe = sun4i_gpadc_mfd_probe,
>>>
>>> No .remove?
>>>
>>
>> No, everything in probe is handled with devm functions.
>
> Don't you need to undo the register write you did?
>
The regmap_write I use is there to disable all interrupts on hardware
side before the irq_chip handles all interrupts by itself. The
interrupts are not used in the MFD driver.
Thus, I chose to disable the hardware interrupts in the remove function
of drivers using the interrupts (only the IIO yet but the touchscreen
driver later also which will be using a third interrupt). When the MFD
driver is removed, the MFD cells will all be removed, thus calling their
own remove functions, thus disabling hardware interrupts used in each
driver. So the hardware interrupts disabling would be called twice.
Quentin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160912/4f94c3f0/attachment.sig>
^ permalink raw reply
* [PATCH V2 10/10] PM / Domains: Add support for removing nested PM domains by provider
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
If a device supports PM domains that are subdomains of another PM
domain, then the PM domains should be removed in reverse order to
ensure that the subdomains are removed first. Furthermore, if there is
more than one provider, then there needs to be a way to remove the
domains in reverse order for a specific provider.
Add the function of_genpd_remove_last() to remove the last PM domain
added by a given PM domain provider and return the generic_pm_domain
structure for the PM domain that was removed.
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
drivers/base/power/domain.c | 35 +++++++++++++++++++++++++++++++++++
include/linux/pm_domain.h | 7 +++++++
2 files changed, 42 insertions(+)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 7481e3e316a2..b0cf46dcae73 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1745,6 +1745,41 @@ int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
EXPORT_SYMBOL_GPL(of_genpd_add_subdomain);
/**
+ * of_genpd_remove_last - Remove the last PM domain registered for a provider
+ * @provider: Pointer to device structure associated with provider
+ *
+ * Find the last PM domain that was added by a particular provider and
+ * remove this PM domain from the list of PM domains. The provider is
+ * identified by the 'provider' device structure that is passed. The PM
+ * domain will only be removed, if the provider associated with domain
+ * has been removed.
+ *
+ * Returns a valid pointer to struct generic_pm_domain on success or
+ * ERR_PTR() on failure.
+ */
+struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
+{
+ struct generic_pm_domain *gpd, *genpd = ERR_PTR(-ENOENT);
+ int ret;
+
+ if (IS_ERR_OR_NULL(np))
+ return ERR_PTR(-EINVAL);
+
+ mutex_lock(&gpd_list_lock);
+ list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
+ if (gpd->provider == &np->fwnode) {
+ ret = genpd_remove(gpd);
+ genpd = ret ? ERR_PTR(ret) : gpd;
+ break;
+ }
+ }
+ mutex_unlock(&gpd_list_lock);
+
+ return genpd;
+}
+EXPORT_SYMBOL_GPL(of_genpd_remove_last);
+
+/**
* genpd_dev_pm_detach - Detach a device from its PM domain.
* @dev: Device to detach.
* @power_off: Currently not used
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 85f7d53a9827..a09fe5c009c8 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -204,6 +204,7 @@ extern int of_genpd_add_device(struct of_phandle_args *args,
struct device *dev);
extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
struct of_phandle_args *new_subdomain);
+extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
int genpd_dev_pm_attach(struct device *dev);
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -237,6 +238,12 @@ static inline int genpd_dev_pm_attach(struct device *dev)
{
return -ENODEV;
}
+
+static inline
+struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
+{
+ return ERR_PTR(-ENOTSUPP);
+}
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
#ifdef CONFIG_PM
--
2.1.4
^ permalink raw reply related
* [PATCH V2 09/10] PM / Domains: Add support for removing PM domains
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
The genpd framework allows users to add PM domains via the pm_genpd_init()
function, however, there is no corresponding function to remove a PM
domain. For most devices this may be fine as the PM domains are never
removed, however, for devices that wish to populate the PM domains from
within a driver, having the ability to remove a PM domain if the probing
of the device fails or the driver is unloaded is necessary.
Add the function pm_genpd_remove() to remove a PM domain by referencing
it's generic_pm_domain structure. Note that the bulk of the code that
removes the PM domain is placed in a separate local function
genpd_remove() (which is called by pm_genpd_remove()). The code is
structured in this way to prepare for adding another function to remove
a PM domain by provider that will also call genpd_remove(). Note that
users of genpd_remove() must call this function with the mutex,
gpd_list_lock, held.
PM domains can only be removed if the associated provider has been
removed, they are not a parent domain to another PM domain and have no
devices associated with them.
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
drivers/base/power/domain.c | 60 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/pm_domain.h | 5 ++++
2 files changed, 65 insertions(+)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index d5135caa84db..7481e3e316a2 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1358,6 +1358,66 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
}
EXPORT_SYMBOL_GPL(pm_genpd_init);
+static int genpd_remove(struct generic_pm_domain *genpd)
+{
+ struct gpd_link *l, *link;
+
+ if (IS_ERR_OR_NULL(genpd))
+ return -EINVAL;
+
+ mutex_lock(&genpd->lock);
+
+ if (genpd->has_provider) {
+ mutex_unlock(&genpd->lock);
+ pr_err("Provider present, unable to remove %s\n", genpd->name);
+ return -EBUSY;
+ }
+
+ if (!list_empty(&genpd->master_links) || genpd->device_count) {
+ mutex_unlock(&genpd->lock);
+ pr_err("%s: unable to remove %s\n", __func__, genpd->name);
+ return -EBUSY;
+ }
+
+ list_for_each_entry_safe(link, l, &genpd->slave_links, slave_node) {
+ list_del(&link->master_node);
+ list_del(&link->slave_node);
+ kfree(link);
+ }
+
+ list_del(&genpd->gpd_list_node);
+ mutex_unlock(&genpd->lock);
+ cancel_work_sync(&genpd->power_off_work);
+ pr_debug("%s: removed %s\n", __func__, genpd->name);
+
+ return 0;
+}
+
+/**
+ * pm_genpd_remove - Remove a generic I/O PM domain
+ * @genpd: Pointer to PM domain that is to be removed.
+ *
+ * To remove the PM domain, this function:
+ * - Removes the PM domain as a subdomain to any parent domains,
+ * if it was added.
+ * - Removes the PM domain from the list of registered PM domains.
+ *
+ * The PM domain will only be removed, if the associated provider has
+ * been removed, it is not a parent to any other PM domain and has no
+ * devices associated with it.
+ */
+int pm_genpd_remove(struct generic_pm_domain *genpd)
+{
+ int ret;
+
+ mutex_lock(&gpd_list_lock);
+ ret = genpd_remove(genpd);
+ mutex_unlock(&gpd_list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pm_genpd_remove);
+
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 554f8915c691..85f7d53a9827 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -130,6 +130,7 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *target);
extern int pm_genpd_init(struct generic_pm_domain *genpd,
struct dev_power_governor *gov, bool is_off);
+extern int pm_genpd_remove(struct generic_pm_domain *genpd);
extern struct dev_power_governor simple_qos_governor;
extern struct dev_power_governor pm_domain_always_on_gov;
@@ -165,6 +166,10 @@ static inline int pm_genpd_init(struct generic_pm_domain *genpd,
{
return -ENOSYS;
}
+static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
+{
+ return -ENOTSUPP;
+}
#endif
static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
--
2.1.4
^ permalink raw reply related
* [PATCH V2 08/10] PM / Domains: Store the provider in the PM domain structure
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
It is possible that a device has more than one provider of PM domains
and to support the removal of a PM domain by provider, it is necessary
to store a reference to the provider in the PM domain structure.
Therefore, store a reference to the firmware node handle in the PM
domain structure and populate it when providers (only device-tree based
providers are currently supported by PM domains) are registered.
Please note that when removing PM domains, it is necessary to verify
that the PM domain provider has been removed from the list of providers
before the PM domain can be removed. To do this add another member to
the PM domain structure that indicates if the provider is present and
set this member accordingly when providers are added and removed.
Initialise the 'provider' and 'has_provider' members of the
generic_pm_domain structure when a PM domains is added by calling
pm_genpd_init().
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
drivers/base/power/domain.c | 42 +++++++++++++++++++++++++++++++++++++-----
include/linux/pm_domain.h | 2 ++
2 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 1bd8d412db06..d5135caa84db 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1306,6 +1306,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
genpd->device_count = 0;
genpd->max_off_time_ns = -1;
genpd->max_off_time_changed = true;
+ genpd->provider = NULL;
+ genpd->has_provider = false;
genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
genpd->domain.ops.runtime_resume = genpd_runtime_resume;
genpd->domain.ops.prepare = pm_genpd_prepare;
@@ -1491,6 +1493,11 @@ int of_genpd_add_provider_simple(struct device_node *np,
if (pm_genpd_present(genpd))
ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
+ if (!ret) {
+ genpd->provider = &np->fwnode;
+ genpd->has_provider = true;
+ }
+
mutex_unlock(&gpd_list_lock);
return ret;
@@ -1506,7 +1513,7 @@ int of_genpd_add_provider_onecell(struct device_node *np,
struct genpd_onecell_data *data)
{
unsigned int i;
- int ret;
+ int ret = -EINVAL;
if (!np || !data)
return -EINVAL;
@@ -1514,13 +1521,26 @@ int of_genpd_add_provider_onecell(struct device_node *np,
mutex_lock(&gpd_list_lock);
for (i = 0; i < data->num_domains; i++) {
- if (!pm_genpd_present(data->domains[i])) {
- mutex_unlock(&gpd_list_lock);
- return -EINVAL;
- }
+ if (!pm_genpd_present(data->domains[i]))
+ goto error;
+
+ data->domains[i]->provider = &np->fwnode;
+ data->domains[i]->has_provider = true;
}
ret = genpd_add_provider(np, genpd_xlate_onecell, data);
+ if (ret < 0)
+ goto error;
+
+ mutex_unlock(&gpd_list_lock);
+
+ return 0;
+
+error:
+ while (i--) {
+ data->domains[i]->provider = NULL;
+ data->domains[i]->has_provider = false;
+ }
mutex_unlock(&gpd_list_lock);
@@ -1535,10 +1555,21 @@ EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);
void of_genpd_del_provider(struct device_node *np)
{
struct of_genpd_provider *cp;
+ struct generic_pm_domain *gpd;
+ mutex_lock(&gpd_list_lock);
mutex_lock(&of_genpd_mutex);
list_for_each_entry(cp, &of_genpd_providers, link) {
if (cp->node == np) {
+ /*
+ * For each PM domain associated with the
+ * provider, set the 'has_provider' to false
+ * so that the PM domain can be safely removed.
+ */
+ list_for_each_entry(gpd, &gpd_list, gpd_list_node)
+ if (gpd->provider == &np->fwnode)
+ gpd->has_provider = false;
+
list_del(&cp->link);
of_node_put(cp->node);
kfree(cp);
@@ -1546,6 +1577,7 @@ void of_genpd_del_provider(struct device_node *np)
}
}
mutex_unlock(&of_genpd_mutex);
+ mutex_unlock(&gpd_list_lock);
}
EXPORT_SYMBOL_GPL(of_genpd_del_provider);
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index f103869db443..554f8915c691 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -51,6 +51,8 @@ struct generic_pm_domain {
struct mutex lock;
struct dev_power_governor *gov;
struct work_struct power_off_work;
+ struct fwnode_handle *provider; /* Identity of the domain provider */
+ bool has_provider;
const char *name;
atomic_t sd_count; /* Number of subdomains with power "on" */
enum gpd_status status; /* Current state of the domain */
--
2.1.4
^ permalink raw reply related
* [PATCH V2 07/10] PM / Domains: Prepare for adding support to remove PM domains
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
In order to remove PM domains safely from the list of PM domains,
it is necessary to adding locking for the PM domain list around any
places where devices or subdomains are added to a PM domain.
There are places where a reference to a PM domain is obtained via
calling of_genpd_get_from_provider() before adding the device or the
subdomain. In these cases a lock for the PM domain list needs to be
held around the call to of_genpd_get_from_provider() and the call to
add the device/subdomain. To avoid deadlocks by multiple attempts to
obtain the PM domain list lock, add functions genpd_add_device() and
genpd_add_subdomain() which require the user to hold the PM domain
list lock when calling.
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/base/power/domain.c | 97 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 73 insertions(+), 24 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index fc9f11c26eec..1bd8d412db06 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1060,14 +1060,8 @@ static void genpd_free_dev_data(struct device *dev,
dev_pm_put_subsys_data(dev);
}
-/**
- * __pm_genpd_add_device - Add a device to an I/O PM domain.
- * @genpd: PM domain to add the device to.
- * @dev: Device to be added.
- * @td: Set of PM QoS timing parameters to attach to the device.
- */
-int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
- struct gpd_timing_data *td)
+static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
+ struct gpd_timing_data *td)
{
struct generic_pm_domain_data *gpd_data;
int ret = 0;
@@ -1107,6 +1101,24 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
return ret;
}
+
+/**
+ * __pm_genpd_add_device - Add a device to an I/O PM domain.
+ * @genpd: PM domain to add the device to.
+ * @dev: Device to be added.
+ * @td: Set of PM QoS timing parameters to attach to the device.
+ */
+int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
+ struct gpd_timing_data *td)
+{
+ int ret;
+
+ mutex_lock(&gpd_list_lock);
+ ret = genpd_add_device(genpd, dev, td);
+ mutex_unlock(&gpd_list_lock);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(__pm_genpd_add_device);
/**
@@ -1160,13 +1172,8 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
}
EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
-/**
- * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
- * @genpd: Master PM domain to add the subdomain to.
- * @subdomain: Subdomain to be added.
- */
-int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
- struct generic_pm_domain *subdomain)
+static int genpd_add_subdomain(struct generic_pm_domain *genpd,
+ struct generic_pm_domain *subdomain)
{
struct gpd_link *link, *itr;
int ret = 0;
@@ -1209,6 +1216,23 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
kfree(link);
return ret;
}
+
+/**
+ * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
+ * @genpd: Master PM domain to add the subdomain to.
+ * @subdomain: Subdomain to be added.
+ */
+int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
+ struct generic_pm_domain *subdomain)
+{
+ int ret;
+
+ mutex_lock(&gpd_list_lock);
+ ret = genpd_add_subdomain(genpd, subdomain);
+ mutex_unlock(&gpd_list_lock);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
/**
@@ -1571,12 +1595,22 @@ static struct generic_pm_domain *genpd_get_from_provider(
int of_genpd_add_device(struct of_phandle_args *genpdspec, struct device *dev)
{
struct generic_pm_domain *genpd;
+ int ret;
+
+ mutex_lock(&gpd_list_lock);
genpd = genpd_get_from_provider(genpdspec);
- if (IS_ERR(genpd))
- return PTR_ERR(genpd);
+ if (IS_ERR(genpd)) {
+ ret = PTR_ERR(genpd);
+ goto out;
+ }
+
+ ret = genpd_add_device(genpd, dev, NULL);
- return pm_genpd_add_device(genpd, dev);
+out:
+ mutex_unlock(&gpd_list_lock);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(of_genpd_add_device);
@@ -1593,16 +1627,28 @@ int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
struct of_phandle_args *subdomain_spec)
{
struct generic_pm_domain *parent, *subdomain;
+ int ret;
+
+ mutex_lock(&gpd_list_lock);
parent = genpd_get_from_provider(parent_spec);
- if (IS_ERR(parent))
- return PTR_ERR(parent);
+ if (IS_ERR(parent)) {
+ ret = PTR_ERR(parent);
+ goto out;
+ }
subdomain = genpd_get_from_provider(subdomain_spec);
- if (IS_ERR(subdomain))
- return PTR_ERR(subdomain);
+ if (IS_ERR(subdomain)) {
+ ret = PTR_ERR(subdomain);
+ goto out;
+ }
+
+ ret = genpd_add_subdomain(parent, subdomain);
- return pm_genpd_add_subdomain(parent, subdomain);
+out:
+ mutex_unlock(&gpd_list_lock);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(of_genpd_add_subdomain);
@@ -1701,9 +1747,11 @@ int genpd_dev_pm_attach(struct device *dev)
return -ENOENT;
}
+ mutex_lock(&gpd_list_lock);
pd = genpd_get_from_provider(&pd_args);
of_node_put(pd_args.np);
if (IS_ERR(pd)) {
+ mutex_unlock(&gpd_list_lock);
dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
__func__, PTR_ERR(pd));
return -EPROBE_DEFER;
@@ -1712,13 +1760,14 @@ int genpd_dev_pm_attach(struct device *dev)
dev_dbg(dev, "adding to PM domain %s\n", pd->name);
for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
- ret = pm_genpd_add_device(pd, dev);
+ ret = genpd_add_device(pd, dev, NULL);
if (ret != -EAGAIN)
break;
mdelay(i);
cond_resched();
}
+ mutex_unlock(&gpd_list_lock);
if (ret < 0) {
dev_err(dev, "failed to add to PM domain %s: %d",
--
2.1.4
^ permalink raw reply related
* [PATCH V2 06/10] PM / Domains: Verify the PM domain is present when adding a provider
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
When a PM domain provider is added, there is currently no way to tell if
any PM domains associated with the provider are present. Naturally, the
PM domain provider should not be registered if the PM domains have not
been added. Nonetheless, verify that the PM domain(s) associated with a
provider are present when registering the PM domain provider.
This change adds a dependency on the function pm_genpd_present() when
CONFIG_PM_GENERIC_DOMAINS_OF is enabled and so ensure this function is
available when CONFIG_PM_GENERIC_DOMAINS_OF selected.
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/base/power/domain.c | 41 ++++++++++++++++++++++++++++++++++++++---
1 file changed, 38 insertions(+), 3 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index c93aa3a64839..fc9f11c26eec 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -586,7 +586,7 @@ static int __init genpd_poweroff_unused(void)
}
late_initcall(genpd_poweroff_unused);
-#ifdef CONFIG_PM_SLEEP
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_GENERIC_DOMAINS_OF)
/**
* pm_genpd_present - Check if the given PM domain has been initialized.
@@ -606,6 +606,10 @@ static bool pm_genpd_present(const struct generic_pm_domain *genpd)
return false;
}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+
static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
struct device *dev)
{
@@ -1453,7 +1457,19 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
int of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
{
- return genpd_add_provider(np, genpd_xlate_simple, genpd);
+ int ret = -EINVAL;
+
+ if (!np || !genpd)
+ return -EINVAL;
+
+ mutex_lock(&gpd_list_lock);
+
+ if (pm_genpd_present(genpd))
+ ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
+
+ mutex_unlock(&gpd_list_lock);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple);
@@ -1465,7 +1481,26 @@ EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple);
int of_genpd_add_provider_onecell(struct device_node *np,
struct genpd_onecell_data *data)
{
- return genpd_add_provider(np, genpd_xlate_onecell, data);
+ unsigned int i;
+ int ret;
+
+ if (!np || !data)
+ return -EINVAL;
+
+ mutex_lock(&gpd_list_lock);
+
+ for (i = 0; i < data->num_domains; i++) {
+ if (!pm_genpd_present(data->domains[i])) {
+ mutex_unlock(&gpd_list_lock);
+ return -EINVAL;
+ }
+ }
+
+ ret = genpd_add_provider(np, genpd_xlate_onecell, data);
+
+ mutex_unlock(&gpd_list_lock);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);
--
2.1.4
^ permalink raw reply related
* [PATCH V2 05/10] PM / Domains: Don't expose xlate and provider helper functions
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
Functions __of_genpd_xlate_simple(), __of_genpd_xlate_onecell() and
__of_genpd_add_provider() are not used outside of the core generic PM
domain code. Therefore, reduce the number of APIs exposed by making
these static. At the same time don't expose the typedef for
genpd_xlate_t either and make this a local definition as well.
The functions are renamed to follow the naming conventions for static
functions in the generic PM domain core.
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/base/power/domain.c | 49 ++++++++++++++++++++++++++++++++++-----------
include/linux/pm_domain.h | 42 +++++++++++++-------------------------
2 files changed, 51 insertions(+), 40 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index d8c1eabc7117..c93aa3a64839 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1329,6 +1329,10 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
EXPORT_SYMBOL_GPL(pm_genpd_init);
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
+
+typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
+ void *data);
+
/*
* Device Tree based PM domain providers.
*
@@ -1340,8 +1344,8 @@ EXPORT_SYMBOL_GPL(pm_genpd_init);
* maps a PM domain specifier retrieved from the device tree to a PM domain.
*
* Two simple mapping functions have been provided for convenience:
- * - __of_genpd_xlate_simple() for 1:1 device tree node to PM domain mapping.
- * - __of_genpd_xlate_onecell() for mapping of multiple PM domains per node by
+ * - genpd_xlate_simple() for 1:1 device tree node to PM domain mapping.
+ * - genpd_xlate_onecell() for mapping of multiple PM domains per node by
* index.
*/
@@ -1366,7 +1370,7 @@ static LIST_HEAD(of_genpd_providers);
static DEFINE_MUTEX(of_genpd_mutex);
/**
- * __of_genpd_xlate_simple() - Xlate function for direct node-domain mapping
+ * genpd_xlate_simple() - Xlate function for direct node-domain mapping
* @genpdspec: OF phandle args to map into a PM domain
* @data: xlate function private data - pointer to struct generic_pm_domain
*
@@ -1374,7 +1378,7 @@ static DEFINE_MUTEX(of_genpd_mutex);
* have their own device tree nodes. The private data of xlate function needs
* to be a valid pointer to struct generic_pm_domain.
*/
-struct generic_pm_domain *__of_genpd_xlate_simple(
+static struct generic_pm_domain *genpd_xlate_simple(
struct of_phandle_args *genpdspec,
void *data)
{
@@ -1382,10 +1386,9 @@ struct generic_pm_domain *__of_genpd_xlate_simple(
return ERR_PTR(-EINVAL);
return data;
}
-EXPORT_SYMBOL_GPL(__of_genpd_xlate_simple);
/**
- * __of_genpd_xlate_onecell() - Xlate function using a single index.
+ * genpd_xlate_onecell() - Xlate function using a single index.
* @genpdspec: OF phandle args to map into a PM domain
* @data: xlate function private data - pointer to struct genpd_onecell_data
*
@@ -1394,7 +1397,7 @@ EXPORT_SYMBOL_GPL(__of_genpd_xlate_simple);
* A single cell is used as an index into an array of PM domains specified in
* the genpd_onecell_data struct when registering the provider.
*/
-struct generic_pm_domain *__of_genpd_xlate_onecell(
+static struct generic_pm_domain *genpd_xlate_onecell(
struct of_phandle_args *genpdspec,
void *data)
{
@@ -1414,16 +1417,15 @@ struct generic_pm_domain *__of_genpd_xlate_onecell(
return genpd_data->domains[idx];
}
-EXPORT_SYMBOL_GPL(__of_genpd_xlate_onecell);
/**
- * __of_genpd_add_provider() - Register a PM domain provider for a node
+ * genpd_add_provider() - Register a PM domain provider for a node
* @np: Device node pointer associated with the PM domain provider.
* @xlate: Callback for decoding PM domain from phandle arguments.
* @data: Context pointer for @xlate callback.
*/
-int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
- void *data)
+static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
+ void *data)
{
struct of_genpd_provider *cp;
@@ -1442,7 +1444,30 @@ int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
return 0;
}
-EXPORT_SYMBOL_GPL(__of_genpd_add_provider);
+
+/**
+ * of_genpd_add_provider_simple() - Register a simple PM domain provider
+ * @np: Device node pointer associated with the PM domain provider.
+ * @genpd: Pointer to PM domain associated with the PM domain provider.
+ */
+int of_genpd_add_provider_simple(struct device_node *np,
+ struct generic_pm_domain *genpd)
+{
+ return genpd_add_provider(np, genpd_xlate_simple, genpd);
+}
+EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple);
+
+/**
+ * of_genpd_add_provider_onecell() - Register a onecell PM domain provider
+ * @np: Device node pointer associated with the PM domain provider.
+ * @data: Pointer to the data associated with the PM domain provider.
+ */
+int of_genpd_add_provider_onecell(struct device_node *np,
+ struct genpd_onecell_data *data)
+{
+ return genpd_add_provider(np, genpd_xlate_onecell, data);
+}
+EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);
/**
* of_genpd_del_provider() - Remove a previously registered PM domain provider
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index bd411e754f4a..f103869db443 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -187,19 +187,12 @@ struct genpd_onecell_data {
unsigned int num_domains;
};
-typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
- void *data);
-
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
-int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
- void *data);
+int of_genpd_add_provider_simple(struct device_node *np,
+ struct generic_pm_domain *genpd);
+int of_genpd_add_provider_onecell(struct device_node *np,
+ struct genpd_onecell_data *data);
void of_genpd_del_provider(struct device_node *np);
-struct generic_pm_domain *__of_genpd_xlate_simple(
- struct of_phandle_args *genpdspec,
- void *data);
-struct generic_pm_domain *__of_genpd_xlate_onecell(
- struct of_phandle_args *genpdspec,
- void *data);
extern int of_genpd_add_device(struct of_phandle_args *args,
struct device *dev);
extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
@@ -207,15 +200,19 @@ extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
int genpd_dev_pm_attach(struct device *dev);
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
-static inline int __of_genpd_add_provider(struct device_node *np,
- genpd_xlate_t xlate, void *data)
+static inline int of_genpd_add_provider_simple(struct device_node *np,
+ struct generic_pm_domain *genpd)
{
- return 0;
+ return -ENOTSUPP;
+}
+
+static inline int of_genpd_add_provider_onecell(struct device_node *np,
+ struct genpd_onecell_data *data)
+{
+ return -ENOTSUPP;
}
-static inline void of_genpd_del_provider(struct device_node *np) {}
-#define __of_genpd_xlate_simple NULL
-#define __of_genpd_xlate_onecell NULL
+static inline void of_genpd_del_provider(struct device_node *np) {}
static inline int of_genpd_add_device(struct of_phandle_args *args,
struct device *dev)
@@ -235,17 +232,6 @@ static inline int genpd_dev_pm_attach(struct device *dev)
}
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
-static inline int of_genpd_add_provider_simple(struct device_node *np,
- struct generic_pm_domain *genpd)
-{
- return __of_genpd_add_provider(np, __of_genpd_xlate_simple, genpd);
-}
-static inline int of_genpd_add_provider_onecell(struct device_node *np,
- struct genpd_onecell_data *data)
-{
- return __of_genpd_add_provider(np, __of_genpd_xlate_onecell, data);
-}
-
#ifdef CONFIG_PM
extern int dev_pm_domain_attach(struct device *dev, bool power_on);
extern void dev_pm_domain_detach(struct device *dev, bool power_off);
--
2.1.4
^ permalink raw reply related
* [PATCH V2 04/10] PM / Domains: Don't expose generic_pm_domain structure to clients
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
There should be no need to expose the generic_pm_domain structure to
clients and this eliminates the need to implement reference counting for
any external reference to a PM domain. Therefore, make the functions
pm_genpd_lookup_dev() and of_genpd_get_from_provider() private to the
PM domain core. The functions are renamed in accordance with the naming
conventions for genpd static functions.
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/base/power/domain.c | 19 +++++++++----------
include/linux/pm_domain.h | 14 --------------
2 files changed, 9 insertions(+), 24 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index e12d3a8a29a9..d8c1eabc7117 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -45,7 +45,7 @@ static DEFINE_MUTEX(gpd_list_lock);
* and checks that the PM domain pointer is a real generic PM domain.
* Any failure results in NULL being returned.
*/
-struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
+static struct generic_pm_domain *genpd_lookup_dev(struct device *dev)
{
struct generic_pm_domain *genpd = NULL, *gpd;
@@ -1119,7 +1119,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
dev_dbg(dev, "%s()\n", __func__);
- if (!genpd || genpd != pm_genpd_lookup_dev(dev))
+ if (!genpd || genpd != genpd_lookup_dev(dev))
return -EINVAL;
/* The above validation also means we have existing domain_data. */
@@ -1466,7 +1466,7 @@ void of_genpd_del_provider(struct device_node *np)
EXPORT_SYMBOL_GPL(of_genpd_del_provider);
/**
- * of_genpd_get_from_provider() - Look-up PM domain
+ * genpd_get_from_provider() - Look-up PM domain
* @genpdspec: OF phandle args to use for look-up
*
* Looks for a PM domain provider under the node specified by @genpdspec and if
@@ -1476,7 +1476,7 @@ EXPORT_SYMBOL_GPL(of_genpd_del_provider);
* Returns a valid pointer to struct generic_pm_domain on success or ERR_PTR()
* on failure.
*/
-struct generic_pm_domain *of_genpd_get_from_provider(
+static struct generic_pm_domain *genpd_get_from_provider(
struct of_phandle_args *genpdspec)
{
struct generic_pm_domain *genpd = ERR_PTR(-ENOENT);
@@ -1499,7 +1499,6 @@ struct generic_pm_domain *of_genpd_get_from_provider(
return genpd;
}
-EXPORT_SYMBOL_GPL(of_genpd_get_from_provider);
/**
* of_genpd_add_device() - Add a device to an I/O PM domain
@@ -1513,7 +1512,7 @@ int of_genpd_add_device(struct of_phandle_args *genpdspec, struct device *dev)
{
struct generic_pm_domain *genpd;
- genpd = of_genpd_get_from_provider(genpdspec);
+ genpd = genpd_get_from_provider(genpdspec);
if (IS_ERR(genpd))
return PTR_ERR(genpd);
@@ -1535,11 +1534,11 @@ int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
{
struct generic_pm_domain *parent, *subdomain;
- parent = of_genpd_get_from_provider(parent_spec);
+ parent = genpd_get_from_provider(parent_spec);
if (IS_ERR(parent))
return PTR_ERR(parent);
- subdomain = of_genpd_get_from_provider(subdomain_spec);
+ subdomain = genpd_get_from_provider(subdomain_spec);
if (IS_ERR(subdomain))
return PTR_ERR(subdomain);
@@ -1561,7 +1560,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)
unsigned int i;
int ret = 0;
- pd = pm_genpd_lookup_dev(dev);
+ pd = genpd_lookup_dev(dev);
if (!pd)
return;
@@ -1642,7 +1641,7 @@ int genpd_dev_pm_attach(struct device *dev)
return -ENOENT;
}
- pd = of_genpd_get_from_provider(&pd_args);
+ pd = genpd_get_from_provider(&pd_args);
of_node_put(pd_args.np);
if (IS_ERR(pd)) {
dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index e1964a242389..bd411e754f4a 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -116,7 +116,6 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
return to_gpd_data(dev->power.subsys_data->domain_data);
}
-extern struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev);
extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
struct device *dev,
struct gpd_timing_data *td);
@@ -138,10 +137,6 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
{
return ERR_PTR(-ENOSYS);
}
-static inline struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
-{
- return NULL;
-}
static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
struct device *dev,
struct gpd_timing_data *td)
@@ -199,9 +194,6 @@ typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
void *data);
void of_genpd_del_provider(struct device_node *np);
-struct generic_pm_domain *of_genpd_get_from_provider(
- struct of_phandle_args *genpdspec);
-
struct generic_pm_domain *__of_genpd_xlate_simple(
struct of_phandle_args *genpdspec,
void *data);
@@ -222,12 +214,6 @@ static inline int __of_genpd_add_provider(struct device_node *np,
}
static inline void of_genpd_del_provider(struct device_node *np) {}
-static inline struct generic_pm_domain *of_genpd_get_from_provider(
- struct of_phandle_args *genpdspec)
-{
- return NULL;
-}
-
#define __of_genpd_xlate_simple NULL
#define __of_genpd_xlate_onecell NULL
--
2.1.4
^ permalink raw reply related
* [PATCH V2 03/10] staging: board: Remove calls to of_genpd_get_from_provider()
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
Update the staging/board PM domain code to use the
of_genpd_add_subdomain() and remove any calls to
of_genpd_get_from_provider().
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/staging/board/board.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/drivers/staging/board/board.c b/drivers/staging/board/board.c
index 45807d8287d1..86dc41101610 100644
--- a/drivers/staging/board/board.c
+++ b/drivers/staging/board/board.c
@@ -140,7 +140,6 @@ static int board_staging_add_dev_domain(struct platform_device *pdev,
const char *domain)
{
struct of_phandle_args pd_args;
- struct generic_pm_domain *pd;
struct device_node *np;
np = of_find_node_by_path(domain);
@@ -151,14 +150,8 @@ static int board_staging_add_dev_domain(struct platform_device *pdev,
pd_args.np = np;
pd_args.args_count = 0;
- pd = of_genpd_get_from_provider(&pd_args);
- if (IS_ERR(pd)) {
- pr_err("Cannot find genpd %s (%ld)\n", domain, PTR_ERR(pd));
- return PTR_ERR(pd);
- }
- pr_debug("Found genpd %s for device %s\n", pd->name, pdev->name);
- return pm_genpd_add_device(pd, &pdev->dev);
+ return of_genpd_add_device(&pd_args, &pdev->dev);
}
#else
static inline int board_staging_add_dev_domain(struct platform_device *pdev,
--
2.1.4
^ permalink raw reply related
* [PATCH V2 02/10] ARM: EXYNOS: Remove calls to of_genpd_get_from_provider()
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
Update the EXYNOS PM domain code to use the of_genpd_add_subdomain()
and remove any calls to of_genpd_get_from_provider().
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/soc/samsung/pm_domains.c | 23 ++++++++---------------
1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c
index 4822346aadc6..7112004b8032 100644
--- a/drivers/soc/samsung/pm_domains.c
+++ b/drivers/soc/samsung/pm_domains.c
@@ -215,29 +215,22 @@ static __init int exynos4_pm_init_power_domain(void)
/* Assign the child power domains to their parents */
for_each_matching_node(np, exynos_pm_domain_of_match) {
- struct generic_pm_domain *child_domain, *parent_domain;
- struct of_phandle_args args;
+ struct of_phandle_args child, parent;
- args.np = np;
- args.args_count = 0;
- child_domain = of_genpd_get_from_provider(&args);
- if (IS_ERR(child_domain))
- continue;
+ child.np = np;
+ child.args_count = 0;
if (of_parse_phandle_with_args(np, "power-domains",
- "#power-domain-cells", 0, &args) != 0)
- continue;
-
- parent_domain = of_genpd_get_from_provider(&args);
- if (IS_ERR(parent_domain))
+ "#power-domain-cells", 0,
+ &parent) != 0)
continue;
- if (pm_genpd_add_subdomain(parent_domain, child_domain))
+ if (of_genpd_add_subdomain(&parent, &child))
pr_warn("%s failed to add subdomain: %s\n",
- parent_domain->name, child_domain->name);
+ parent.np->name, child.np->name);
else
pr_info("%s has as child subdomain: %s.\n",
- parent_domain->name, child_domain->name);
+ parent.np->name, child.np->name);
}
return 0;
--
2.1.4
^ permalink raw reply related
* [PATCH V2 01/10] PM / Domains: Add new helper functions for device-tree
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com>
Ideally, if we are returning a reference to a PM domain via a call to
of_genpd_get_from_provider(), then we should keep track of such
references via a reference count. The reference count could then be used
to determine if a PM domain can be safely removed. Alternatively, it is
possible to avoid such external references by providing APIs to access
the PM domain and hence, eliminate any calls to
of_genpd_get_from_provider().
Add new helper functions for adding a device and a subdomain to a PM
domain when using device-tree, so that external calls to
of_genpd_get_from_provider() can be removed.
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/base/power/domain.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/pm_domain.h | 16 ++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 058c8b6d2871..e12d3a8a29a9 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1502,6 +1502,52 @@ struct generic_pm_domain *of_genpd_get_from_provider(
EXPORT_SYMBOL_GPL(of_genpd_get_from_provider);
/**
+ * of_genpd_add_device() - Add a device to an I/O PM domain
+ * @genpdspec: OF phandle args to use for look-up PM domain
+ * @dev: Device to be added.
+ *
+ * Looks-up an I/O PM domain based upon phandle args provided and adds
+ * the device to the PM domain. Returns a negative error code on failure.
+ */
+int of_genpd_add_device(struct of_phandle_args *genpdspec, struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ genpd = of_genpd_get_from_provider(genpdspec);
+ if (IS_ERR(genpd))
+ return PTR_ERR(genpd);
+
+ return pm_genpd_add_device(genpd, dev);
+}
+EXPORT_SYMBOL_GPL(of_genpd_add_device);
+
+/**
+ * of_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
+ * @parent_spec: OF phandle args to use for parent PM domain look-up
+ * @subdomain_spec: OF phandle args to use for subdomain look-up
+ *
+ * Looks-up a parent PM domain and subdomain based upon phandle args
+ * provided and adds the subdomain to the parent PM domain. Returns a
+ * negative error code on failure.
+ */
+int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
+ struct of_phandle_args *subdomain_spec)
+{
+ struct generic_pm_domain *parent, *subdomain;
+
+ parent = of_genpd_get_from_provider(parent_spec);
+ if (IS_ERR(parent))
+ return PTR_ERR(parent);
+
+ subdomain = of_genpd_get_from_provider(subdomain_spec);
+ if (IS_ERR(subdomain))
+ return PTR_ERR(subdomain);
+
+ return pm_genpd_add_subdomain(parent, subdomain);
+}
+EXPORT_SYMBOL_GPL(of_genpd_add_subdomain);
+
+/**
* genpd_dev_pm_detach - Detach a device from its PM domain.
* @dev: Device to detach.
* @power_off: Currently not used
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 31fec858088c..e1964a242389 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -208,6 +208,10 @@ struct generic_pm_domain *__of_genpd_xlate_simple(
struct generic_pm_domain *__of_genpd_xlate_onecell(
struct of_phandle_args *genpdspec,
void *data);
+extern int of_genpd_add_device(struct of_phandle_args *args,
+ struct device *dev);
+extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
+ struct of_phandle_args *new_subdomain);
int genpd_dev_pm_attach(struct device *dev);
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -227,6 +231,18 @@ static inline struct generic_pm_domain *of_genpd_get_from_provider(
#define __of_genpd_xlate_simple NULL
#define __of_genpd_xlate_onecell NULL
+static inline int of_genpd_add_device(struct of_phandle_args *args,
+ struct device *dev)
+{
+ return -ENODEV;
+}
+
+static inline int of_genpd_add_subdomain(struct of_phandle_args *parent,
+ struct of_phandle_args *new_subdomain)
+{
+ return -ENODEV;
+}
+
static inline int genpd_dev_pm_attach(struct device *dev)
{
return -ENODEV;
--
2.1.4
^ permalink raw reply related
* [PATCH V2 00/10] PM / Domains: Add support for removing PM domains
From: Jon Hunter @ 2016-09-12 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In order to safely remove PM domains there are a few changes that need to be
made to ensure that no one is holding an external reference to a PM domain
after it has been removed. One solution, implemented here, solves this by
eliminating external references to PM domain.
Changes from V1:
- Added test when removing a PM domain to ensure the PM domain provider
has been removed.
- Re-organised patches 8-10 so that patch #8 adds the code to verify if
the provider is present, patch #9 adds basic support for removing PM
domains and patch #10 adds support for removing PM domains by provider.
Changes from initial RFC:
- Renamed functions made static per Ulf's feedback.
- Added patch to clean-up provider/xlate APIs per Ulf's feedback
- Re-worked and simplified the association between PM domains and PM
domain providers. Dropped the 'provider_data' variable from the
generic_pm_domain structure in favour of using the fwnode_handle.
- Split patch for removing PM domains into multiple patches per Ulf's
feedback.
Jon Hunter (10):
PM / Domains: Add new helper functions for device-tree
ARM: EXYNOS: Remove calls to of_genpd_get_from_provider()
staging: board: Remove calls to of_genpd_get_from_provider()
PM / Domains: Don't expose generic_pm_domain structure to clients
PM / Domains: Don't expose xlate and provider helper functions
PM / Domains: Verify the PM domain is present when adding a provider
PM / Domains: Prepare for adding support to remove PM domains
PM / Domains: Store the provider in the PM domain structure
PM / Domains: Add support for removing PM domains
PM / Domains: Add support for removing nested PM domains by provider
drivers/base/power/domain.c | 353 +++++++++++++++++++++++++++++++++++----
drivers/soc/samsung/pm_domains.c | 23 +--
drivers/staging/board/board.c | 9 +-
include/linux/pm_domain.h | 74 ++++----
4 files changed, 364 insertions(+), 95 deletions(-)
--
2.1.4
^ permalink raw reply
* [PATCH v5 2/3] mfd: add support for Allwinner SoCs ADC
From: Quentin Schulz @ 2016-09-12 10:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160912104932.GF1873@dell>
On 12/09/2016 12:49, Lee Jones wrote:
> On Mon, 12 Sep 2016, Maxime Ripard wrote:
>
>> On Mon, Sep 12, 2016 at 10:59:23AM +0100, Lee Jones wrote:
>>>>>> +static const struct of_device_id sun4i_gpadc_mfd_of_match[] = {
>>>>>> + {
>>>>>> + .compatible = "allwinner,sun4i-a10-ts",
>>>>>> + .data = &sun4i_gpadc_mfd_cells,
>>>>>> + }, {
>>>>>> + .compatible = "allwinner,sun5i-a13-ts",
>>>>>> + .data = &sun5i_gpadc_mfd_cells,
>>>>>> + }, {
>>>>>> + .compatible = "allwinner,sun6i-a31-ts",
>>>>>> + .data = &sun6i_gpadc_mfd_cells,
>>>>>> + }, { /* sentinel */ }
>>>>>> +};
>>>>>
>>>>> Don't mix OF and MFD functionality.
>>>>>
>>>>> Why don't you create a node for "iio_hwmon" and have
>>>>> platform_of_populate() do your bidding?
>>>>>
>>>>
>>>> We are using a stable binding which we cannot modify. This means, the DT
>>>> in its current state can only be modified to add features, which is not
>>>> the case of this driver (it is a rewriting of an existing driver which
>>>> uses the rtp node).
>>>
>>> Then use .data = <defined model ID> and set up a switch() in .probe().
>>
>> Uh? Why? It just adds a non-standard indirection, while using
>> of_match_device is very standard, and used extensively in Linux.
>
> You still use of_match_device() to obtain the ID.
>
> The "don't mix DT with the MFD API" is there to prevent some of the
> nasty hacks I've seen previously. This particular example doesn't
> seem so bad, but it's a gateway to ridiculous hackery!
>
How am I supposed to get the .data without of_match_node then?
What's more hackish in using .data field for specific data for each
compatible than in using a random ID in .data and switching on it? The
result is exactly the same, the switching case being more verbose and
adding complexity to something that can be done in a straightforward manner.
Quentin
^ permalink raw reply
* [PATCHv2 3/3] tty/serial: at91: fix hardware handshake on SAM9x5 (without GPIOs)
From: Richard Genoud @ 2016-09-12 10:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160912095317.74e5xiedrq5nh3v4@piout.net>
2016-09-12 11:53 GMT+02:00 Alexandre Belloni
<alexandre.belloni@free-electrons.com>:
> On 12/09/2016 at 11:47:33 +0200, Richard Genoud wrote :
>> Commit 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when
>> hardware handshake is enabled") broke the hardware handshake on SAM9x5
>> platforms.
>>
>> On Atmel platforms, the USART can only handle the handware handshake
>> (ATMEL_US_USMODE_HWHS) if FIFOs or PDC are used.
>>
>> Thus, ATMEL_US_USMODE_HWHS mode should only be used in this case.
>>
>> For SAM9x5, there's no FIFOs nor PDC for the USART, so the mode should
>> be ATMEL_US_USMODE_NORMAL and the RTS pin should be controlled by the
>> driver.
>>
>> NB: -stable is not Cced because it doesn't cleanly apply on 4.1+
>>
>> Tested on SAM9G35-CM with and without DMA
>>
>> Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
>> Fixes: 1cf6e8fc8341 ("tty/serial: at91: fix RTS line management when hardware handshake is enabled")
>> ---
>> drivers/tty/serial/atmel_serial.c | 18 +++++++++++-------
>> 1 file changed, 11 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
>> index e9b4fbf88c2d..32154e7231ce 100644
>> --- a/drivers/tty/serial/atmel_serial.c
>> +++ b/drivers/tty/serial/atmel_serial.c
>> @@ -2130,15 +2130,19 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>> } else if ((termios->c_cflag & CRTSCTS) &&
>> !mctrl_gpio_use_rtscts(atmel_port->gpios)) {
>> /*
>> - * RS232 with hardware handshake (RTS/CTS)
>> - * handled by the controller.
>> + * Automatic hardware handshake (RTS/CTS) only work with
>> + * FIFOs or PDC.
>> + * Meaning that on SAM9x5 the controller can't handle
>> + * the hardware handshake (no FIFOs nor PDC on these platforms).
>> */
>> - if (atmel_use_dma_rx(port) && !atmel_use_fifo(port)) {
>> - dev_info(port->dev, "not enabling hardware flow control because DMA is used");
>> - termios->c_cflag &= ~CRTSCTS;
>> - } else {
>> + if (atmel_use_pdc_rx(port) || atmel_use_fifo(port))
>> mode |= ATMEL_US_USMODE_HWHS;
>> - }
>> + else
>> + /*
>> + * The hardware handshake won't be handle by the
>> + * controller but by the driver.
>> + */
>> + mode |= ATMEL_US_USMODE_NORMAL;
>
> You still need the case where HWHS is impossible and there are no gpio
> configured. You need to inform userspace that the configuration was not
> applied instead of silently ignoring the error.
Could you explain which case it is ?
The only one I can see is when there's no GPIO declared for RTS/CTS
AND, there's no pin muxed for RTS/CTS either.
Have you got another example in mind ?
>
>> } else {
>> /* RS232 without hadware handshake or controlled by GPIOs */
>> mode |= ATMEL_US_USMODE_NORMAL;
>
> --
> Alexandre Belloni, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
--
for me, ck means con kolivas and not calvin klein... does it mean I'm a geek ?
^ permalink raw reply
* [PATCH v5 2/3] mfd: add support for Allwinner SoCs ADC
From: Lee Jones @ 2016-09-12 10:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160912100719.GJ9449@lukather>
On Mon, 12 Sep 2016, Maxime Ripard wrote:
> On Mon, Sep 12, 2016 at 10:59:23AM +0100, Lee Jones wrote:
> > > >> +static const struct of_device_id sun4i_gpadc_mfd_of_match[] = {
> > > >> + {
> > > >> + .compatible = "allwinner,sun4i-a10-ts",
> > > >> + .data = &sun4i_gpadc_mfd_cells,
> > > >> + }, {
> > > >> + .compatible = "allwinner,sun5i-a13-ts",
> > > >> + .data = &sun5i_gpadc_mfd_cells,
> > > >> + }, {
> > > >> + .compatible = "allwinner,sun6i-a31-ts",
> > > >> + .data = &sun6i_gpadc_mfd_cells,
> > > >> + }, { /* sentinel */ }
> > > >> +};
> > > >
> > > > Don't mix OF and MFD functionality.
> > > >
> > > > Why don't you create a node for "iio_hwmon" and have
> > > > platform_of_populate() do your bidding?
> > > >
> > >
> > > We are using a stable binding which we cannot modify. This means, the DT
> > > in its current state can only be modified to add features, which is not
> > > the case of this driver (it is a rewriting of an existing driver which
> > > uses the rtp node).
> >
> > Then use .data = <defined model ID> and set up a switch() in .probe().
>
> Uh? Why? It just adds a non-standard indirection, while using
> of_match_device is very standard, and used extensively in Linux.
You still use of_match_device() to obtain the ID.
The "don't mix DT with the MFD API" is there to prevent some of the
nasty hacks I've seen previously. This particular example doesn't
seem so bad, but it's a gateway to ridiculous hackery!
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH 1/2] ARM: dts: imx6ul: Add DTS for liteSOM module
From: Fabio Estevam @ 2016-09-12 10:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <de2e41be-ad69-ce4b-57fe-3215bc9811ad@grinn-global.com>
On Mon, Sep 12, 2016 at 5:34 AM, Marcin Niestroj
<m.niestroj@grinn-global.com> wrote:
>> Is it possible to use a dual GPLv2/X11 license?
>
> It is possible. But why should we do that?
So that non-Linux users could reuse the dts. There are many dual
licence examples in arch/arm/boot/dts.
^ permalink raw reply
* [PATCH] ARM: decompressor: reset ttbcr fields to use TTBR0 on ARMv7
From: Russell King - ARM Linux @ 2016-09-12 10:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473663420-18629-1-git-send-email-sramana@codeaurora.org>
On Mon, Sep 12, 2016 at 12:27:00PM +0530, Srinivas Ramana wrote:
> If the bootloader uses the long descriptor format and jumps to
> kernel decompressor code, TTBCR may not be in a right state.
> Before enabling the MMU, it is required to clear the TTBCR.PD0
> field to use TTBR0 for translation table walks.
>
> The 'commit dbece45894d3a ("ARM: 7501/1: decompressor:
> reset ttbcr for VMSA ARMv7 cores")' does the reset of TTBCR.N, but
There's no need to single-quote the commit part of this sentence.
> doesn't consider all the bits for the size of TTBCR.N.
>
> Clear TTBCR.PD0 field and reset all the three bits of TTBCR.N to
> indicate the use of TTBR0 and the correct base address width.
>
Adding a properly formatted Fixes: line here would be a bonus if we
need to backport it to stable trees.
> Signed-off-by: Srinivas Ramana <sramana@codeaurora.org>
> ---
> arch/arm/boot/compressed/head.S | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> index af11c2f8f3b7..fc6d541549a2 100644
> --- a/arch/arm/boot/compressed/head.S
> +++ b/arch/arm/boot/compressed/head.S
> @@ -779,7 +779,7 @@ __armv7_mmu_cache_on:
> orrne r0, r0, #1 @ MMU enabled
> movne r1, #0xfffffffd @ domain 0 = client
> bic r6, r6, #1 << 31 @ 32-bit translation system
> - bic r6, r6, #3 << 0 @ use only ttbr0
> + bic r6, r6, #(7 << 0) | (1 << 4) @ use only ttbr0
Provided this is correct (I've not checked, I'd like an ack from one of
the ARM people, and I'd prefer to see a tested-by as well), and the above
points are addressed, it can be dropped into the patch system. Thanks.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently@9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [PATCH 4/5] ARM: dts: exynos: add support for ISP power domain to exynos4x12 clocks device
From: Marek Szyprowski @ 2016-09-12 10:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160908002254.GD13062@codeaurora.org>
Hi Stephen,
On 2016-09-08 02:22, Stephen Boyd wrote:
> On 09/01, Marek Szyprowski wrote:
>> Exynos4412 clock controller contains some additional clocks for FIMC-ISP
>> (Camera ISP) subsystem. Registers for those clocks are partially located
>> in the SOC area, which belongs to ISP power domain.
>>
>> This patch extends clock controller node with ISP clock sub-node and link
>> (phandle) to ISP power domain.
>>
>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> ---
>> arch/arm/boot/dts/exynos4x12.dtsi | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
>> index 3394bdcf10ae..4daea67546b9 100644
>> --- a/arch/arm/boot/dts/exynos4x12.dtsi
>> +++ b/arch/arm/boot/dts/exynos4x12.dtsi
>> @@ -74,6 +74,11 @@
>> compatible = "samsung,exynos4412-clock";
>> reg = <0x10030000 0x20000>;
>> #clock-cells = <1>;
>> +
>> + isp-clock-controller {
>> + compatible = "samsung,exynos4412-isp-clock";
>> + power-domains = <&pd_isp>;
>> + };
> Why can't we extend support in power domains code to have
> multiple domains for a single device node? i.e. power-domains =
> <&pd_isp>, <&pd_foo>, <&pd_bar>, and then pick the right one with
> power-domain-names or something like that? Making a subnode
> (which seems to turn into a child platform device?) seems like a
> quick solution for larger problems.
The larger problem here is the fact that clock controller is partially
located
in different power areas of SoC. Majority of the clock controllers is
located
in the area which is typically always powered (besides system sleep case),
while a few Camera ISP registers are located in the ISP block, which have
separate power domain. Having a separate nodes for sub-parts of the
device is
rather common approach, already practices by some more complex devices.
I see some serious design problems with multiple entries in power domains
property. First how to show that some part of the device IS NOT in any
domain?
The question is how the automated assignment to domains would be handled for
such case?
The second is related to Linux kernel internals. Right now device
drivers are
not aware of the power domains - there are no direct calls to power domains
code, everything is hidden behind runtime pm which does all the hard work.
Similar situation is on Exynos 542x/5800, which will look more or less like
this:
clock: clock-controller at 10010000 {
compatible = "samsung,exynos5420-clock";
reg = <0x10010000 0x30000>;
#clock-cells = <1>;
+
+ gsc-clock-controller {
+ compatible = "samsung,exynos5420-gsc-clock";
+ power-domains = <&gsc_pd>;
+ };
+
+ isp-clock-controller {
+ compatible = "samsung,exynos5420-isp-clock";
+ power-domains = <&isp_pd>;
+ };
+
+ mfc-clock-controller {
+ compatible = "samsung,exynos5420-mfc-clock";
+ power-domains = <&mfc_pd>;
+ };
+
+ msc-clock-controller {
+ compatible = "samsung,exynos5420-msc-clock";
+ power-domains = <&msc_pd>;
+ };
+
+ disp-clock-controller {
+ compatible = "samsung,exynos5420-disp-clock";
+ power-domains = <&disp_pd>;
+ };
};
The patch is not yet ready, so I didn't include it in this patchset.
The clock controller evolved and in the latest Exynos 5433 it is divided in
several parts (each related to given hw block and its power domains), which
each is now modeled by a separate device node. This allows to bind power
domains cleanly without any need for sub-nodes for the clock controllers.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* [PATCHv3 0/3] Devicetree bindings for Ion
From: Greg Kroah-Hartman @ 2016-09-12 10:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1472601869-19469-1-git-send-email-labbott@redhat.com>
On Tue, Aug 30, 2016 at 05:04:26PM -0700, Laura Abbott wrote:
> Hi,
>
> This is a long overdue resend and slight update from the last version[1] of
> Ion devicetree bindings.
>
> The goal here is to keep the Ion bindings minimalist. I experimented with
> dropping all but a dummy devicetree node and just matching on the machine
> name in the platform file. This ends up being a nightmare for the DMA (i.e. CMA)
> heap type. That heap requires a device structure to do its allocation and
> setting up a device structure properly isn't pretty. I have other ideas for
> working with that heap if this gets NAKed.
>
> I've thought about the idea of a devicetree overlay for specifying more
> platform configuration but that a) requires Android actually load the overlay
> at the right time in the framework and b) opens up an entirely new can of
> worms.
>
> In conclusion, if we assume that Ion platform support is something anyone
> actually wants, this is still the least bad and intrusive idea I've come up
> with. There exists hisilicon Ion code but it came in without being fully acked.
> I've converted it over as an example of how it might look.
>
> As always, feedback appreciated.
Give a total lack of feeback, I've now applied these patches :)
thanks,
greg k-h
^ permalink raw reply
* [PATCH 1/5] clk: add support for runtime pm
From: Marek Szyprowski @ 2016-09-12 10:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160908001943.GC13062@codeaurora.org>
Hi Stephen,
On 2016-09-08 02:19, Stephen Boyd wrote:
> On 09/01, Marek Szyprowski wrote:
>> Registers for some clocks might be located in the SOC area, which are under the
>> power domain. To enable access to those registers respective domain has to be
>> turned on. Additionally, registers for such clocks will usually loose its
>> contents when power domain is turned off, so additional saving and restoring of
>> them might be needed in the clock controller driver.
>>
>> This patch adds basic infrastructure in the clocks core to allow implementing
>> driver for such clocks under power domains. Clock provider can supply a
>> struct device pointer, which is the used by clock core for tracking and managing
>> clock's controller runtime pm state. Each clk_prepare() operation
>> will first call pm_runtime_get_sync() on the supplied device, while
>> clk_unprepare() will do pm_runtime_put() at the end.
>>
>> Additional calls to pm_runtime_get/put functions are required to ensure that any
>> register access (like calculating/chaning clock rates) will be done with clock
>> controller in active runtime state.
>>
>> Special handling of the case when runtime pm is disabled for clock controller's
>> device is needed to let this feature work properly also during system sleep
>> suspend/resume operations (runtime pm is first disabled before entering sleep
>> state's, but controller is usually still operational until its suspend pm
>> callback is called).
>>
>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> My "knee jerk" concern is that we're going to take a runtime PM
> lock underneath the prepare lock. That seems like a situation
> where we could hit a lock inversion if the runtime PM callbacks
> themselves acquire the prepare lock by calling clk APIs? But this
> concern is false right? We release the runtime PM lock before
> calling the PM callback, so we shouldn't hit any deadlock and
> lockdep won't complain?
Runtime PM uses fine grained locking based on per-device locks, so there
should be no problem with global clock prepare lock. The only lock
interaction
is between clock controller device's rpm lock and clocks global prepare
lock, but
it always done with the same access pattern. I've tested it extensively
(also
with lock dep) with various use cases and found no problems.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* [PATCH v7 9/9] drm/mediatek: add support for Mediatek SoC MT2701
From: YT Shen @ 2016-09-12 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473226653.11736.33.camel@mtksdaap41>
Hi CK,
On Wed, 2016-09-07 at 13:37 +0800, CK Hu wrote:
> Hi, YT:
>
> On Fri, 2016-09-02 at 19:24 +0800, YT Shen wrote:
> > This patch add support for the Mediatek MT2701 DISP subsystem.
> > There is only one OVL engine in MT2701.
> >
> > Signed-off-by: YT Shen <yt.shen@mediatek.com>
>
> [snip...]
>
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> > index 4b4e449..465819b 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> > @@ -112,6 +112,7 @@ struct mtk_ddp_comp_match {
> >
> > static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
> > [DDP_COMPONENT_AAL] = { MTK_DISP_AAL, 0, NULL },
> > + [DDP_COMPONENT_BLS] = { MTK_DISP_PWM, 0, NULL },
>
> I think BLS is different than PWM, so this statement should be
>
> [DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 0, NULL };
The BLS module actually is a multifunction device, one of them is the
PWM function. We only upstream PWM function [1] now, and it is
accepted. When there are real use case (gamma function), we will update
this part. What do you think?
Regards,
yt.shen
[1] https://patchwork.kernel.org/patch/9223001/
>
>
> > [DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, &ddp_color },
> > [DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, &ddp_color },
> > [DDP_COMPONENT_DPI0] = { MTK_DPI, 0, NULL },
>
> Regards,
> CK
>
>
^ permalink raw reply
* [PATCH v7 4/9] drm/mediatek: update display module connections
From: YT Shen @ 2016-09-12 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473147546.11736.7.camel@mtksdaap41>
Hi CK,
On Tue, 2016-09-06 at 15:39 +0800, CK Hu wrote:
> Hi, YT:
>
> On Fri, 2016-09-02 at 19:24 +0800, YT Shen wrote:
> > update connections for OVL, RDMA, BLS, DSI
> >
> > Signed-off-by: YT Shen <yt.shen@mediatek.com>
> > ---
> > drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 25 +++++++++++++++++++++++++
> > 1 file changed, 25 insertions(+)
> >
>
> [snip...]
>
> > @@ -111,6 +119,9 @@ static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
> > if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
> > *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN;
> > value = OVL0_MOUT_EN_COLOR0;
> > + } else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) {
> > + *addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN;
> > + value = OVL_MOUT_EN_RDMA;
> > } else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) {
> > *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
> > value = OD_MOUT_EN_RDMA0;
> > @@ -148,6 +159,9 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
> > } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
> > *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN;
> > value = COLOR1_SEL_IN_OVL1;
> > + } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
>
> DDP_COMPONENT_BLS is a new symbol which is defined in 9th patch of this
> series. I think the definition of DDP_COMPONENT_BLS should be in front
> of this patch.
OK, we will move the definition to this patch.
Regards,
yt.shen
>
> > + *addr = DISP_REG_CONFIG_DSI_SEL;
> > + value = DSI_SEL_IN_BLS;
> > } else {
> > value = 0;
> > }
> > @@ -155,6 +169,15 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
> > return value;
> > }
> >
>
> Regards,
> CK
>
>
^ permalink raw reply
* [PATCH v7 7/9] drm/mediatek: add dsi transfer function
From: YT Shen @ 2016-09-12 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473215632.11736.21.camel@mtksdaap41>
Hi CK,
On Wed, 2016-09-07 at 10:33 +0800, CK Hu wrote:
> Hi, YT:
>
> On Fri, 2016-09-02 at 19:24 +0800, YT Shen wrote:
> > From: shaoming chen <shaoming.chen@mediatek.com>
> >
> > add dsi read/write commands for transfer function
> >
> > Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
> > ---
> > drivers/gpu/drm/mediatek/mtk_dsi.c | 188 +++++++++++++++++++++++++++++++++++++
> > 1 file changed, 188 insertions(+)
> >
>
> [snip...]
>
> >
> > +static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
> > +{
> > + dsi->irq_data &= ~irq_bit;
> > +}
> > +
>
> [snip...]
>
> > +
> > +static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
> > + unsigned int timeout)
> > +{
> > + s32 ret = 0;
> > + unsigned long jiffies = msecs_to_jiffies(timeout);
> > +
> > + ret = wait_event_interruptible_timeout(_dsi_irq_wait_queue,
> > + dsi->irq_data & irq_flag,
> > + jiffies);
> > + if (ret == 0) {
> > + dev_info(dsi->dev, "Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
> > +
> > + mtk_dsi_enable(dsi);
> > + mtk_dsi_reset_engine(dsi);
> > + }
> > +
> > + return ret;
> > +}
>
> I think mtk_dsi_irq_data_clear() and mtk_dsi_wait_for_irq_done() should
> be moved to the 6th patch [1] of this series because these two functions
> deal the irq control.
We will move mtk_dsi_irq_data_clear() to patch "drm/mediatek: add dsi
interrupt control" and put mtk_dsi_wait_for_irq_done() here, because it
is used in the transfer function.
Regards,
yt.shen
>
>
> [1] https://patchwork.kernel.org/patch/9310819/
>
>
> Regards,
> CK
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox