Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 14/16] cpufreq: Add cpufreq driver for Tegra124
From: Viresh Kumar @ 2014-07-23  4:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405957142-19416-15-git-send-email-ttynkkynen@nvidia.com>

On 21 July 2014 21:09, Tuomas Tynkkynen <ttynkkynen@nvidia.com> wrote:

> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index 7364a53..df3c73e 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> @@ -244,6 +244,7 @@ config ARM_SPEAR_CPUFREQ
>  config ARM_TEGRA_CPUFREQ
>         bool "TEGRA CPUFreq support"
>         depends on ARCH_TEGRA
> +       depends on GENERIC_CPUFREQ_CPU0

Wouldn't this also disturb the existing cpufreq driver for earlier
tegra platforms? i.e. we don't need cpufreq-cpu0 for them
atleast as of now.

>         default y
>         help
>           This adds the CPUFreq driver support for TEGRA SOCs.
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> index db6d9a2..3437d24 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -76,6 +76,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ)      += sa1100-cpufreq.o
>  obj-$(CONFIG_ARM_SA1110_CPUFREQ)       += sa1110-cpufreq.o
>  obj-$(CONFIG_ARM_SPEAR_CPUFREQ)                += spear-cpufreq.o
>  obj-$(CONFIG_ARM_TEGRA_CPUFREQ)                += tegra-cpufreq.o
> +obj-$(CONFIG_ARM_TEGRA_CPUFREQ)                += tegra124-cpufreq.o

Maybe, you can update the same line if you want.

>  obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
>
>  ##################################################################################
> diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c

> +static struct cpufreq_frequency_table *freq_table;
> +
> +static struct device *cpu_dev;
> +static struct clk *cpu_clk;
> +static struct clk *pllp_clk;
> +static struct clk *pllx_clk;
> +static struct clk *dfll_clk;

The routines in this file are going to be called just once at boot, right?
In that case we are actually wasting some memory by creating globals.
Probably just move all these in a struct and allocate it at runtime.

> +static int tegra124_cpu_switch_to_dfll(void)
> +{
> +       struct clk *original_cpu_clk_parent;
> +       unsigned long rate;
> +       struct dev_pm_opp *opp;
> +       int ret;
> +
> +       rate = clk_get_rate(cpu_clk);
> +       opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
> +       if (IS_ERR(opp))
> +               return PTR_ERR(opp);
> +
> +       ret = clk_set_rate(dfll_clk, rate);
> +       if (ret)
> +               return ret;
> +
> +       original_cpu_clk_parent = clk_get_parent(cpu_clk);
> +       clk_set_parent(cpu_clk, pllp_clk);
> +       if (ret)
> +               return ret;
> +
> +       ret = clk_prepare_enable(dfll_clk);
> +       if (ret)
> +               goto out_switch_to_original_parent;
> +
> +       clk_set_parent(cpu_clk, dfll_clk);
> +
> +       return 0;
> +
> +out_switch_to_original_parent:
> +       clk_set_parent(cpu_clk, original_cpu_clk_parent);
> +
> +       return ret;
> +}
> +
> +static struct platform_device_info cpufreq_cpu0_devinfo = {
> +       .name = "cpufreq-cpu0",
> +};
> +
> +static int tegra124_cpufreq_probe(struct platform_device *pdev)
> +{
> +       int ret;
> +
> +       cpu_dev = get_cpu_device(0);
> +       if (!cpu_dev)
> +               return -ENODEV;
> +

Shouldn't we do a of_node_get() here?

> +       cpu_clk = of_clk_get_by_name(cpu_dev->of_node, "cpu_g");
> +       if (IS_ERR(cpu_clk))
> +               return PTR_ERR(cpu_clk);
> +
> +       dfll_clk = of_clk_get_by_name(cpu_dev->of_node, "dfll");
> +       if (IS_ERR(dfll_clk)) {
> +               ret = PTR_ERR(dfll_clk);
> +               goto out_put_cpu_clk;
> +       }
> +
> +       pllx_clk = of_clk_get_by_name(cpu_dev->of_node, "pll_x");
> +       if (IS_ERR(pllx_clk)) {
> +               ret = PTR_ERR(pllx_clk);
> +               goto out_put_dfll_clk;
> +       }
> +
> +       pllp_clk = of_clk_get_by_name(cpu_dev->of_node, "pll_p");
> +       if (IS_ERR(pllp_clk)) {
> +               ret = PTR_ERR(pllp_clk);
> +               goto out_put_pllx_clk;
> +       }
> +
> +       ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
> +       if (ret)
> +               goto out_put_pllp_clk;

Why do you need this? cpufreq-cpu0 also does it and this freq_table is
just not getting used at all then.

> +
> +       ret = tegra124_cpu_switch_to_dfll();
> +       if (ret)
> +               goto out_free_table;
> +
> +       platform_device_register_full(&cpufreq_cpu0_devinfo);
> +
> +       return 0;
> +
> +out_free_table:
> +       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
> +out_put_pllp_clk:
> +       clk_put(pllp_clk);
> +out_put_pllx_clk:
> +       clk_put(pllx_clk);
> +out_put_dfll_clk:
> +       clk_put(dfll_clk);
> +out_put_cpu_clk:
> +       clk_put(cpu_clk);
> +
> +       return ret;
> +}
> +
> +static struct platform_driver tegra124_cpufreq_platdrv = {
> +       .driver = {
> +               .name   = "cpufreq-tegra124",
> +               .owner  = THIS_MODULE,
> +       },
> +       .probe          = tegra124_cpufreq_probe,
> +};
> +
> +static const struct of_device_id soc_of_matches[] = {
> +       { .compatible = "nvidia,tegra124", },
> +       {}
> +};
> +
> +static int __init tegra_cpufreq_init(void)
> +{
> +       int ret;
> +       struct platform_device *pdev;
> +
> +       if (!of_find_matching_node(NULL, soc_of_matches))
> +               return -ENODEV;
> +
> +       ret = platform_driver_register(&tegra124_cpufreq_platdrv);
> +       if (ret)
> +               return ret;
> +
> +       pdev = platform_device_register_simple("cpufreq-tegra124", -1, NULL, 0);
> +       if (IS_ERR(pdev)) {
> +               platform_driver_unregister(&tegra124_cpufreq_platdrv);
> +               return PTR_ERR(pdev);
> +       }

Why create another unnecessary platform-device/driver here? If
of_find_matching_node() passes and you really need to probe cpufreq-cpu0
here, then just remove the other two calls and move probe's implementation
here only.

> +       return 0;
> +}
> +
> +MODULE_AUTHOR("Tuomas Tynkkynen <ttynkkynen@nvidia.com>");
> +MODULE_DESCRIPTION("cpufreq driver for nVIDIA Tegra124");
> +MODULE_LICENSE("GPLv2");
> +module_init(tegra_cpufreq_init);
> --
> 1.8.1.5
>

^ permalink raw reply

* [GIT PULL] Armada DRM devel updates
From: Dave Airlie @ 2014-07-23  4:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140722085138.GB15250@rmk-PC.arm.linux.org.uk>

On 22 July 2014 18:51, Russell King <rmk@arm.linux.org.uk> wrote:
> On Fri, Jul 11, 2014 at 09:03:44PM +0100, Russell King wrote:
>> David,
>>
>> Please incorporate the latest Armada DRM updates, which can be found at:
>>
>>   git://ftp.arm.linux.org.uk/~rmk/linux-arm.git drm-armada-devel
>
> Ping?
>
sorry I wanted to confirm the sha1 in Greg's tree were the same, did so now.

Dave.

^ permalink raw reply

* [PATCH 0/2] ARM: DRA7: hwmod: Add dra74x and dra72x specific ocp interface lists
From: Lokesh Vutla @ 2014-07-23  4:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <53CE952D.6040705@ti.com>

Hi Nishanth,
On Tuesday 22 July 2014 10:15 PM, Nishanth Menon wrote:
> On 07/16/2014 03:36 AM, Lokesh Vutla wrote:
>> This series add seperate ocp interface lists that are specific to dra74x
>> and dra72x, and moving USB OTG SS4 to dra74x only since its not present
>> in dra72x. Without this USB OTG SS4 hwmod gives an abort on dra72x.
>>
>> Adding support for soc_is_dra74x() and soc_is_dra72x() in order to differentiate
>> between dra74x and dra72x and pass the respective ocp interface lists.
>>
>> Verified on dra74x evm and dra72x evm using 3.16-rc5 based mainline kernel.
>>
>> Before:
>> dra74x : http://paste.ubuntu.com/7802364/ 
>> dra72x : http://paste.ubuntu.com/7802334/ (Kernel panic)
>>
>> After-
>> dra74x : http://paste.ubuntu.com/7802340/
>> dra72x : http://paste.ubuntu.com/7802338/ (booted)
>>
>> Rajendra Nayak (2):
>>   ARM: DRA7: Add support for soc_is_dra74x() and soc_is_dra72x()
>>     varients
>>   ARM: DRA7: hwmod: Add dra74x and dra72x specific ocp interface lists
>>
>>  arch/arm/mach-omap2/omap_hwmod.c          |    3 +++
>>  arch/arm/mach-omap2/omap_hwmod_7xx_data.c |   22 ++++++++++++++++++++--
>>  arch/arm/mach-omap2/soc.h                 |    7 +++++++
>>  3 files changed, 30 insertions(+), 2 deletions(-)
>>
> Tested-by: Nishanth Menon <nm@ti.com>
Thanks..
> 
> BUT, I suggest a follow up series to do exactly the same (moving stuff
> that are not common from dra7.dtsi to dra72x.dtsi and 74x.dtsi) as
> well to ensure that dts indicates exactly the same information (only
> the applicable IPs are present in dts).
The separation of dra72x.dtsi and dra74x.dtsi is already happened and the patch is
already present in mainline[1].
Looks like usb_otg_ss4 is still present in dra7.dtsi, but this should go into dra74x.dtsi.
I ll take it up.

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=38b248db60e32734417534b57f9ab687c445113a

Thanks and regards,
Lokesh

> 

^ permalink raw reply

* [PATCH 2/2] ARM: DRA7: hwmod: Add dra74x and dra72x specific ocp interface lists
From: Lokesh Vutla @ 2014-07-23  3:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <53CE9652.4080304@ti.com>

Hi Nishanth,
On Tuesday 22 July 2014 10:20 PM, Nishanth Menon wrote:
> On 07/16/2014 03:36 AM, Lokesh Vutla wrote:
>> From: Rajendra Nayak <rnayak@ti.com>
>>
>> To deal with IPs which are specific to dra74x and dra72x, maintain seperate
>> ocp interface lists, while keeping the common list for all common IPs.
>>
>> Move USB OTG SS4 to dra74x only list since its unavailable in
>> dra72x and is giving an abort during boot. The dra72x only list
>> is empty for now and a placeholder for future hwmod additions which
>> are specific to dra72x.
>>
>> Fixes: d904b38 ARM: DRA7: hwmod: Add SYSCONFIG for usb_otg_ss
> 
> please use a format as following:
> Fixes: d904b38df0db13 ("ARM: DRA7: hwmod: Add SYSCONFIG for usb_otg_ss")
> 
>> Reported-by: Keerthy <j-keerthy@ti.com>
>> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
>> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
>> ---
>>  arch/arm/mach-omap2/omap_hwmod.c          |    3 +++
>>  arch/arm/mach-omap2/omap_hwmod_7xx_data.c |   22 ++++++++++++++++++++--
>>  2 files changed, 23 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
>> index 6c074f3..14f8370 100644
>> --- a/arch/arm/mach-omap2/omap_hwmod.c
>> +++ b/arch/arm/mach-omap2/omap_hwmod.c
>> @@ -3345,6 +3345,9 @@ int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois)
>>  	if (!ois)
>>  		return 0;
>>  
>> +	if (ois[0] == NULL) /*empty list*/
> /* Empty list */ ?
>> +		return 0;
>> +
> 
> This change looks like a different patch?
Since we are introducing empty lists in this patch, I guess
this can go in the same patch.
> 
>>  	if (!linkspace) {
>>  		if (_alloc_linkspace(ois)) {
>>  			pr_err("omap_hwmod: could not allocate link space\n");
>> diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
>> index 284324f..c95033c 100644
>> --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
>> +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
>> @@ -35,6 +35,7 @@
>>  #include "i2c.h"
>>  #include "mmc.h"
>>  #include "wd_timer.h"
>> +#include "soc.h"
>>  
>>  /* Base offset for all DRA7XX interrupts external to MPUSS */
>>  #define DRA7XX_IRQ_GIC_START	32
>> @@ -2705,7 +2706,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
>>  	&dra7xx_l4_per3__usb_otg_ss1,
>>  	&dra7xx_l4_per3__usb_otg_ss2,
>>  	&dra7xx_l4_per3__usb_otg_ss3,
>> -	&dra7xx_l4_per3__usb_otg_ss4,
>>  	&dra7xx_l3_main_1__vcp1,
>>  	&dra7xx_l4_per2__vcp1,
>>  	&dra7xx_l3_main_1__vcp2,
>> @@ -2714,8 +2714,26 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
>>  	NULL,
>>  };
>>  
>> +static struct omap_hwmod_ocp_if *dra74x_hwmod_ocp_ifs[] __initdata = {
>> +	&dra7xx_l4_per3__usb_otg_ss4,
>> +	NULL,
>> +};
>> +
>> +static struct omap_hwmod_ocp_if *dra72x_hwmod_ocp_ifs[] __initdata = {
>> +	NULL,
>> +};
>> +
>>  int __init dra7xx_hwmod_init(void)
>>  {
>> +	int ret;
>> +
>>  	omap_hwmod_init();
>> -	return omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs);
>> +	ret = omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs);
> if (ret)
> 	goto out;
>> +
>> +	if (!ret && soc_is_dra74x())
> no need of !ret
>> +		return omap_hwmod_register_links(dra74x_hwmod_ocp_ifs);
> ret = omap_hwmod_register_links(dra74x_hwmod_ocp_ifs);
>> +	else if (!ret && soc_is_dra72x())
> no need of else and !ret
>> +		return omap_hwmod_register_links(dra72x_hwmod_ocp_ifs);
> ret = omap_hwmod_register_links(dra72x_hwmod_ocp_ifs);
>> +
> 
> out:
Ok. Will do this and repost.

Thanks and regards,
Lokesh
>> +	return ret;
>>  }
>>
> 
> 

^ permalink raw reply

* [RFC Patch V1 21/30] mm, irqchip: Use cpu_to_mem()/numa_mem_id() to support memoryless node
From: Jiang Liu @ 2014-07-23  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140718124038.GE24496@titan.lakedaemon.net>

Hi Jason,
	Thanks for your review. According to review comments,
we need to rework the patch set in another direction and will
give up this patch.
Regards!
Gerry

On 2014/7/18 20:40, Jason Cooper wrote:
> On Fri, Jul 11, 2014 at 03:37:38PM +0800, Jiang Liu wrote:
>> When CONFIG_HAVE_MEMORYLESS_NODES is enabled, cpu_to_node()/numa_node_id()
>> may return a node without memory, and later cause system failure/panic
>> when calling kmalloc_node() and friends with returned node id.
>> So use cpu_to_mem()/numa_mem_id() instead to get the nearest node with
>> memory for the/current cpu.
>>
>> If CONFIG_HAVE_MEMORYLESS_NODES is disabled, cpu_to_mem()/numa_mem_id()
>> is the same as cpu_to_node()/numa_node_id().
>>
>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>> ---
>>  drivers/irqchip/irq-clps711x.c |    2 +-
>>  drivers/irqchip/irq-gic.c      |    2 +-
>>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> Do you have anything depending on this?  Can apply it to irqchip?  If
> you need to keep it with other changes,
> 
> Acked-by: Jason Cooper <jason@lakedaemon.net>
> 
> But please do let me know if I can take it.
> 
> thx,
> 
> Jason.
> 

^ permalink raw reply

* [PATCH 0/6] net: mvpp2: Assorted fixes
From: David Miller @ 2014-07-23  2:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140722.174153.413669013449137654.davem@davemloft.net>

From: David Miller <davem@davemloft.net>
Date: Tue, 22 Jul 2014 17:41:53 -0700 (PDT)

> From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> Date: Tue, 22 Jul 2014 20:20:04 -0300
> 
>> On 23 Jul 12:29 AM, Thomas Petazzoni wrote:
>>> On Tue, 22 Jul 2014 13:16:39 -0700 (PDT), David Miller wrote:
>>> 
>>> > >> This series does not apply to the 'net' tree at all, please respin
>>> > >> and resubmit.
>>> > > 
>>> > > This series applies on net-next.
>>> > > 
>>> > > Sorry for not mentioning it,
>>> > 
>>> > They are bonafide bug fixes, therefore should be targetted at 'net'.
>>> 
>>> Except that I believe they are fixes for a driver which itself is in
>>> net-next, i.e scheduled for 3.17.
>>> 
>> 
>> That's right. These are fixes for the new mvpp2 driver, which is only
>> in net-next.
> 
> Ok, I queued them back up, thanks for the clarification.

I've applied the 4 driver patches to net-next.  But, since the ARM
device tree file changes did not go into net-next, I can't apply the
last two patches to my tree.  You'll need to sort that out yourself.

It's a bit unfortunate that things are now out of sync like this, but
that's what you asked me to do.

^ permalink raw reply

* Issue found in Armada 370: "No buffer space available" error during continuous ping
From: Maggie Mae Roxas @ 2014-07-23  2:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140721070303.GM21834@1wt.eu>

Hi Willy,
Good day.

> OK so clearly the issue must be found.

Actually we have 2 products using Armada 370.
One has only 1 ethernet port, so it is expected to act as Client only.
The other one has 2 ethernet ports, so it's more router-like.

For the product with one port, we have checked the combination patch
and it seems like Tx IRQ is increasing so it's OK. We checked this via
/proc/interrupts and mvneta's value there changed from 500000+ to
around 900000+ after we perform a 10-iteration iperf to the server.
The throughput is also OK, we're getting around 850Mbits when we use a
1Gbit connection, which is roughly just the same as what we've been
experiencing when we're still using 3.10.x (even 3.2.x).

As for the other product with two ports, we do expect that we might be
encountering the slow performance you mentioned.
But we are not focusing on this project yet so once it's active again,
I'll let you know.

> Just thinking about something, do you have a custom boot loader ?
> It would be possible that in our case, the Tx IRQ works only because some
> obscure or undocumented bits are set by the boot loader and that in your
> case it's not pre-initialized.

We are indeed using a "custom" boot loader.
We are using Marvell u-boot 2014_T1.1 (latest QA release, I think).
We applied some patches to memory (since we have 1Gb DDR), some bits
and pieces for the interfaces we're going to support and not to
support, and of course our own environment variables.
As for the DDR memory/register patches, they came directly from our
Marvell contact.

But with what I mentioned above, I think our Tx interrupt is working...?

BTW, for both products we've designed from Armada 370 RD, we didn't
use a switch. So we removed all switch-related codes in the boot
loader.
I'm not sure if not having switch affects the behavior?

How about you? May I know what boot loader you are using?

> LTS would probably even interest your customer as it's an LTS version.
> In this case, always pick the most recent one (3.14.12 today). You may
> even be interested in 3.15.6 which contains another phy fix supposed to
> fix cd71e2, but if you're saying that it doesn't change anything for you
> I guess it will have no effet (might be worth testing for the purpose of
> helping troubleshooting though).

Thank you for this advise, we'll take note of this.
We plan to stick on using LTS from now on, as much as possible.

> OK. I still have a hard time imagining how hardware itself could prevent
> an IRQ from being delivered from a NIC which is located inside the SoC,
> but there must be an explanation somewhere :-/
I also would like to know how. :-/
But maybe it's our difference in boot loader as you speculated.

In any case, thanks a lot again for your assistance!

Regards,
Maggie Roxas

On Mon, Jul 21, 2014 at 12:03 AM, Willy Tarreau <w@1wt.eu> wrote:
> Hi Maggie,
>
> On Sun, Jul 20, 2014 at 11:33:22PM -0700, Maggie Mae Roxas wrote:
>> > As you said that you both applied cd71e2 and reverted 4f3a4f, could you
>> please confirm that with cd71 applied only it was not enough?
>> Yes.
>> If mvneta.c used is the v3.13.9 + cd71e2, issue still occurs.
>> If mvneta.c used is the v3.13.9 + cd71e2 - 4f3a4f, issue does not occur anymore.
>
> Rather strange then.
>
>> Okay. First, I'll check if the interrupts are working by checking
>> this, as you suggested:
>> <snip>
>> Checking /proc/interrupts when you're sending some traffic should show
>> that the IRQ is increasing from time to time.
>> <snip>
>> I'll inform you the results within the next 2-3 days.
>
> OK.
>
>> We'll be using it as a router, thus, it would really be a problem for us.
>
> OK so clearly the issue must be found.
> Just thinking about something, do you have a custom boot loader ? It
> would be possible that in our case, the Tx IRQ works only because some
> obscure or undocumented bits are set by the boot loader and that in your
> case it's not pre-initialized.
>
>> Will check possibilities of shifting to v3.14+ with our customer -
>> especially if we found problems in ethernet performance as you
>> mentioned.
>> Any recommendations on which version to use, specifically?
>
> LTS would probably even interest your customer as it's an LTS version.
> In this case, always pick the most recent one (3.14.12 today). You may
> even be interested in 3.15.6 which contains another phy fix supposed to
> fix cd71e2, but if you're saying that it doesn't change anything for you
> I guess it will have no effet (might be worth testing for the purpose of
> helping troubleshooting though).
>
>> > Third, considering that other boards work without applying these changes, it might be possible that there's an issue on your board, and maybe detecting it early would allow you to fix it for all future batches, and maybe only apply these patches for the few very first ones.
>> Acknowledged.
>> Once we verified that indeed, the performance was slower (or
>> interrupts were not increasing) - we will inform our hardware team and
>> have them investigate this issue further for possible hardware bugs.
>
> OK. I still have a hard time imagining how hardware itself could prevent
> an IRQ from being delivered from a NIC which is located inside the SoC,
> but there must be an explanation somewhere :-/
>
>> Thanks a lot for the help again, I'll let you know as soon as I have more info.
>
> Thanks,
> Willy
>

^ permalink raw reply

* [PATCH] ARM: tegra: apalis t30: fix device tree compatible node
From: Marcel Ziswiler @ 2014-07-23  2:23 UTC (permalink / raw)
  To: linux-arm-kernel

Working on sound support I noticed the Apalis T30 Evaluation board
device tree missing the more generic Apalis T30 compatible string.

Signed-off-by: Marcel Ziswiler <marcel@ziswiler.com>
---
 arch/arm/boot/dts/tegra30-apalis-eval.dts |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/tegra30-apalis-eval.dts
index 9921433..45d40f0 100644
--- a/arch/arm/boot/dts/tegra30-apalis-eval.dts
+++ b/arch/arm/boot/dts/tegra30-apalis-eval.dts
@@ -5,7 +5,7 @@
 
 / {
 	model = "Toradex Apalis T30 on Apalis Evaluation Board";
-	compatible = "toradex,apalis_t30-eval", "nvidia,tegra30";
+	compatible = "toradex,apalis_t30-eval", "toradex,apalis_t30", "nvidia,tegra30";
 
 	aliases {
 		rtc0 = "/i2c at 7000c000/rtc at 68";
-- 
1.7.9.5

^ permalink raw reply related

* [PATCHv8 0/4] iio: adc: exynos_adc: Support Exynos3250 ADC and code clean
From: Chanwoo Choi @ 2014-07-23  1:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405994696-3117-1-git-send-email-cw00.choi@samsung.com>

Dear Jonathan,

Could you please pick this patchset for 3.17?

Best Regards,
Chanwoo Choi

On 07/22/2014 11:04 AM, Chanwoo Choi wrote:
> This patchset support Exynos3250 ADC (Analog Digital Converter) because
> Exynos3250 has additional special clock for ADC IP.
> 
> Changes from v7:
> - Add acked message by Arnd Bergmann
> - Use two compatible string for Exynos3250 ADC as following:
>   : compatible = "samsung,exynos3250-adc", "samsung,exynos-adc-v2;
> 
> Changes from v6:
> - Use "exynos3250-adc" compatible string instead of "exynos3250-adc-v2"
> - Use "sclk" clock name instead of "sclk_adc"
> - Remove un-necessary macro for exyno-adc-data-v2 structure.
> - Remove '(void *)' cast and mark the exynos-adc-data structure as 'const'
> - Change the number of ADC channels (Exynos3250 has only two channels for ADC)
> 
> Changes from v5:
> - Add acked message by Kukjin Kim
> - Add reviewed messgae by Tomasz Figa
> - Fix typo (for for -> for)
> 
> Changes from v4:
> - Use 'exynos_adc_data' structure instead of 'exynos_adc_ops' structure
>   and remove enum variable of ADC version
> - Fix wrong name of special clock (sclk_tsadc -> sclk_adc)
> - Add reviewed message by Naveen Krishna Chatradhi
> - Add functions for ADC clock control
> 
> Changes from v3:
> - Add new 'exynos_adc_ops' structure to improve readability according to
>  Tomasz Figa comment[1]
>  [1] https://lkml.org/lkml/2014/4/16/238
> - Add new 'exynos3250-adc-v2' compatible string to support Exynos3250 ADC
> - Fix wrong compaitlbe string of ADC in Exynos3250 dtsi file
> 
> Changes from v2:
> - Check return value of clock function to deal with error exception
> - Fix minor coding style to improve readability
> 
> Changes from v1:
> - Add new "samsung,exynos-adc-v3" compatible to support Exynos3250 ADC
> - Add a patch about DT binding documentation
> 
> Chanwoo Choi (4):
>   iio: adc: exynos_adc: Add exynos_adc_data structure to improve
>     readability
>   iio: adc: exynos_adc: Control special clock of ADC to support
>     Exynos3250 ADC
>   iio: devicetree: Add DT binding documentation for Exynos3250 ADC
>   ARM: dts: Fix wrong compatible string for Exynos3250 ADC
> 
>  .../devicetree/bindings/arm/samsung/exynos-adc.txt |  25 +-
>  arch/arm/boot/dts/exynos3250.dtsi                  |   5 +-
>  drivers/iio/adc/exynos_adc.c                       | 335 +++++++++++++++------
>  3 files changed, 275 insertions(+), 90 deletions(-)
> 

^ permalink raw reply

* [PATCHv4 5/5] arm64: Add atomic pool for non-coherent and CMA allocations.
From: Laura Abbott @ 2014-07-23  1:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406079308-5232-1-git-send-email-lauraa@codeaurora.org>

Neither CMA nor noncoherent allocations support atomic allocations.
Add a dedicated atomic pool to support this.

Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
---
 arch/arm64/Kconfig          |   1 +
 arch/arm64/mm/dma-mapping.c | 164 +++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 146 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 44deb53..d6c8603 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -18,6 +18,7 @@ config ARM64
 	select COMMON_CLK
 	select CPU_PM if (SUSPEND || CPU_IDLE)
 	select DCACHE_WORD_ACCESS
+	select GENERIC_ALLOCATOR
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
 	select GENERIC_CPU_AUTOPROBE
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 4164c5a..90bb7b3 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -27,6 +27,7 @@
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
 #include <linux/amba/bus.h>
+#include <linux/genalloc.h>
 
 #include <asm/cacheflush.h>
 
@@ -41,6 +42,54 @@ static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
 	return prot;
 }
 
+static struct gen_pool *atomic_pool;
+
+#define DEFAULT_DMA_COHERENT_POOL_SIZE  SZ_256K
+static size_t atomic_pool_size = DEFAULT_DMA_COHERENT_POOL_SIZE;
+
+static int __init early_coherent_pool(char *p)
+{
+	atomic_pool_size = memparse(p, &p);
+	return 0;
+}
+early_param("coherent_pool", early_coherent_pool);
+
+static void *__alloc_from_pool(size_t size, struct page **ret_page)
+{
+	unsigned long val;
+	void *ptr = NULL;
+
+	if (!atomic_pool) {
+		WARN(1, "coherent pool not initialised!\n");
+		return NULL;
+	}
+
+	val = gen_pool_alloc(atomic_pool, size);
+	if (val) {
+		phys_addr_t phys = gen_pool_virt_to_phys(atomic_pool, val);
+
+		*ret_page = phys_to_page(phys);
+		ptr = (void *)val;
+	}
+
+	return ptr;
+}
+
+static bool __in_atomic_pool(void *start, size_t size)
+{
+	return addr_in_gen_pool(atomic_pool, (unsigned long)start, size);
+}
+
+static int __free_from_pool(void *start, size_t size)
+{
+	if (!__in_atomic_pool(start, size))
+		return 0;
+
+	gen_pool_free(atomic_pool, (unsigned long)start, size);
+
+	return 1;
+}
+
 static void *__dma_alloc_coherent(struct device *dev, size_t size,
 				  dma_addr_t *dma_handle, gfp_t flags,
 				  struct dma_attrs *attrs)
@@ -53,7 +102,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
 	if (IS_ENABLED(CONFIG_ZONE_DMA) &&
 	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
 		flags |= GFP_DMA;
-	if (IS_ENABLED(CONFIG_DMA_CMA)) {
+	if (IS_ENABLED(CONFIG_DMA_CMA) && (flags & __GFP_WAIT)) {
 		struct page *page;
 
 		size = PAGE_ALIGN(size);
@@ -73,50 +122,54 @@ static void __dma_free_coherent(struct device *dev, size_t size,
 				void *vaddr, dma_addr_t dma_handle,
 				struct dma_attrs *attrs)
 {
+	bool freed;
+	phys_addr_t paddr = dma_to_phys(dev, dma_handle);
+
 	if (dev == NULL) {
 		WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
 		return;
 	}
 
-	if (IS_ENABLED(CONFIG_DMA_CMA)) {
-		phys_addr_t paddr = dma_to_phys(dev, dma_handle);
-
-		dma_release_from_contiguous(dev,
+	freed = dma_release_from_contiguous(dev,
 					phys_to_page(paddr),
 					size >> PAGE_SHIFT);
-	} else {
+	if (!freed)
 		swiotlb_free_coherent(dev, size, vaddr, dma_handle);
-	}
 }
 
 static void *__dma_alloc_noncoherent(struct device *dev, size_t size,
 				     dma_addr_t *dma_handle, gfp_t flags,
 				     struct dma_attrs *attrs)
 {
-	struct page *page, **map;
+	struct page *page;
 	void *ptr, *coherent_ptr;
-	int order, i;
 
 	size = PAGE_ALIGN(size);
-	order = get_order(size);
+
+	if (!(flags & __GFP_WAIT)) {
+		struct page *page = NULL;
+		void *addr = __alloc_from_pool(size, &page);
+
+		if (addr)
+			*dma_handle = phys_to_dma(dev, page_to_phys(page));
+
+		return addr;
+
+	}
 
 	ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs);
 	if (!ptr)
 		goto no_mem;
-	map = kmalloc(sizeof(struct page *) << order, flags & ~GFP_DMA);
-	if (!map)
-		goto no_map;
 
 	/* remove any dirty cache lines on the kernel alias */
 	__dma_flush_range(ptr, ptr + size);
 
 	/* create a coherent mapping */
 	page = virt_to_page(ptr);
-	for (i = 0; i < (size >> PAGE_SHIFT); i++)
-		map[i] = page + i;
-	coherent_ptr = vmap(map, size >> PAGE_SHIFT, VM_MAP,
-			    __get_dma_pgprot(attrs, __pgprot(PROT_NORMAL_NC), false));
-	kfree(map);
+	coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP,
+				__get_dma_pgprot(attrs,
+					__pgprot(PROT_NORMAL_NC), false),
+					NULL);
 	if (!coherent_ptr)
 		goto no_map;
 
@@ -135,6 +188,8 @@ static void __dma_free_noncoherent(struct device *dev, size_t size,
 {
 	void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
 
+	if (__free_from_pool(vaddr, size))
+		return;
 	vunmap(vaddr);
 	__dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs);
 }
@@ -332,6 +387,67 @@ static struct notifier_block amba_bus_nb = {
 
 extern int swiotlb_late_init_with_default_size(size_t default_size);
 
+static int __init atomic_pool_init(void)
+{
+	pgprot_t prot = __pgprot(PROT_NORMAL_NC);
+	unsigned long nr_pages = atomic_pool_size >> PAGE_SHIFT;
+	struct page *page;
+	void *addr;
+	unsigned int pool_size_order = get_order(atomic_pool_size);
+
+	if (dev_get_cma_area(NULL))
+		page = dma_alloc_from_contiguous(NULL, nr_pages,
+							pool_size_order);
+	else
+		page = alloc_pages(GFP_DMA, pool_size_order);
+
+	if (page) {
+		int ret;
+		void *page_addr = page_address(page);
+
+		memset(page_addr, 0, atomic_pool_size);
+		__dma_flush_range(page_addr, page_addr + atomic_pool_size);
+
+		atomic_pool = gen_pool_create(PAGE_SHIFT, -1);
+		if (!atomic_pool)
+			goto free_page;
+
+		addr = dma_common_contiguous_remap(page, atomic_pool_size,
+					VM_USERMAP, prot, atomic_pool_init);
+
+		if (!addr)
+			goto destroy_genpool;
+
+		ret = gen_pool_add_virt(atomic_pool, (unsigned long)addr,
+					page_to_phys(page),
+					atomic_pool_size, -1);
+		if (ret)
+			goto remove_mapping;
+
+		gen_pool_set_algo(atomic_pool,
+				  gen_pool_first_fit_order_align,
+				  (void *)PAGE_SHIFT);
+
+		pr_info("DMA: preallocated %zu KiB pool for atomic allocations\n",
+			atomic_pool_size / 1024);
+		return 0;
+	}
+	goto out;
+
+remove_mapping:
+	dma_common_free_remap(addr, atomic_pool_size, VM_USERMAP);
+destroy_genpool:
+	gen_pool_destroy(atomic_pool);
+	atomic_pool = NULL;
+free_page:
+	if (!dma_release_from_contiguous(NULL, page, nr_pages))
+		__free_pages(page, pool_size_order);
+out:
+	pr_err("DMA: failed to allocate %zu KiB pool for atomic coherent allocation\n",
+		atomic_pool_size / 1024);
+	return -ENOMEM;
+}
+
 static int __init swiotlb_late_init(void)
 {
 	size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT);
@@ -346,7 +462,17 @@ static int __init swiotlb_late_init(void)
 
 	return swiotlb_late_init_with_default_size(swiotlb_size);
 }
-arch_initcall(swiotlb_late_init);
+
+static int __init arm64_dma_init(void)
+{
+	int ret = 0;
+
+	ret |= swiotlb_late_init();
+	ret |= atomic_pool_init();
+
+	return ret;
+}
+arch_initcall(arm64_dma_init);
 
 #define PREALLOC_DMA_DEBUG_ENTRIES	4096
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related

* [PATCHv4 4/5] arm: use genalloc for the atomic pool
From: Laura Abbott @ 2014-07-23  1:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406079308-5232-1-git-send-email-lauraa@codeaurora.org>

ARM currently uses a bitmap for tracking atomic allocations.
genalloc already handles this type of memory pool allocation
so switch to using that instead.

Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
---
 arch/arm/Kconfig          |   1 +
 arch/arm/mm/dma-mapping.c | 153 +++++++++++++++-------------------------------
 2 files changed, 50 insertions(+), 104 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index eed8334..b686e0e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -13,6 +13,7 @@ config ARM
 	select CLONE_BACKWARDS
 	select CPU_PM if (SUSPEND || CPU_IDLE)
 	select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select GENERIC_ALLOCATOR
 	select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI)
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
 	select GENERIC_IDLE_POLL_SETUP
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 8c4c755..ad6ac3a 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -12,6 +12,7 @@
 #include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/genalloc.h>
 #include <linux/gfp.h>
 #include <linux/errno.h>
 #include <linux/list.h>
@@ -314,23 +315,13 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
 }
 
 #define DEFAULT_DMA_COHERENT_POOL_SIZE	SZ_256K
+static struct gen_pool *atomic_pool;
 
-struct dma_pool {
-	size_t size;
-	spinlock_t lock;
-	unsigned long *bitmap;
-	unsigned long nr_pages;
-	void *vaddr;
-	struct page **pages;
-};
-
-static struct dma_pool atomic_pool = {
-	.size = DEFAULT_DMA_COHERENT_POOL_SIZE,
-};
+static size_t atomic_pool_size = DEFAULT_DMA_COHERENT_POOL_SIZE;
 
 static int __init early_coherent_pool(char *p)
 {
-	atomic_pool.size = memparse(p, &p);
+	atomic_pool_size = memparse(p, &p);
 	return 0;
 }
 early_param("coherent_pool", early_coherent_pool);
@@ -340,14 +331,14 @@ void __init init_dma_coherent_pool_size(unsigned long size)
 	/*
 	 * Catch any attempt to set the pool size too late.
 	 */
-	BUG_ON(atomic_pool.vaddr);
+	BUG_ON(atomic_pool);
 
 	/*
 	 * Set architecture specific coherent pool size only if
 	 * it has not been changed by kernel command line parameter.
 	 */
-	if (atomic_pool.size == DEFAULT_DMA_COHERENT_POOL_SIZE)
-		atomic_pool.size = size;
+	if (atomic_pool_size == DEFAULT_DMA_COHERENT_POOL_SIZE)
+		atomic_pool_size = size;
 }
 
 /*
@@ -355,52 +346,44 @@ void __init init_dma_coherent_pool_size(unsigned long size)
  */
 static int __init atomic_pool_init(void)
 {
-	struct dma_pool *pool = &atomic_pool;
 	pgprot_t prot = pgprot_dmacoherent(PAGE_KERNEL);
 	gfp_t gfp = GFP_KERNEL | GFP_DMA;
-	unsigned long nr_pages = pool->size >> PAGE_SHIFT;
-	unsigned long *bitmap;
 	struct page *page;
-	struct page **pages;
 	void *ptr;
-	int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
-
-	bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!bitmap)
-		goto no_bitmap;
 
-	pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
-	if (!pages)
-		goto no_pages;
+	atomic_pool = gen_pool_create(PAGE_SHIFT, -1);
+	if (!atomic_pool)
+		goto out;
 
 	if (dev_get_cma_area(NULL))
-		ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
-					      atomic_pool_init);
+		ptr = __alloc_from_contiguous(NULL, atomic_pool_size, prot,
+					      &page, atomic_pool_init);
 	else
-		ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
-					   atomic_pool_init);
+		ptr = __alloc_remap_buffer(NULL, atomic_pool_size, gfp, prot,
+					   &page, atomic_pool_init);
 	if (ptr) {
-		int i;
-
-		for (i = 0; i < nr_pages; i++)
-			pages[i] = page + i;
-
-		spin_lock_init(&pool->lock);
-		pool->vaddr = ptr;
-		pool->pages = pages;
-		pool->bitmap = bitmap;
-		pool->nr_pages = nr_pages;
-		pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n",
-		       (unsigned)pool->size / 1024);
+		int ret;
+
+		ret = gen_pool_add_virt(atomic_pool, (unsigned long)ptr,
+					page_to_phys(page),
+					atomic_pool_size, -1);
+		if (ret)
+			goto destroy_genpool;
+
+		gen_pool_set_algo(atomic_pool,
+				gen_pool_first_fit_order_align,
+				(void *)PAGE_SHIFT);
+		pr_info("DMA: preallocated %zd KiB pool for atomic coherent allocations\n",
+		       atomic_pool_size / 1024);
 		return 0;
 	}
 
-	kfree(pages);
-no_pages:
-	kfree(bitmap);
-no_bitmap:
-	pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
-	       (unsigned)pool->size / 1024);
+destroy_genpool:
+	gen_pool_destroy(atomic_pool);
+	atomic_pool = NULL;
+out:
+	pr_err("DMA: failed to allocate %zx KiB pool for atomic coherent allocation\n",
+	       atomic_pool_size / 1024);
 	return -ENOMEM;
 }
 /*
@@ -495,76 +478,36 @@ static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
 
 static void *__alloc_from_pool(size_t size, struct page **ret_page)
 {
-	struct dma_pool *pool = &atomic_pool;
-	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-	unsigned int pageno;
-	unsigned long flags;
+	unsigned long val;
 	void *ptr = NULL;
-	unsigned long align_mask;
 
-	if (!pool->vaddr) {
+	if (!atomic_pool) {
 		WARN(1, "coherent pool not initialised!\n");
 		return NULL;
 	}
 
-	/*
-	 * Align the region allocation - allocations from pool are rather
-	 * small, so align them to their order in pages, minimum is a page
-	 * size. This helps reduce fragmentation of the DMA space.
-	 */
-	align_mask = (1 << get_order(size)) - 1;
-
-	spin_lock_irqsave(&pool->lock, flags);
-	pageno = bitmap_find_next_zero_area(pool->bitmap, pool->nr_pages,
-					    0, count, align_mask);
-	if (pageno < pool->nr_pages) {
-		bitmap_set(pool->bitmap, pageno, count);
-		ptr = pool->vaddr + PAGE_SIZE * pageno;
-		*ret_page = pool->pages[pageno];
-	} else {
-		pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n"
-			    "Please increase it with coherent_pool= kernel parameter!\n",
-			    (unsigned)pool->size / 1024);
+	val = gen_pool_alloc(atomic_pool, size);
+	if (val) {
+		phys_addr_t phys = gen_pool_virt_to_phys(atomic_pool, val);
+
+		*ret_page = phys_to_page(phys);
+		ptr = (void *)val;
 	}
-	spin_unlock_irqrestore(&pool->lock, flags);
 
 	return ptr;
 }
 
 static bool __in_atomic_pool(void *start, size_t size)
 {
-	struct dma_pool *pool = &atomic_pool;
-	void *end = start + size;
-	void *pool_start = pool->vaddr;
-	void *pool_end = pool->vaddr + pool->size;
-
-	if (start < pool_start || start >= pool_end)
-		return false;
-
-	if (end <= pool_end)
-		return true;
-
-	WARN(1, "Wrong coherent size(%p-%p) from atomic pool(%p-%p)\n",
-	     start, end - 1, pool_start, pool_end - 1);
-
-	return false;
+	return addr_in_gen_pool(atomic_pool, (unsigned long)start, size);
 }
 
 static int __free_from_pool(void *start, size_t size)
 {
-	struct dma_pool *pool = &atomic_pool;
-	unsigned long pageno, count;
-	unsigned long flags;
-
 	if (!__in_atomic_pool(start, size))
 		return 0;
 
-	pageno = (start - pool->vaddr) >> PAGE_SHIFT;
-	count = size >> PAGE_SHIFT;
-
-	spin_lock_irqsave(&pool->lock, flags);
-	bitmap_clear(pool->bitmap, pageno, count);
-	spin_unlock_irqrestore(&pool->lock, flags);
+	gen_pool_free(atomic_pool, (unsigned long)start, size);
 
 	return 1;
 }
@@ -1307,11 +1250,13 @@ static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t si
 
 static struct page **__atomic_get_pages(void *addr)
 {
-	struct dma_pool *pool = &atomic_pool;
-	struct page **pages = pool->pages;
-	int offs = (addr - pool->vaddr) >> PAGE_SHIFT;
+	struct page *page;
+	phys_addr_t phys;
+
+	phys = gen_pool_virt_to_phys(atomic_pool, (unsigned long)addr);
+	page = phys_to_page(phys);
 
-	return pages + offs;
+	return (struct page **)page;
 }
 
 static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related

* [PATCHv4 3/5] common: dma-mapping: Introduce common remapping functions
From: Laura Abbott @ 2014-07-23  1:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406079308-5232-1-git-send-email-lauraa@codeaurora.org>

For architectures without coherent DMA, memory for DMA may
need to be remapped with coherent attributes. Factor out
the the remapping code from arm and put it in a
common location to reduced code duplication.

Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
---
 arch/arm/mm/dma-mapping.c                | 57 +++++----------------------
 drivers/base/dma-mapping.c               | 67 ++++++++++++++++++++++++++++++++
 include/asm-generic/dma-mapping-common.h |  9 +++++
 3 files changed, 85 insertions(+), 48 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 3116880..8c4c755 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -298,37 +298,19 @@ static void *
 __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
 	const void *caller)
 {
-	struct vm_struct *area;
-	unsigned long addr;
-
 	/*
 	 * DMA allocation can be mapped to user space, so lets
 	 * set VM_USERMAP flags too.
 	 */
-	area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
-				  caller);
-	if (!area)
-		return NULL;
-	addr = (unsigned long)area->addr;
-	area->phys_addr = __pfn_to_phys(page_to_pfn(page));
-
-	if (ioremap_page_range(addr, addr + size, area->phys_addr, prot)) {
-		vunmap((void *)addr);
-		return NULL;
-	}
-	return (void *)addr;
+	return dma_common_contiguous_remap(page, size,
+			VM_ARM_DMA_CONSISTENT | VM_USERMAP,
+			prot, caller);
 }
 
 static void __dma_free_remap(void *cpu_addr, size_t size)
 {
-	unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP;
-	struct vm_struct *area = find_vm_area(cpu_addr);
-	if (!area || (area->flags & flags) != flags) {
-		WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
-		return;
-	}
-	unmap_kernel_range((unsigned long)cpu_addr, size);
-	vunmap(cpu_addr);
+	dma_common_free_remap(cpu_addr, size,
+			VM_ARM_DMA_CONSISTENT | VM_USERMAP);
 }
 
 #define DEFAULT_DMA_COHERENT_POOL_SIZE	SZ_256K
@@ -1262,29 +1244,8 @@ static void *
 __iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot,
 		    const void *caller)
 {
-	unsigned int i, nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
-	struct vm_struct *area;
-	unsigned long p;
-
-	area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
-				  caller);
-	if (!area)
-		return NULL;
-
-	area->pages = pages;
-	area->nr_pages = nr_pages;
-	p = (unsigned long)area->addr;
-
-	for (i = 0; i < nr_pages; i++) {
-		phys_addr_t phys = __pfn_to_phys(page_to_pfn(pages[i]));
-		if (ioremap_page_range(p, p + PAGE_SIZE, phys, prot))
-			goto err;
-		p += PAGE_SIZE;
-	}
-	return area->addr;
-err:
-	unmap_kernel_range((unsigned long)area->addr, size);
-	vunmap(area->addr);
+	return dma_common_pages_remap(pages, size,
+			VM_ARM_DMA_CONSISTENT | VM_USERMAP, prot, caller);
 	return NULL;
 }
 
@@ -1492,8 +1453,8 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 	}
 
 	if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) {
-		unmap_kernel_range((unsigned long)cpu_addr, size);
-		vunmap(cpu_addr);
+		dma_common_free_remap(cpu_addr, size,
+			VM_ARM_DMA_CONSISTENT | VM_USERMAP);
 	}
 
 	__iommu_remove_mapping(dev, handle, size);
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 6cd08e1..ddaad8d 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -10,6 +10,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/export.h>
 #include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <asm-generic/dma-coherent.h>
 
 /*
@@ -267,3 +269,68 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
 	return ret;
 }
 EXPORT_SYMBOL(dma_common_mmap);
+
+/*
+ * remaps an allocated contiguous region into another vm_area.
+ * Cannot be used in non-sleeping contexts
+ */
+
+void *dma_common_contiguous_remap(struct page *page, size_t size,
+			unsigned long vm_flags,
+			pgprot_t prot, const void *caller)
+{
+	int i;
+	struct page **pages;
+	void *ptr;
+
+	pages = kmalloc(sizeof(struct page *) << get_order(size), GFP_KERNEL);
+	if (!pages)
+		return NULL;
+
+	for (i = 0; i < (size >> PAGE_SHIFT); i++)
+		pages[i] = page + i;
+
+	ptr = dma_common_pages_remap(pages, size, vm_flags, prot, caller);
+
+	kfree(pages);
+
+	return ptr;
+}
+
+/*
+ * remaps an array of PAGE_SIZE pages into another vm_area
+ * Cannot be used in non-sleeping contexts
+ */
+void *dma_common_pages_remap(struct page **pages, size_t size,
+			unsigned long vm_flags, pgprot_t prot,
+			const void *caller)
+{
+	struct vm_struct *area;
+
+	area = get_vm_area_caller(size, vm_flags, caller);
+	if (!area)
+		return NULL;
+
+	if (map_vm_area(area, prot, pages)) {
+		vunmap(area->addr);
+		return NULL;
+	}
+
+	return area->addr;
+}
+
+/*
+ * unmaps a range previously mapped by dma_common_*_remap
+ */
+void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags)
+{
+	struct vm_struct *area = find_vm_area(cpu_addr);
+
+	if (!area || (area->flags & vm_flags) != vm_flags) {
+		WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
+		return;
+	}
+
+	unmap_kernel_range((unsigned long)cpu_addr, size);
+	vunmap(cpu_addr);
+}
diff --git a/include/asm-generic/dma-mapping-common.h b/include/asm-generic/dma-mapping-common.h
index de8bf89..a9fd248 100644
--- a/include/asm-generic/dma-mapping-common.h
+++ b/include/asm-generic/dma-mapping-common.h
@@ -179,6 +179,15 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
 			   void *cpu_addr, dma_addr_t dma_addr, size_t size);
 
+void *dma_common_contiguous_remap(struct page *page, size_t size,
+			unsigned long vm_flags,
+			pgprot_t prot, const void *caller);
+
+void *dma_common_pages_remap(struct page **pages, size_t size,
+			unsigned long vm_flags, pgprot_t prot,
+			const void *caller);
+void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags);
+
 /**
  * dma_mmap_attrs - map a coherent DMA allocation into user space
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related

* [PATCHv4 2/5] lib/genalloc.c: Add genpool range check function
From: Laura Abbott @ 2014-07-23  1:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406079308-5232-1-git-send-email-lauraa@codeaurora.org>

After allocating an address from a particular genpool,
there is no good way to verify if that address actually
belongs to a genpool. Introduce addr_in_gen_pool which
will return if an address plus size falls completely
within the genpool range.

Acked-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
---
 include/linux/genalloc.h |  3 +++
 lib/genalloc.c           | 29 +++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
index 3cd0934..1ccaab4 100644
--- a/include/linux/genalloc.h
+++ b/include/linux/genalloc.h
@@ -121,6 +121,9 @@ extern struct gen_pool *devm_gen_pool_create(struct device *dev,
 		int min_alloc_order, int nid);
 extern struct gen_pool *dev_get_gen_pool(struct device *dev);
 
+bool addr_in_gen_pool(struct gen_pool *pool, unsigned long start,
+			size_t size);
+
 #ifdef CONFIG_OF
 extern struct gen_pool *of_get_named_gen_pool(struct device_node *np,
 	const char *propname, int index);
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 9758529..66edf93 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -403,6 +403,35 @@ void gen_pool_for_each_chunk(struct gen_pool *pool,
 EXPORT_SYMBOL(gen_pool_for_each_chunk);
 
 /**
+ * addr_in_gen_pool - checks if an address falls within the range of a pool
+ * @pool:	the generic memory pool
+ * @start:	start address
+ * @size:	size of the region
+ *
+ * Check if the range of addresses falls within the specified pool. Takes
+ * the rcu_read_lock for the duration of the check.
+ */
+bool addr_in_gen_pool(struct gen_pool *pool, unsigned long start,
+			size_t size)
+{
+	bool found = false;
+	unsigned long end = start + size;
+	struct gen_pool_chunk *chunk;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(chunk, &(pool)->chunks, next_chunk) {
+		if (start >= chunk->start_addr && start <= chunk->end_addr) {
+			if (end <= chunk->end_addr) {
+				found = true;
+				break;
+			}
+		}
+	}
+	rcu_read_unlock();
+	return found;
+}
+
+/**
  * gen_pool_avail - get available free space of the pool
  * @pool: pool to get available free space
  *
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related

* [PATCHv4 1/5] lib/genalloc.c: Add power aligned algorithm
From: Laura Abbott @ 2014-07-23  1:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406079308-5232-1-git-send-email-lauraa@codeaurora.org>

One of the more common algorithms used for allocation
is to align the start address of the allocation to
the order of size requested. Add this as an algorithm
option for genalloc.

Acked-by: Will Deacon <will.deacon@arm.com>
Acked-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
---
 include/linux/genalloc.h |  4 ++++
 lib/genalloc.c           | 21 +++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
index 1c2fdaa..3cd0934 100644
--- a/include/linux/genalloc.h
+++ b/include/linux/genalloc.h
@@ -110,6 +110,10 @@ extern void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo,
 extern unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size,
 		unsigned long start, unsigned int nr, void *data);
 
+extern unsigned long gen_pool_first_fit_order_align(unsigned long *map,
+		unsigned long size, unsigned long start, unsigned int nr,
+		void *data);
+
 extern unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size,
 		unsigned long start, unsigned int nr, void *data);
 
diff --git a/lib/genalloc.c b/lib/genalloc.c
index bdb9a45..9758529 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -481,6 +481,27 @@ unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size,
 EXPORT_SYMBOL(gen_pool_first_fit);
 
 /**
+ * gen_pool_first_fit_order_align - find the first available region
+ * of memory matching the size requirement. The region will be aligned
+ * to the order of the size specified.
+ * @map: The address to base the search on
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ * @nr: The number of zeroed bits we're looking for
+ * @data: additional data - unused
+ */
+unsigned long gen_pool_first_fit_order_align(unsigned long *map,
+		unsigned long size, unsigned long start,
+		unsigned int nr, void *data)
+{
+	unsigned long order = (unsigned long) data;
+	unsigned long align_mask = (1 << get_order(nr << order)) - 1;
+
+	return bitmap_find_next_zero_area(map, size, start, nr, align_mask);
+}
+EXPORT_SYMBOL(gen_pool_first_fit_order_align);
+
+/**
  * gen_pool_best_fit - find the best fitting region of memory
  * macthing the size requirement (no alignment constraint)
  * @map: The address to base the search on
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related

* [PATCHv4 0/5] Atomic pool for arm64
From: Laura Abbott @ 2014-07-23  1:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This is another revision of the series to properly add atomic allocations
for arm64. This version mostly addressed review comments. As always,
reviews and testing welcome

Thanks,
Laura

v4: Addressed comments from Thierry and Catalin. Updated map_vm_area call in
dma_common_pages_remap since the API changed.

v3: Now a patch series due to refactoring of arm code. arm and arm64 now both
use genalloc for atomic pool management. genalloc extensions added.
DMA remapping code factored out as well.

v2: Various bug fixes pointed out by David and Ritesh (CMA dependency, swapping
coherent, noncoherent). I'm still not sure how to address the devicetree
suggestion by Will [1][2]. I added the devicetree mailing list this time around
to get more input on this.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2014-April/249180.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2014-April/249528.html

Laura Abbott (5):
  lib/genalloc.c: Add power aligned algorithm
  lib/genalloc.c: Add genpool range check function
  common: dma-mapping: Introduce common remapping functions
  arm: use genalloc for the atomic pool
  arm64: Add atomic pool for non-coherent and CMA allocations.

 arch/arm/Kconfig                         |   1 +
 arch/arm/mm/dma-mapping.c                | 210 +++++++++----------------------
 arch/arm64/Kconfig                       |   1 +
 arch/arm64/mm/dma-mapping.c              | 164 +++++++++++++++++++++---
 drivers/base/dma-mapping.c               |  67 ++++++++++
 include/asm-generic/dma-mapping-common.h |   9 ++
 include/linux/genalloc.h                 |   7 ++
 lib/genalloc.c                           |  50 ++++++++
 8 files changed, 338 insertions(+), 171 deletions(-)

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

^ permalink raw reply

* [PATCH v7 3/5] PCI: designware: enhance dw_pcie_host_init() to support v3.65 DW hardware
From: Jingoo Han @ 2014-07-23  1:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405961925-27248-4-git-send-email-m-karicheri2@ti.com>

On Tuesday, July 22, 2014 1:59 AM, Murali Karicheri wrote:
> 
> keystone PCI controller is based on v3.65 designware hardware. This
> version differs from newer versions of the hardware in few functional
> areas discussed below that makes it necessary to change dw_pcie_host_init()
> to support v3.65 based PCI controller.
> 
>  1. No support for ATU port. So any ATU specific resource handling code
>     is to be bypassed for v3.65 h/w.
>  2. MSI controller uses Application space to implement MSI and 32 MSI
>     interrupts are multiplexed over 8 IRQs to the host. Hence the code
>     to process MSI IRQ needs to be different. This patch allows platform
>     driver to provide its own irq_domain_ops ptr to irq_domain_add_linear()
>     through an API callback from the designware core driver.
>  3. MSI interrupt generation requires EP to write to the RC's application
>     register. So enhance the driver to allow setup of inbound access to
>     MSI irq register as a post scan bus API callback.
> 
> Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
> Reviewed-by: Pratyush Anand <pratyush.anand@st.com>
> Acked-by: Mohit KUMAR <mohit.kumar@st.com>
> 
> CC: Santosh Shilimkar <santosh.shilimkar@ti.com>
> CC: Russell King <linux@arm.linux.org.uk>
> CC: Grant Likely <grant.likely@linaro.org>
> CC: Rob Herring <robh+dt@kernel.org>
> CC: Jingoo Han <jg1.han@samsung.com>

Acked-by: Jingoo Han <jg1.han@samsung.com>

Best regards,
Jingoo Han

> CC: Bjorn Helgaas <bhelgaas@google.com>
> CC: Richard Zhu <r65037@freescale.com>
> CC: Kishon Vijay Abraham I <kishon@ti.com>
> CC: Marek Vasut <marex@denx.de>
> CC: Arnd Bergmann <arnd@arndb.de>
> CC: Pawel Moll <pawel.moll@arm.com>
> CC: Mark Rutland <mark.rutland@arm.com>
> CC: Ian Campbell <ijc+devicetree@hellion.org.uk>
> CC: Kumar Gala <galak@codeaurora.org>
> CC: Randy Dunlap <rdunlap@infradead.org>
> CC: Grant Likely <grant.likely@linaro.org>
> ---
>  drivers/pci/host/pcie-designware.c |   54 +++++++++++++++++++++++-------------
>  drivers/pci/host/pcie-designware.h |    2 ++
>  2 files changed, 36 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 905941c..35bb4af 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -420,8 +420,8 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
>  	struct device_node *np = pp->dev->of_node;
>  	struct of_pci_range range;
>  	struct of_pci_range_parser parser;
> +	int i, ret;
>  	u32 val;
> -	int i;
> 
>  	if (of_pci_range_parser_init(&parser, np)) {
>  		dev_err(pp->dev, "missing ranges property\n");
> @@ -467,21 +467,26 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
>  		}
>  	}
> 
> -	pp->cfg0_base = pp->cfg.start;
> -	pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size;
>  	pp->mem_base = pp->mem.start;
> 
> -	pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> -					pp->config.cfg0_size);
>  	if (!pp->va_cfg0_base) {
> -		dev_err(pp->dev, "error with ioremap in function\n");
> -		return -ENOMEM;
> +		pp->cfg0_base = pp->cfg.start;
> +		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> +						pp->config.cfg0_size);
> +		if (!pp->va_cfg0_base) {
> +			dev_err(pp->dev, "error with ioremap in function\n");
> +			return -ENOMEM;
> +		}
>  	}
> -	pp->va_cfg1_base = devm_ioremap(pp->dev, pp->cfg1_base,
> -					pp->config.cfg1_size);
> +
>  	if (!pp->va_cfg1_base) {
> -		dev_err(pp->dev, "error with ioremap\n");
> -		return -ENOMEM;
> +		pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size;
> +		pp->va_cfg1_base = devm_ioremap(pp->dev, pp->cfg1_base,
> +						pp->config.cfg1_size);
> +		if (!pp->va_cfg1_base) {
> +			dev_err(pp->dev, "error with ioremap\n");
> +			return -ENOMEM;
> +		}
>  	}
> 
>  	if (of_property_read_u32(np, "num-lanes", &pp->lanes)) {
> @@ -490,16 +495,22 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
>  	}
> 
>  	if (IS_ENABLED(CONFIG_PCI_MSI)) {
> -		pp->irq_domain = irq_domain_add_linear(pp->dev->of_node,
> -					MAX_MSI_IRQS, &msi_domain_ops,
> -					&dw_pcie_msi_chip);
> -		if (!pp->irq_domain) {
> -			dev_err(pp->dev, "irq domain init failed\n");
> -			return -ENXIO;
> -		}
> +		if (!pp->ops->msi_host_init) {
> +			pp->irq_domain = irq_domain_add_linear(pp->dev->of_node,
> +						MAX_MSI_IRQS, &msi_domain_ops,
> +						&dw_pcie_msi_chip);
> +			if (!pp->irq_domain) {
> +				dev_err(pp->dev, "irq domain init failed\n");
> +				return -ENXIO;
> +			}
> 
> -		for (i = 0; i < MAX_MSI_IRQS; i++)
> -			irq_create_mapping(pp->irq_domain, i);
> +			for (i = 0; i < MAX_MSI_IRQS; i++)
> +				irq_create_mapping(pp->irq_domain, i);
> +		} else {
> +			ret = pp->ops->msi_host_init(pp, &dw_pcie_msi_chip);
> +			if (ret < 0)
> +				return ret;
> +		}
>  	}
> 
>  	if (pp->ops->host_init)
> @@ -759,6 +770,9 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
>  		BUG();
>  	}
> 
> +	if (bus && pp->ops->scan_bus)
> +		pp->ops->scan_bus(pp);
> +
>  	return bus;
>  }
> 
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index 387f69e..080c649 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -70,6 +70,8 @@ struct pcie_host_ops {
>  	void (*msi_set_irq)(struct pcie_port *pp, int irq);
>  	void (*msi_clear_irq)(struct pcie_port *pp, int irq);
>  	u32 (*get_msi_data)(struct pcie_port *pp);
> +	void (*scan_bus)(struct pcie_port *pp);
> +	int (*msi_host_init)(struct pcie_port *pp, struct msi_chip *chip);
>  };
> 
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val);
> --
> 1.7.9.5

^ permalink raw reply

* [PATCH v2] ARM: rockchip: Add cpu hotplug support for RK3XXX SoCs
From: Heiko Stübner @ 2014-07-23  0:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405775006-950-1-git-send-email-romain.perier@gmail.com>

Am Samstag, 19. Juli 2014, 13:03:26 schrieb Romain Perier:
> Adds ability to shutdown all CPUs except the first one
> (since it might be special for a lot of platforms).
> It is now possible to use kexec which requires such a feature.
> 
> Signed-off-by: Romain Perier <romain.perier@gmail.com>

works like a charm :-)

I've added it to my tree and will send it off in the next days.


Heiko

> ---
>  arch/arm/mach-rockchip/platsmp.c | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 
> diff --git a/arch/arm/mach-rockchip/platsmp.c
> b/arch/arm/mach-rockchip/platsmp.c index 910835d..189684f 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -21,6 +21,7 @@
>  #include <linux/of_address.h>
> 
>  #include <asm/cacheflush.h>
> +#include <asm/cp15.h>
>  #include <asm/smp_scu.h>
>  #include <asm/smp_plat.h>
>  #include <asm/mach/map.h>
> @@ -178,8 +179,27 @@ static void __init rockchip_smp_prepare_cpus(unsigned
> int max_cpus) pmu_set_power_domain(0 + i, false);
>  }
> 
> +#ifdef CONFIG_HOTPLUG_CPU
> +static int rockchip_cpu_kill(unsigned int cpu)
> +{
> +	pmu_set_power_domain(0 + cpu, false);
> +	return 1;
> +}
> +
> +static void rockchip_cpu_die(unsigned int cpu)
> +{
> +	v7_exit_coherency_flush(louis);
> +	while(1)
> +		cpu_do_idle();
> +}
> +#endif
> +
>  static struct smp_operations rockchip_smp_ops __initdata = {
>  	.smp_prepare_cpus	= rockchip_smp_prepare_cpus,
>  	.smp_boot_secondary	= rockchip_boot_secondary,
> +#ifdef CONFIG_HOTPLUG_CPU
> +	.cpu_kill		= rockchip_cpu_kill,
> +	.cpu_die		= rockchip_cpu_die,
> +#endif
>  };
>  CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp",
> &rockchip_smp_ops);

^ permalink raw reply

* [PATCH 0/6] net: mvpp2: Assorted fixes
From: David Miller @ 2014-07-23  0:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140722232004.GA7838@arch.cereza>

From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Date: Tue, 22 Jul 2014 20:20:04 -0300

> On 23 Jul 12:29 AM, Thomas Petazzoni wrote:
>> On Tue, 22 Jul 2014 13:16:39 -0700 (PDT), David Miller wrote:
>> 
>> > >> This series does not apply to the 'net' tree at all, please respin
>> > >> and resubmit.
>> > > 
>> > > This series applies on net-next.
>> > > 
>> > > Sorry for not mentioning it,
>> > 
>> > They are bonafide bug fixes, therefore should be targetted at 'net'.
>> 
>> Except that I believe they are fixes for a driver which itself is in
>> net-next, i.e scheduled for 3.17.
>> 
> 
> That's right. These are fixes for the new mvpp2 driver, which is only
> in net-next.

Ok, I queued them back up, thanks for the clarification.

^ permalink raw reply

* [PATCH v7 4/5] PCI: add PCI controller for keystone PCIe h/w
From: Bjorn Helgaas @ 2014-07-22 23:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <53CEEB1C.9020202@ti.com>

On Tue, Jul 22, 2014 at 06:52:12PM -0400, Murali Karicheri wrote:
> Bjorn,
> 
> On 07/22/2014 06:35 PM, Bjorn Helgaas wrote:
> >On Mon, Jul 21, 2014 at 12:58:44PM -0400, Murali Karicheri wrote:
> >>keystone PCIe controller is based on v3.65 version of the
> >>designware h/w. Main differences are
> >>	1. No ATU support
> >>	2. Legacy and MSI irq functions are implemented in
> >>	   application register space
> >>	3. MSI interrupts are multiplexed over 8 IRQ lines to the Host
> >>	   side.
> >>All of the Application register space handing code are organized into
> >>pci-keystone-dw.c and the functions are called from pci-keystone.c
> >>to implement PCI controller driver. Also add necessary DT documentation
> >>for the driver.
> >>
> >>Signed-off-by: Murali Karicheri<m-karicheri2@ti.com>
> >>Acked-by: Santosh Shilimkar<santosh.shilimkar@ti.com>
> >>...
> >
> >>+++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt
> >>...
> >
> >>+Note for PCI driver usage
> >>+=========================
> >>+Driver requires pci=pcie_bus_perf in the bootargs for proper functioning.
> >
> >Whoa, why is this?  Special boot args should not be required.
> 
> This was discussed initially and I had added following commit to get
> this working instead of a PCI quirk. To get some background please
> see the thread for commit below that you also had signed off as
> well.

I applied 8b5742ad156d because it's something all arches should do
(actually, we *should* do it in the PCI core, but nobody's gotten
around to doing that yet).  It has nothing to do with Keystone
support, and it doesn't mean I'm in favor of a boot argument.

I think the discussion you mentioned is [1].  I see hints that there
might be a Keystone hardware defect related to MRSS, but I don't see a
clear description of it.  If you have a hardware erratum document,
those usually contain pretty good descriptions.

If there is a hardware defect, a PCI quirk is a reasonable way to work
around it, since that's the main purpose of quirks.  fixup_mpss_256()
is an example of something that sounds superficially similar.

I don't think there's a way for a device to advertise the maximum MRSS
value it supports.  MRSS only controls the maximum Read Request size
the device can generate, and I wouldn't think there's much to go wrong
there, because the request doesn't contain any data, so MRSS doesn't
affect the packet size of the *request*.

I think it's more likely that a hardware problem would affect the
*response*, where, e.g., a device might advertise (via the Device
Capabilities Max_Payload_Size_Supported field) that it can support an
MPS of 1024, but it can't actually handle a TLP that big.  Software
would have to work around that by artificially limiting the MPS to
something smaller than the MPSS advertised by the device.  This is
what fixup_mpss_256() is doing.

If there is a hardware problem with MRSS specifically, you can
probably still do a quirk, but it might also involve a little work in
the PCI core to add something similar to pcie_mpss to support the
quirk.

Bjorn

[1] http://lkml.kernel.org/r/1400169692-9677-6-git-send-email-m-karicheri2 at ti.com

> commit 8b5742ad156d30ee38486652cdbd152e2d6ebbcc
> Author: Murali Karicheri <m-karicheri2@ti.com>
> Date:   Wed May 28 13:14:53 2014 -0400
> 
>     ARM/PCI: Call pcie_bus_configure_settings() to set MPS
> 
>     Call pcie_bus_configure_settings() on ARM, like for other platforms.
>     pcie_bus_configure_settings() makes sure the MPS across the bus
> is uniform
>     and provides the ability to tune the MRSS and MPS to higher performance
>     values.  This is particularly important for embedded where there is no
>     firmware to program these PCIe settings for the OS.
> 
>     Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
>     Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
>     CC: Russell King <linux@arm.linux.org.uk>
>     CC: Arnd Bergmann <arnd@arndb.de>
>     CC: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
>     CC: Santosh Shilimkar <santosh.shilimkar@ti.com>
> 
> This was added as a preparatory patch to support keystone and
> avoid a PCI quirk to do the same. Keystone has MRSS limitation
> of 256 bytes. So adding a bootargs flag was suggested a better
> option than a PCI quirk.
> 
> I will look into the rest of the comments and possibly try to
> address them or discuss.
> 
> BTW, please apply patch 1-3 that has already got ack from maintainers
> and is indepdent of this patch.
> 
> Thanks
> 
> Murali
> 
> >
> >>diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> >>index 21df477..f8bc475 100644
> >>--- a/drivers/pci/host/Kconfig
> >>+++ b/drivers/pci/host/Kconfig
> >>@@ -46,4 +46,9 @@ config PCI_HOST_GENERIC
> >>  	  Say Y here if you want to support a simple generic PCI host
> >>  	  controller, such as the one emulated by kvmtool.
> >>
> >>+config PCI_KEYSTONE
> >>+	bool "TI Keystone PCIe controller"
> >>+	depends on ARCH_KEYSTONE
> >>+	select PCIE_DW
> >>+	select PCIEPORTBUS
> >
> >It'd be nice to have some help text here.  I know, not everybody else does.
> >
> >>+++ b/drivers/pci/host/pci-keystone-dw.c
> >>...
> >>+void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie , int offset)
> >>+{
> >>+	struct pcie_port *pp =&ks_pcie->pp;
> >>+	u32 pending, vector;
> >>+	int src, virq;
> >>+
> >>+	pending = readl(ks_pcie->va_app_base + MSI0_IRQ_STATUS + (offset<<  4));
> >
> >Blank line here (before the block comment).
> >
> >>+	/*
> >>+	 * MSI0, Status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
> >>+	 * shows 1, 9, 17, 25 and so forth
> >>+	 */
> >>+	for (src = 0; src<  4; src++) {
> >>+		if (BIT(src)&  pending) {
> >>+			vector = offset + (src<<  3);
> >>+			virq = irq_linear_revmap(pp->irq_domain, vector);
> >>+			dev_dbg(pp->dev,
> >>+				"irq: bit %d, vector %d, virq %d\n",
> >>+				 src, vector, virq);
> >>+			generic_handle_irq(virq);
> >>+		}
> >>+	}
> >>+}
> >>+
> >>...
> >
> >>+static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
> >>+					unsigned int devfn)
> >>+{
> >>+	u8 device = PCI_SLOT(devfn), function = PCI_FUNC(devfn);
> >>+	struct pcie_port *pp =&ks_pcie->pp;
> >>+	u32 regval;
> >>+
> >>+	if (bus == 0)
> >>+		return pp->dbi_base;
> >>+
> >>+	regval = (bus<<  16) | (device<<  8) | function;
> >>+	/*
> >>+	 * Since Bus#1 will be a virtual bus, we need to have TYPE0
> >>+	 * access only.
> >>+	 * TYPE 1
> >>+	 */
> >>+	if (bus != 1)
> >>+		regval |= BIT(24);
> >>+
> >>+	writel(regval, ks_pcie->va_app_base + CFG_SETUP);
> >>+	return pp->va_cfg0_base;
> >>+}
> >>+
> >>+int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
> >>+		unsigned int devfn, int where, int size, u32 *val)
> >>+{
> >>+	struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> >>+	u8 bus_num = bus->number;
> >>+	void __iomem *addr;
> >>+	int ret;
> >>+
> >>+	addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
> >>+	ret = dw_pcie_cfg_read(addr + (where&  ~0x3), where, size, val);
> >
> >This *looks* like it needs a lock to protect against concurrent
> >ks_pcie_cfg_setup() users, since it writes a register.
> >
> >>+
> >>+	return ret;
> >
> >Please use the same style as in ks_dw_pcie_wr_other_conf(), i.e., get rid
> >of "ret".
> >
> >>+}
> >>+
> >>+int ks_dw_pcie_wr_other_conf(struct pcie_port *pp,
> >>+		struct pci_bus *bus, unsigned int devfn, int where,
> >>+		int size, u32 val)
> >>+{
> >>+	struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> >>+	u8 bus_num = bus->number;
> >>+	void __iomem *addr;
> >>+
> >>+	addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
> >>+
> >>+	return dw_pcie_cfg_write(addr + (where&  ~0x3), where, size, val);
> >>+}
> >
> >>+++ b/drivers/pci/host/pci-keystone.c
> >>...
> >
> >>+static struct platform_driver ks_pcie_driver __refdata = {
> >
> >Why does this need to be __refdata?  There are no other occurrences in
> >drivers/pci.
> >
> >>+	.probe  = ks_pcie_probe,
> >>+	.remove = __exit_p(ks_pcie_remove),
> >>+	.driver = {
> >>+		.name	= "keystone-pcie",
> >>+		.owner	= THIS_MODULE,
> >>+		.of_match_table = of_match_ptr(ks_pcie_of_match),
> >>+	},
> >>+};
> >
> >Bjorn
> 

^ permalink raw reply

* [PATCH] PM / OPP: Remove ARCH_HAS_OPP
From: Rafael J. Wysocki @ 2014-07-22 23:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406040192-632-1-git-send-email-broonie@kernel.org>

On Tuesday, July 22, 2014 03:43:12 PM Mark Brown wrote:
> From: Mark Brown <broonie@linaro.org>
> 
> Since the OPP layer is a kernel library which has been converted to be
> directly selectable by its callers rather than user selectable and
> requiring architectures to enable it explicitly the ARCH_HAS_OPP symbol
> has become redundant and can be removed. Do so.
> 
> Signed-off-by: Mark Brown <broonie@linaro.org>
> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
> Acked-by: Nishanth Menon <nm@ti.com>
> Acked-by: Rob Herring <robh@kernel.org>
> Acked-by: Shawn Guo <shawn.guo@freescale.com>
> Acked-by: Simon Horman <horms+renesas@verge.net.au>
> ---
> 
> Raphael, IIRC you said that you'd applied this but it seems not to have
> appeared in -next.  There's a few more references crept in, I'll try to
> get them removed at source.

I've queued this up for 3.17, thanks!

>  Documentation/power/opp.txt    | 3 ---
>  arch/arm/mach-exynos/Kconfig   | 1 -
>  arch/arm/mach-highbank/Kconfig | 1 -
>  arch/arm/mach-imx/Kconfig      | 1 -
>  arch/arm/mach-omap2/Kconfig    | 1 -
>  arch/arm/mach-shmobile/Kconfig | 2 --
>  arch/arm/mach-vexpress/Kconfig | 1 -
>  arch/arm/mach-zynq/Kconfig     | 1 -
>  drivers/devfreq/Kconfig        | 1 -
>  kernel/power/Kconfig           | 3 ---
>  10 files changed, 15 deletions(-)
> 
> diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
> index a9adad828cdc..c6279c2be47c 100644
> --- a/Documentation/power/opp.txt
> +++ b/Documentation/power/opp.txt
> @@ -51,9 +51,6 @@ Typical usage of the OPP library is as follows:
>  SoC framework	-> modifies on required cases certain OPPs	-> OPP layer
>  		-> queries to search/retrieve information	->
>  
> -Architectures that provide a SoC framework for OPP should select ARCH_HAS_OPP
> -to make the OPP layer available.
> -
>  OPP layer expects each domain to be represented by a unique device pointer. SoC
>  framework registers a set of initial OPPs per device with the OPP layer. This
>  list is expected to be an optimally small number typically around 5 per device.
> diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
> index 8f9b66c4ac78..f7889f6a1353 100644
> --- a/arch/arm/mach-exynos/Kconfig
> +++ b/arch/arm/mach-exynos/Kconfig
> @@ -100,7 +100,6 @@ config SOC_EXYNOS5440
>  	default y
>  	depends on ARCH_EXYNOS5
>  	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
> -	select ARCH_HAS_OPP
>  	select HAVE_ARM_ARCH_TIMER
>  	select AUTO_ZRELADDR
>  	select MIGHT_HAVE_PCI
> diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
> index a5960e2ac090..31aa866c3317 100644
> --- a/arch/arm/mach-highbank/Kconfig
> +++ b/arch/arm/mach-highbank/Kconfig
> @@ -2,7 +2,6 @@ config ARCH_HIGHBANK
>  	bool "Calxeda ECX-1000/2000 (Highbank/Midway)" if ARCH_MULTI_V7
>  	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
>  	select ARCH_HAS_HOLES_MEMORYMODEL
> -	select ARCH_HAS_OPP
>  	select ARCH_SUPPORTS_BIG_ENDIAN
>  	select ARM_AMBA
>  	select ARM_ERRATA_764369 if SMP
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index 2bc7b97861b4..9de84a215abd 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -1,6 +1,5 @@
>  menuconfig ARCH_MXC
>  	bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
> -	select ARCH_HAS_OPP
>  	select ARCH_REQUIRE_GPIOLIB
>  	select ARM_CPU_SUSPEND if PM
>  	select CLKSRC_MMIO
> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
> index 1c1ed737f7ab..e7189dcc9309 100644
> --- a/arch/arm/mach-omap2/Kconfig
> +++ b/arch/arm/mach-omap2/Kconfig
> @@ -15,7 +15,6 @@ config ARCH_OMAP3
>  	bool "TI OMAP3"
>  	depends on ARCH_MULTI_V7
>  	select ARCH_OMAP2PLUS
> -	select ARCH_HAS_OPP
>  	select ARM_CPU_SUSPEND if PM
>  	select OMAP_INTERCONNECT
>  	select PM_OPP if PM
> diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
> index 384221d72d22..5814754c1240 100644
> --- a/arch/arm/mach-shmobile/Kconfig
> +++ b/arch/arm/mach-shmobile/Kconfig
> @@ -92,7 +92,6 @@ config ARCH_R8A73A4
>  	select CPU_V7
>  	select SH_CLK_CPG
>  	select RENESAS_IRQC
> -	select ARCH_HAS_OPP
>  	select SYS_SUPPORTS_SH_CMT
>  	select SYS_SUPPORTS_SH_TMU
>  
> @@ -244,7 +243,6 @@ config MACH_KOELSCH
>  config MACH_KZM9G
>  	bool "KZM-A9-GT board"
>  	depends on ARCH_SH73A0
> -	select ARCH_HAS_OPP
>  	select ARCH_REQUIRE_GPIOLIB
>  	select REGULATOR_FIXED_VOLTAGE if REGULATOR
>  	select SND_SOC_AK4642 if SND_SIMPLE_CARD
> diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
> index d8b9330f896a..1af70329b88d 100644
> --- a/arch/arm/mach-vexpress/Kconfig
> +++ b/arch/arm/mach-vexpress/Kconfig
> @@ -64,7 +64,6 @@ config ARCH_VEXPRESS_DCSCB
>  
>  config ARCH_VEXPRESS_SPC
>  	bool "Versatile Express Serial Power Controller (SPC)"
> -	select ARCH_HAS_OPP
>  	select PM_OPP
>  	help
>  	  The TC2 (A15x2 A7x3) versatile express core tile integrates a logic
> diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
> index 0c164f81e72d..aaa5162c1509 100644
> --- a/arch/arm/mach-zynq/Kconfig
> +++ b/arch/arm/mach-zynq/Kconfig
> @@ -1,6 +1,5 @@
>  config ARCH_ZYNQ
>  	bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7
> -	select ARCH_HAS_OPP
>  	select ARCH_SUPPORTS_BIG_ENDIAN
>  	select ARM_AMBA
>  	select ARM_GIC
> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> index 49e74c1fc639..3dced0a9eae3 100644
> --- a/drivers/devfreq/Kconfig
> +++ b/drivers/devfreq/Kconfig
> @@ -68,7 +68,6 @@ comment "DEVFREQ Drivers"
>  config ARM_EXYNOS4_BUS_DEVFREQ
>  	bool "ARM Exynos4210/4212/4412 Memory Bus DEVFREQ Driver"
>  	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM
> -	select ARCH_HAS_OPP
>  	select DEVFREQ_GOV_SIMPLE_ONDEMAND
>  	select PM_OPP
>  	help
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index 9a83d780facd..e4e4121fa327 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -253,9 +253,6 @@ config APM_EMULATION
>  	  anything, try disabling/enabling this option (or disabling/enabling
>  	  APM in your BIOS).
>  
> -config ARCH_HAS_OPP
> -	bool
> -
>  config PM_OPP
>  	bool
>  	---help---
> 

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply

* [PATCHv4 5/5] arm64: Add atomic pool for non-coherent and CMA allocations.
From: Laura Abbott @ 2014-07-22 23:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140722210352.GA10604@arm.com>

On 7/22/2014 2:03 PM, Catalin Marinas wrote:
> On Tue, Jul 22, 2014 at 07:06:44PM +0100, Arnd Bergmann wrote:
[...]
>>> +               if (!addr)
>>> +                       goto destroy_genpool;
>>> +
>>> +               memset(addr, 0, atomic_pool_size);
>>> +               __dma_flush_range(addr, addr + atomic_pool_size);
>>
>> It also seems weird to flush the cache on a virtual address of
>> an uncacheable mapping. Is that well-defined?
> 
> Yes. According to D5.8.1 (Data and unified caches), "if cache
> maintenance is performed on a memory location, the effect of that cache
> maintenance is visible to all aliases of that physical memory location.
> These properties are consistent with implementing all caches that can
> handle data accesses as Physically-indexed, physically-tagged (PIPT)
> caches".
> 

This was actually unintentional on my part. I'm going to clean this up
to flush via the existing cached mapping to make it clearer what's going
on.

>> In the CMA case, the
>> original mapping should already be uncached here, so you don't need
>> to flush it.
> 
> I don't think it is non-cacheable already, at least not for arm64 (CMA
> can be used on coherent architectures as well).
> 

Memory allocated via dma_alloc_from_contiguous is not guaranteed to be
uncached. On arm, we allocate the page of memory and the remap it as
appropriate.

>> In the alloc_pages() case, I think you need to unmap
>> the pages from the linear mapping instead.
> 
> Even if unmapped, it would not remove dirty cache lines (which are
> associated with physical addresses anyway). But we don't need to worry
> about unmapping anyway, see above (that's unless we find some
> architecture implementation where having such cacheable/non-cacheable
> aliases is not efficient enough, the efficiency is not guaranteed by the
> ARM ARM, just the correct behaviour).
> 

Let's hope that never happens.

Thanks,
Laura

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply

* mvebu: Can we make the orion-mdio clock a requirement?
From: Ezequiel Garcia @ 2014-07-22 23:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140721222326.668db913@free-electrons.com>

On 21 Jul 10:23 PM, Thomas Petazzoni wrote:
> On Mon, 21 Jul 2014 22:12:45 +0200, Sebastian Hesselbarth wrote:
> 
> > > However, yes, I tend to agree, making the clock mandatory would
> > > probably be a good thing.
> > 
> > We can always pass TCLK on Orion5x if there is a need for a mandatory
> > clock. Anyway, IIRC clock framework should now properly return
> > -EPROPEDEFER only if there is a clock property set. If there is none,
> > the error is different and can be catched on Orion5x.
> 
> Yes, I already use tclk on Orion5x for various clock references.
> 

Since we all agree, I'll prepare a patchset changing the mvmdio devicetree
binding so the clock is required.

On the driver side, we can only print a warning if the clock is missing,
to keep compatibility.
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH v2 0/3] iommu: Remove OMAP IOVMM driver
From: Laurent Pinchart @ 2014-07-22 23:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140722061929.GD18374@atomide.com>

Hi Joerg,

(Your attention is kindly requested in time for v3.17, please see below)

On Monday 21 July 2014 23:19:29 Tony Lindgren wrote:
> * Laurent Pinchart <laurent.pinchart@ideasonboard.com> [140721 11:17]:
> > On Monday 21 July 2014 02:33:36 Tony Lindgren wrote:
> >> * Laurent Pinchart <laurent.pinchart@ideasonboard.com> [140721 02:16]:
> >>> On Friday 18 July 2014 11:53:56 Suman Anna wrote:
> >>>> On 07/18/2014 05:49 AM, Laurent Pinchart wrote:
> >>>>> Hello,
> >>>>> 
> >>>>> The OMAP3 ISP driver was the only user of the OMAP IOVMM API. Now
> >>>>> that is has been ported to the DMA API, remove the unused virtual
> >>>>> memory manager.
> >>>>> 
> >>>>> The removal is split in three patches to ease upstream merge. The
> >>>>> first patch removes the omap-iovmm driver, the second patch
> >>>>> removes setting of now unused platform data fields from arch code,
> >>>>> and the last patch cleans up the platform data structure.
> >>>> 
> >>>> Thanks for the revised series, it looks good. I have also tested the
> >>>> series on OMAP3, OMAP4 and OMAP5.
> >>>> 
> >>>> For the changes in the entire series,
> >>>> Acked-by: Suman Anna <s-anna@ti.com>
> >>> 
> >>> Thank you.
> >>> 
> >>>>> I'd like to get at least the first patch merged in v3.17. To avoid
> >>>>> splitting the series across three kernel versions, it would be
> >>>>> nice to also merge at least the second patch for v3.17. If there's
> >>>>> no risk of conflict everything could be merged in one go through
> >>>>> the ARM SoC tree. Otherwise a stable branch with patch 1/3 will be
> >>>>> needed to base the arch change on.
> >>>>> 
> >>>>> Joerg, Tony, how would you like to proceed ?
> >>> 
> >>> The v3.17 merge window is getting close, it's probably too late to
> >>> merge patch 2/3. Joerg, could you please take 1/3 in your tree for
> >>> v3.17 ? 2/3 and 3/3 would then get in v3.18. Tony, how would you like
> >>> to proceed for those ?
> >> 
> >> How about Joerg maybe do an immutable branch against v3.16-rc1
> >> with just these three patches and merge it into your tree?
> >> 
> >> That way I too can merge the minimal branch in if there are conflics.
> >> If that works for Joerg, then for arch/arm/*omap* changes:
> >> 
> >> Acked-by: Tony Lindgren <tony@atomide.com>
> > 
> > I've created an immutable branch (or, rather, immutable until the changes
> > reach mainline, at which point I will remove the branch) on top of
> > v3.16-rc1 with just the three patches from this series. You can find it
> > at.
> > 
> > 	git://linuxtv.org/pinchartl/media.git omap/iommu
> > 
> > Tony, is there still time to get this (and especially patch 2/3, which
> > touches arch/ code) in v3.17 ?
> 
> Yes as long as Joerg is OK to merge that branch in :)

Are you ? :-)

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* [PATCH] ARM: mm: implement no-highmem fast path in kmap_atomic_pfn()
From: Ezequiel Garcia @ 2014-07-22 23:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1404305055-16769-1-git-send-email-thomas.petazzoni@free-electrons.com>

On 02 Jul 02:44 PM, Thomas Petazzoni wrote:
> Since CONFIG_HIGHMEM got enabled on ARMv5 Kirkwood, we have noticed a
> very significant drop in networking performance. The test were
> conducted on an OpenBlocks A7 board. Without this patch, the outgoing
> performance measured with iperf are:
> 
>  - highmem OFF, TSO OFF   544 Mbit/s
>  - highmem OFF, TSO ON	  942 Mbit/s
>  - highmem ON,  TSO OFF   306 Mbit/s
>  - highmem ON,  TSO ON    246 Mbit/s
> 
> On this Kirkwood platform, the L2 cache is a Feroceon cache, and with
> this cache, all the range operations have to be done on virtual
> addresses and not physical addresses. Therefore, whenever
> CONFIG_HIGHMEM is enabled, the cache maintenance operations call
> kmap_atomic_pfn() and kunmap_atomic().
> 
> However, kmap_atomic_pfn() does not implement the same fast path for
> non-highmem pages as the one implemented in kmap_atomic(), and this is
> one of the reason for the performance drop. While this patch does not
> fully restore the performances, it clearly improves them a lot:
> 
>       	      	        without patch  with patch
> 
>  - highmem ON, TSO OFF   306 Mbit/s     387 Mbit/s
>  - highmem ON, TSO ON    246 Mbit/s     434 Mbit/s
> 
> We're still far from the !CONFIG_HIGHMEM performances, but it does
> improve a bit the situation.
> 
> Thanks a lot to Ezequiel Garcia and Gregory Clement for all the
> testing work around this topic.
> 
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
>  arch/arm/mm/highmem.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
> index 45aeaac..e17ed00 100644
> --- a/arch/arm/mm/highmem.c
> +++ b/arch/arm/mm/highmem.c
> @@ -127,8 +127,11 @@ void *kmap_atomic_pfn(unsigned long pfn)
>  {
>  	unsigned long vaddr;
>  	int idx, type;
> +	struct page *page = pfn_to_page(pfn);
>  
>  	pagefault_disable();
> +	if (!PageHighMem(page))
> +		return page_address(page);
>  
>  	type = kmap_atomic_idx_push();
>  	idx = type + KM_TYPE_NR * smp_processor_id();

What's the status of this one?
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH 1/3] ARM: exynos: remove unused <mach/memory.h>
From: Kukjin Kim @ 2014-07-22 23:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAOesGMgA0fc0_8JOOE01y=UKv-eAZuWiAkAKHG5iam0Zkhp9TA@mail.gmail.com>

On 07/23/14 01:14, Olof Johansson wrote:
> On Tue, Jul 22, 2014 at 12:51 AM, Uwe Kleine-K?nig
> <u.kleine-koenig@pengutronix.de>  wrote:
>> Hello,
>>
>> who takes care of this series?
>>
>> In fact they are all orthogonal to each other.
>>
>> The first patch
>>
>>          ARM: exynos: remove unused<mach/memory.h>
>>
>> has been reviewed and tested by Tomasz Figa and Sachin Kamat. Can the
>> Samsung people pick it up? Or armsoc?
>
> Kukjin should apply this one.
>
Oh, thanks for gentle reminder and I've applied into 2nd cleanup.

Thanks,
Kukjin


>> Patch 2 (v2!)
>>
>>          ARM: remove remaining definitions of PLAT_PHYS_OFFSET from<mach/memory.h>
>>
>> touches several arch/arm/mach-*/include/mach/memory.h and
>> arch/arm/Kconfig. armsoc? Russell?
>
> This can go through either, but Russell has already reviewed it once
> so send it to his patch tracker.
>
>> Patch 3 fixes a warning regarding nommu and touches the Kconfig entry
>> for Integrator and Renesas (non-multiplatform). armsoc?
>
> Don't know without seeing the patch. What's the patch subject so I can find it?

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox