Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/8] clk: sunxi: Add Allwinner A20/A31 GMAC clock unit
From: Maxime Ripard @ 2014-02-03 19:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391398346-5094-2-git-send-email-wens@csie.org>

Hi,

On Mon, Feb 03, 2014 at 11:32:19AM +0800, Chen-Yu Tsai wrote:
> The Allwinner A20/A31 clock module controls the transmit clock source
> and interface type of the GMAC ethernet controller. Model this as
> a single clock for GMAC drivers to use.
> 
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
>  Documentation/devicetree/bindings/clock/sunxi.txt | 26 +++++++
>  drivers/clk/sunxi/clk-sunxi.c                     | 83 +++++++++++++++++++++++
>  2 files changed, 109 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> index 0cf679b..f43b4c0 100644
> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> @@ -37,6 +37,7 @@ Required properties:
>  	"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
>  	"allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
>  	"allwinner,sun7i-a20-out-clk" - for the external output clocks
> +	"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
>  
>  Required properties for all clocks:
>  - reg : shall be the control register address for the clock.
> @@ -50,6 +51,9 @@ Required properties for all clocks:
>  	If the clock module only has one output, the name shall be the
>  	module name.
>  
> +For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
> +dummy clocks at 25 MHz and 125 MHz, respectively. See example.
> +
>  Clock consumers should specify the desired clocks they use with a
>  "clocks" phandle cell. Consumers that are using a gated clock should
>  provide an additional ID in their clock property. This ID is the
> @@ -96,3 +100,25 @@ mmc0_clk: clk at 01c20088 {
>  	clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
>  	clock-output-names = "mmc0";
>  };
> +
> +mii_phy_tx_clk: clk at 2 {
> +	#clock-cells = <0>;
> +	compatible = "fixed-clock";
> +	clock-frequency = <25000000>;
> +	clock-output-names = "mii_phy_tx";
> +};
> +
> +gmac_int_tx_clk: clk at 3 {
> +	#clock-cells = <0>;
> +	compatible = "fixed-clock";
> +	clock-frequency = <125000000>;
> +	clock-output-names = "gmac_int_tx";
> +};
> +
> +gmac_clk: clk at 01c20164 {
> +	#clock-cells = <0>;
> +	compatible = "allwinner,sun7i-a20-gmac-clk";
> +	reg = <0x01c20164 0x4>;
> +	clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;

You should also document in which order you expect the parents to
be. Or it will probably be easier to just use clock-names here.

> +	clock-output-names = "gmac";
> +};
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index 736fb60..0b361d2 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -379,6 +379,89 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
>  
>  
>  /**
> + * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
> + *
> + * This clock looks something like this
> + *                               ________________________
> + *  MII TX clock from PHY >-----|___________    _________|----> to GMAC core
> + *  GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
> + *  Ext. 125MHz RGMII TX clk >--|__divider__/            |
> + *                              |________________________|
> + *
> + * The external 125 MHz reference is optional, i.e. GMAC can use its
> + * internal TX clock just fine. The A31 GMAC clock module does not have
> + * the divider controls for the external reference.
> + *
> + * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
> + * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
> + * select the appropriate source and gate/ungate the output to the PHY.
> + *
> + * Only the GMAC should use this clock. Altering the clock so that it doesn't
> + * match the GMAC's operation parameters will result in the GMAC not being
> + * able to send traffic out. The GMAC driver should set the clock rate and
> + * enable/disable this clock to configure the required state. The clock
> + * driver then responds by auto-reparenting the clock.
> + */
> +
> +#define SUN7I_A20_GMAC_GPIT	2
> +#define SUN7I_A20_GMAC_MASK	0x3
> +#define SUN7I_A20_GMAC_MAX_PARENTS	2
> +
> +static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
> +{
> +	struct clk *clk;
> +	struct clk_mux *mux;
> +	struct clk_gate *gate;
> +	const char *clk_name = node->name;
> +	const char *parents[SUN7I_A20_GMAC_MAX_PARENTS];
> +	void *reg;
> +	int i = 0;
> +
> +	/* allocate mux and gate clock structs */
> +	mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
> +	if (!mux)
> +		return;

Newline.

> +	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
> +	if (!gate) {
> +		kfree(mux);
> +		return;
> +	}
> +
> +	reg = of_iomap(node, 0);

You should check for the return code here.

> +	of_property_read_string(node, "clock-output-names", &clk_name);

And here too, since you made the clock-output-names property mandatory

> +	while (i < SUN7I_A20_GMAC_MAX_PARENTS &&
> +			(parents[i] = of_clk_get_parent_name(node, i)) != NULL)

You should check for an error here too, but if you switch to using
clock-names, that will probably be refactored anyway.

> +		i++;
> +
> +	/* set up gate and fixed rate properties */
> +	gate->reg = reg;
> +	gate->bit_idx = SUN7I_A20_GMAC_GPIT;
> +	gate->lock = &clk_lock;
> +	mux->reg = reg;
> +	mux->mask = SUN7I_A20_GMAC_MASK;
> +	mux->flags = CLK_MUX_INDEX_BIT;
> +	mux->lock = &clk_lock;
> +
> +	clk = clk_register_composite(NULL, clk_name,
> +			parents, i,
> +			&mux->hw, &clk_mux_ops,
> +			NULL, NULL,
> +			&gate->hw, &clk_gate_ops,
> +			0);
> +
> +	if (!IS_ERR(clk)) {
> +		of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +		clk_register_clkdev(clk, clk_name, NULL);
> +	}
> +}
> +CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
> +		sun7i_a20_gmac_clk_setup);
> +
> +
> +
> +/**
>   * sunxi_factors_clk_setup() - Setup function for factor clocks
>   */
>  
> -- 
> 1.9.rc1
> 

It looks fine otherwise.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140203/1ee9717e/attachment.sig>

^ permalink raw reply

* [RFC] dtc: add ability to make nodes conditional on them being referenced
From: Maxime Ripard @ 2014-02-03 19:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1578575.rVWgTPdq1W@phil>

Hi,

On Thu, Jan 30, 2014 at 01:25:56PM +0100, Heiko St?bner wrote:
> From: Heiko Stuebner <heiko.stuebner@bqreaders.com>
> 
> On i.MX, which carries a lot of pin-groups of which most are unused on
> individual boards, they noticed that this plehora of nodes also results
> in the runtime-lookup-performance also degrading [0].
> 
> A i.MX-specific solution defining the pingroups in the board files but
> using macros to reference the pingroup-data was not well received
> 
> This patch is trying to solve this issue in a more general way, by
> adding the ability to mark nodes as needing to be referenced somewhere
> in the tree.
> 
> To mark a node a needing to be referenced it must be prefixed with
> /delete-unreferenced/. This makes dtc check the nodes reference-status
> when creating the flattened tree, dropping it if unreferenced.
> 
> For example, the i.MX6SL pingroup
> 
> 	/delete-uneferenced/ pinctrl_ecspi1_1: ecspi1grp-1 {
> 		fsl,pins = <
> 			MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
> 			MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
> 			MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
> 		>;
> 	};
> 
> would only be included in the dtb if it got referenced somewhere
> as pingroup via
> 
> 	node {
> 		pinctrl-0 <&pinctrl_ecscpi1_1>;
> 	};
> 
> [0] http://thread.gmane.org/gmane.linux.ports.arm.kernel/275912/
> 
> Signed-off-by: Heiko Stuebner <heiko.stuebner@bqreaders.com>
> ---
> This is just the idea I had in [1] explored a bit more. I'm definitely
> not sure if this is a valid approach to the problem.
> Also this is my first venture into dtc as well as flex and bison :-) .
> 
> [1] http://www.spinics.net/lists/arm-kernel/msg303731.html

This is a nice feature to have :)

However, I wonder wether it's the right way of implementing it. I'd
have another use case for this, which would be to embed a DT in a
first-stage bootloader. We have around 7kB available currently for the
DT, and this is actually less than any of our (very small already)
DTBs. So having this of feature makes complete sense to us
too. However, we also have some other tools that require most of the
nodes to be in the DTB.

So I guess turning wether we should delete a node if unreferenced into
a dtc option would make sense, since every DT user will be able to
choose, without having to duplicate the DT and make conflicting
changes.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140203/4771d4c2/attachment-0001.sig>

^ permalink raw reply

* [PATCH] ARM: unistd.h: relocate comments back to place
From: Baruch Siach @ 2014-02-03 19:21 UTC (permalink / raw)
  To: linux-arm-kernel

Commit cb8db5d45 (UAPI: (Scripted) Disintegrate arch/arm/include/asm) moved
these syscall comments out of their context into the UAPI headers. Fix this.

Fixes: cb8db5d4578a ("UAPI: (Scripted) Disintegrate arch/arm/include/asm")
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
---
 arch/arm/include/asm/unistd.h      | 10 ++++++++++
 arch/arm/include/uapi/asm/unistd.h | 11 -----------
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index acabef1a75df..4229595e5c04 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -15,7 +15,17 @@
 
 #include <uapi/asm/unistd.h>
 
+/*
+ * This may need to be greater than __NR_last_syscall+1 in order to
+ * account for the padding in the syscall table
+ */
 #define __NR_syscalls  (384)
+
+/*
+ * *NOTE*: This is a ghost syscall private to the kernel.  Only the
+ * __kuser_cmpxchg code in entry-armv.S should be aware of its
+ * existence.  Don't ever use this from user code.
+ */
 #define __ARM_NR_cmpxchg		(__ARM_NR_BASE+0x00fff0)
 
 #define __ARCH_WANT_STAT64
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
index fb5584d0cc05..c3776331f407 100644
--- a/arch/arm/include/uapi/asm/unistd.h
+++ b/arch/arm/include/uapi/asm/unistd.h
@@ -410,11 +410,6 @@
 #define __NR_sched_getattr		(__NR_SYSCALL_BASE+381)
 
 /*
- * This may need to be greater than __NR_last_syscall+1 in order to
- * account for the padding in the syscall table
- */
-
-/*
  * The following SWIs are ARM private.
  */
 #define __ARM_NR_BASE			(__NR_SYSCALL_BASE+0x0f0000)
@@ -425,12 +420,6 @@
 #define __ARM_NR_set_tls		(__ARM_NR_BASE+5)
 
 /*
- * *NOTE*: This is a ghost syscall private to the kernel.  Only the
- * __kuser_cmpxchg code in entry-armv.S should be aware of its
- * existence.  Don't ever use this from user code.
- */
-
-/*
  * The following syscalls are obsolete and no longer available for EABI.
  */
 #if !defined(__KERNEL__)
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH] arm64: Add architecture support for PCI
From: Liviu Dudau @ 2014-02-03 19:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <21596846.kVTqp7roW4@wuerfel>

On Mon, Feb 03, 2014 at 06:58:56PM +0000, Arnd Bergmann wrote:
> On Monday 03 February 2014 18:43:48 Liviu Dudau wrote:
> > diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> > index 4cc813e..ce5bad2 100644
> > --- a/arch/arm64/include/asm/io.h
> > +++ b/arch/arm64/include/asm/io.h
> > @@ -120,9 +120,13 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
> >  /*
> >   *  I/O port access primitives.
> >   */
> > +#define arch_has_dev_port()        (0)
>
> Why not?

Maybe I got it the wrong way around, but the comment in include/linux/io.h says:

/*
 * Some systems do not have legacy ISA devices.
 * /dev/port is not a valid interface on these systems.
 * So for those archs, <asm/io.h> should define the following symbol.
 */

So ... defining it should mean no legacy ISA devices, right?

>
> >  #define IO_SPACE_LIMIT             0xffff
>
> You probably want to increase this a bit, to allow multiple host bridges
> to have their own I/O space.

OK, but to what size?

>
> >  #define PCI_IOBASE         ((void __iomem *)(MODULES_VADDR - SZ_2M))
>
> And modify this location: There is no particular reason to have the I/O space
> mapped exactly 2MB below the loadable modules, as virtual address space is
> essentially free.

Will talk with Catalin about where to place this.

>
> > +#define ioport_map(port, nr)       (PCI_IOBASE + ((port) & IO_SPACE_LIMIT))
> > +#define ioport_unmap(addr)
>
> inline functions?

Will do, thanks!

>
> >  static inline u8 inb(unsigned long addr)
> >  {
> >     return readb(addr + PCI_IOBASE);
> > diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
> > new file mode 100644
> > index 0000000..dd084a3
> > --- /dev/null
> > +++ b/arch/arm64/include/asm/pci.h
> > @@ -0,0 +1,35 @@
> > +#ifndef __ASM_PCI_H
> > +#define __ASM_PCI_H
> > +#ifdef __KERNEL__
> > +
> > +#include <linux/types.h>
> > +#include <linux/slab.h>
> > +#include <linux/dma-mapping.h>
> > +
> > +#include <asm/io.h>
> > +#include <asm-generic/pci-bridge.h>
> > +#include <asm-generic/pci-dma-compat.h>
> > +
> > +#define PCIBIOS_MIN_IO             0
> > +#define PCIBIOS_MIN_MEM            0
>
> PCIBIOS_MIN_IO is normally set to 0x1000, to stay out of the ISA range.

:) No ISA support! (Die ISA, die!!)

>
> > diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
> > new file mode 100644
> > index 0000000..7b652cf
> > --- /dev/null
> > +++ b/arch/arm64/kernel/pci.c
> > @@ -0,0 +1,112 @@
>
> None of this looks really arm64 specific, nor should it be. I think
> we should try a little harder to move this as a default implementation
> into common code, even if we start out by having all architectures
> override it.

Agree. This is the RFC version. I didn't dare to post a patch with fixes
for all architectures. :)

>
> > +int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
> > +{
> > +   BUG_ON(offset + SZ_64K - 1 > IO_SPACE_LIMIT);
> > +
> > +   return ioremap_page_range((unsigned long)PCI_IOBASE + offset,
> > +                           (unsigned long)PCI_IOBASE + offset + SZ_64K,
> > +                           phys_addr,
> > +                           __pgprot(PROT_DEVICE_nGnRE));
> > +}
>
> Not sure if we want to treat this one as architecture specific though.
> It certainly won't be portable to x86, but it could be shared with
> a couple of others. We may also want to redesign the interface.
> I've been thinking we could make this function allocate space in the
> Linux virtual I/O space aperture, and pass two resources into it
> (physical I/O aperture and bus I/O range), and get the actual
> io_offset as the return value, or a negative error number.

Not sure I completely follow your idea.

>
> That way, you could have an arbitrary number of host bridges in the
> system and each one gets a share of the virtual aperture until
> it's full.

One still needs to fix the pci_request_region use that checks against
ioport_resource. But it is an interesting idea.

>
>       Arnd
>
>

Thanks for reviewing this patch!

Liviu

--
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?

-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium.  Thank you.

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2548782

^ permalink raw reply

* [PATCH] pci: Add support for creating a generic host_bridge from device tree
From: Liviu Dudau @ 2014-02-03 19:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <7398333.9L5KlyFggU@wuerfel>

Hi Arnd,

First of all, thanks for reviewing this!

On Mon, Feb 03, 2014 at 06:46:10PM +0000, Arnd Bergmann wrote:
> On Monday 03 February 2014 18:33:48 Liviu Dudau wrote:
> > +/**
> > + * pci_host_bridge_of_get_ranges - Parse PCI host bridge resources from DT
> > + * @dev: device node of the host bridge having the range property
> > + * @resources: list where the range of resources will be added after DT parsing
> > + *
> > + * This function will parse the "ranges" property of a PCI host bridge device
> > + * node and setup the resource mapping based on its content. It is expected
> > + * that the property conforms with the Power ePAPR document.
> > + *
> > + * Each architecture will then apply their filtering based on the limitations
> > + * of each platform. One general restriction seems to be the number of IO space
> > + * ranges, the PCI framework makes intensive use of struct resource management,
> > + * and for IORESOURCE_IO types they can only be requested if they are contained
> > + * within the global ioport_resource, so that should be limited to one IO space
> > + * range.
>
> Actually we have quite a different set of restrictions around I/O space on ARM32
> at the moment: Each host bridge can have its own 64KB range in an arbitrary
> location on MMIO space, and the total must not exceed 2MB of I/O space.

And that is why the filtering is not (yet) imposed in the generic code. But once
you use pci_request_region, that will call request_region which will check
against ioport_resource as parent for the requested resource. That should fail
if is is not in the correct range, so I don't know how arm arch code manages
multiple IO ranges.

>
> > + */
> > +static int pci_host_bridge_of_get_ranges(struct device_node *dev,
> > +                                   struct list_head *resources)
> > +{
> > +   struct resource *res;
> > +   struct of_pci_range range;
> > +   struct of_pci_range_parser parser;
> > +   int err;
> > +
> > +   pr_info("PCI host bridge %s ranges:\n", dev->full_name);
> > +
> > +   /* Check for ranges property */
> > +   err = of_pci_range_parser_init(&parser, dev);
> > +   if (err)
> > +           return err;
> > +
> > +   pr_debug("Parsing ranges property...\n");
> > +   for_each_of_pci_range(&parser, &range) {
> > +           /* Read next ranges element */
> > +           pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ",
> > +                           range.pci_space, range.pci_addr);
> > +           pr_debug("cpu_addr:0x%016llx size:0x%016llx\n",
> > +                                   range.cpu_addr, range.size);
> > +
> > +           /* If we failed translation or got a zero-sized region
> > +            * (some FW try to feed us with non sensical zero sized regions
> > +            * such as power3 which look like some kind of attempt
> > +            * at exposing the VGA memory hole) then skip this range
> > +            */
> > +           if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
> > +                   continue;
> > +
> > +           res = kzalloc(sizeof(struct resource), GFP_KERNEL);
> > +           if (!res) {
> > +                   err = -ENOMEM;
> > +                   goto bridge_ranges_nomem;
> > +           }
> > +
> > +           of_pci_range_to_resource(&range, dev, res);
> > +
> > +           pci_add_resource_offset(resources, res,
> > +                           range.cpu_addr - range.pci_addr);
> > +   }
>
> I believe of_pci_range_to_resource() will return the MMIO aperture for the
> I/O space window here, which is not what you are supposed to pass into
> pci_add_resource_offset.

And that is why the code in probe.c has been added to deal with that. It is
too early to do the adjustments here as all we have is the list of resources
and that might get culled by the architecture fixup code. Remembering the
io_offset will happen once the pci_host_bridge gets created, and the resources
are then adjusted.

>
> > +EXPORT_SYMBOL(pci_host_bridge_of_init);
>
> EXPORT_SYMBOL_GPL

Will change for v2, thanks!

>
> > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> > index 6e34498..16febae 100644
> > --- a/drivers/pci/probe.c
> > +++ b/drivers/pci/probe.c
> > @@ -1787,6 +1787,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
> >     list_for_each_entry_safe(window, n, resources, list) {
> >             list_move_tail(&window->list, &bridge->windows);
> >             res = window->res;
> > +           /*
> > +            * IO resources are stored in the kernel with a CPU start
> > +            * address of zero. Adjust the data accordingly and remember
> > +            * the offset
> > +            */
> > +           if (resource_type(res) == IORESOURCE_IO) {
> > +                   bridge->io_offset = res->start;
> > +                   res->end -= res->start;
> > +                   window->offset -= res->start;
> > +                   res->start = 0;
> > +           }
> >             offset = window->offset;
> >             if (res->flags & IORESOURCE_BUS)
>
> Won't this break all existing host bridges?

I am not sure. I believe not, due to what I've explained earlier, but you might be right.

The adjustment happens before the resource is added to the host bridge windows and translates
it from MMIO range into IO range.

Best regards,
Liviu

>
>       Arnd
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>

--
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?

-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium.  Thank you.

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2548782

^ permalink raw reply

* [PATCH] arm64: Add architecture support for PCI
From: Arnd Bergmann @ 2014-02-03 18:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391453028-23191-2-git-send-email-Liviu.Dudau@arm.com>

On Monday 03 February 2014 18:43:48 Liviu Dudau wrote:
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 4cc813e..ce5bad2 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -120,9 +120,13 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  /*
>   *  I/O port access primitives.
>   */
> +#define arch_has_dev_port()	(0)

Why not?

>  #define IO_SPACE_LIMIT		0xffff

You probably want to increase this a bit, to allow multiple host bridges
to have their own I/O space.

>  #define PCI_IOBASE		((void __iomem *)(MODULES_VADDR - SZ_2M))

And modify this location: There is no particular reason to have the I/O space
mapped exactly 2MB below the loadable modules, as virtual address space is
essentially free.

> +#define ioport_map(port, nr)	(PCI_IOBASE + ((port) & IO_SPACE_LIMIT))
> +#define ioport_unmap(addr)

inline functions?

>  static inline u8 inb(unsigned long addr)
>  {
>  	return readb(addr + PCI_IOBASE);
> diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
> new file mode 100644
> index 0000000..dd084a3
> --- /dev/null
> +++ b/arch/arm64/include/asm/pci.h
> @@ -0,0 +1,35 @@
> +#ifndef __ASM_PCI_H
> +#define __ASM_PCI_H
> +#ifdef __KERNEL__
> +
> +#include <linux/types.h>
> +#include <linux/slab.h>
> +#include <linux/dma-mapping.h>
> +
> +#include <asm/io.h>
> +#include <asm-generic/pci-bridge.h>
> +#include <asm-generic/pci-dma-compat.h>
> +
> +#define PCIBIOS_MIN_IO		0
> +#define PCIBIOS_MIN_MEM		0

PCIBIOS_MIN_IO is normally set to 0x1000, to stay out of the ISA range.

> diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
> new file mode 100644
> index 0000000..7b652cf
> --- /dev/null
> +++ b/arch/arm64/kernel/pci.c
> @@ -0,0 +1,112 @@

None of this looks really arm64 specific, nor should it be. I think
we should try a little harder to move this as a default implementation
into common code, even if we start out by having all architectures
override it.

> +int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
> +{
> +	BUG_ON(offset + SZ_64K - 1 > IO_SPACE_LIMIT);
> +
> +	return ioremap_page_range((unsigned long)PCI_IOBASE + offset,
> +				(unsigned long)PCI_IOBASE + offset + SZ_64K,
> +				phys_addr,
> +				__pgprot(PROT_DEVICE_nGnRE));
> +}

Not sure if we want to treat this one as architecture specific though.
It certainly won't be portable to x86, but it could be shared with
a couple of others. We may also want to redesign the interface.
I've been thinking we could make this function allocate space in the
Linux virtual I/O space aperture, and pass two resources into it
(physical I/O aperture and bus I/O range), and get the actual
io_offset as the return value, or a negative error number.

That way, you could have an arbitrary number of host bridges in the
system and each one gets a share of the virtual aperture until
it's full.

	Arnd

^ permalink raw reply

* [PATCH] pci: Add support for creating a generic host_bridge from device tree
From: Arnd Bergmann @ 2014-02-03 18:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391452428-22917-2-git-send-email-Liviu.Dudau@arm.com>

On Monday 03 February 2014 18:33:48 Liviu Dudau wrote:
> +/**
> + * pci_host_bridge_of_get_ranges - Parse PCI host bridge resources from DT
> + * @dev: device node of the host bridge having the range property
> + * @resources: list where the range of resources will be added after DT parsing
> + *
> + * This function will parse the "ranges" property of a PCI host bridge device
> + * node and setup the resource mapping based on its content. It is expected
> + * that the property conforms with the Power ePAPR document.
> + *
> + * Each architecture will then apply their filtering based on the limitations
> + * of each platform. One general restriction seems to be the number of IO space
> + * ranges, the PCI framework makes intensive use of struct resource management,
> + * and for IORESOURCE_IO types they can only be requested if they are contained
> + * within the global ioport_resource, so that should be limited to one IO space
> + * range.

Actually we have quite a different set of restrictions around I/O space on ARM32
at the moment: Each host bridge can have its own 64KB range in an arbitrary
location on MMIO space, and the total must not exceed 2MB of I/O space.

> + */
> +static int pci_host_bridge_of_get_ranges(struct device_node *dev,
> +					struct list_head *resources)
> +{
> +	struct resource *res;
> +	struct of_pci_range range;
> +	struct of_pci_range_parser parser;
> +	int err;
> +
> +	pr_info("PCI host bridge %s ranges:\n", dev->full_name);
> +
> +	/* Check for ranges property */
> +	err = of_pci_range_parser_init(&parser, dev);
> +	if (err)
> +		return err;
> +
> +	pr_debug("Parsing ranges property...\n");
> +	for_each_of_pci_range(&parser, &range) {
> +		/* Read next ranges element */
> +		pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ",
> +				range.pci_space, range.pci_addr);
> +		pr_debug("cpu_addr:0x%016llx size:0x%016llx\n",
> +					range.cpu_addr, range.size);
> +
> +		/* If we failed translation or got a zero-sized region
> +		 * (some FW try to feed us with non sensical zero sized regions
> +		 * such as power3 which look like some kind of attempt
> +		 * at exposing the VGA memory hole) then skip this range
> +		 */
> +		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
> +			continue;
> +
> +		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
> +		if (!res) {
> +			err = -ENOMEM;
> +			goto bridge_ranges_nomem;
> +		}
> +
> +		of_pci_range_to_resource(&range, dev, res);
> +
> +		pci_add_resource_offset(resources, res,
> +				range.cpu_addr - range.pci_addr);
> +	}

I believe of_pci_range_to_resource() will return the MMIO aperture for the
I/O space window here, which is not what you are supposed to pass into
pci_add_resource_offset.

> +EXPORT_SYMBOL(pci_host_bridge_of_init);

EXPORT_SYMBOL_GPL

> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 6e34498..16febae 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1787,6 +1787,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>  	list_for_each_entry_safe(window, n, resources, list) {
>  		list_move_tail(&window->list, &bridge->windows);
>  		res = window->res;
> +		/*
> +		 * IO resources are stored in the kernel with a CPU start
> +		 * address of zero. Adjust the data accordingly and remember
> +		 * the offset
> +		 */
> +		if (resource_type(res) == IORESOURCE_IO) {
> +			bridge->io_offset = res->start;
> +			res->end -= res->start;
> +			window->offset -= res->start;
> +			res->start = 0;
> +		}
>  		offset = window->offset;
>  		if (res->flags & IORESOURCE_BUS)

Won't this break all existing host bridges?

	Arnd

^ permalink raw reply

* [PATCH] arm64: Add architecture support for PCI
From: Liviu Dudau @ 2014-02-03 18:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391453028-23191-1-git-send-email-Liviu.Dudau@arm.com>

Use the generic host bridge functions to provide support for
PCI Express on arm64. There is no support for ISA memory.

Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 arch/arm64/Kconfig            |  17 +++++++
 arch/arm64/include/asm/Kbuild |   1 +
 arch/arm64/include/asm/io.h   |   4 ++
 arch/arm64/include/asm/pci.h  |  35 +++++++++++++
 arch/arm64/kernel/Makefile    |   1 +
 arch/arm64/kernel/pci.c       | 112 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 170 insertions(+)
 create mode 100644 arch/arm64/include/asm/pci.h
 create mode 100644 arch/arm64/kernel/pci.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index f8e5ee6..48fdd69 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -133,6 +133,23 @@ menu "Bus support"
 config ARM_AMBA
 	bool
 
+config PCI
+	bool "PCI support"
+	help
+	  This feature enables support for PCIe bus system. If you say Y
+	  here, the kernel will include drivers and infrastructure code
+	  to support PCIe bus devices.
+
+config PCI_DOMAINS
+	def_bool PCI
+
+config PCI_SYSCALL
+	def_bool PCI
+
+source "drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
+source "drivers/pci/hotplug/Kconfig"
+
 endmenu
 
 menu "Kernel Features"
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 71c53ec..46924bc 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -26,6 +26,7 @@ generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += pci.h
+generic-y += pci-bridge.h
 generic-y += poll.h
 generic-y += posix_types.h
 generic-y += resource.h
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 4cc813e..ce5bad2 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -120,9 +120,13 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 /*
  *  I/O port access primitives.
  */
+#define arch_has_dev_port()	(0)
 #define IO_SPACE_LIMIT		0xffff
 #define PCI_IOBASE		((void __iomem *)(MODULES_VADDR - SZ_2M))
 
+#define ioport_map(port, nr)	(PCI_IOBASE + ((port) & IO_SPACE_LIMIT))
+#define ioport_unmap(addr)
+
 static inline u8 inb(unsigned long addr)
 {
 	return readb(addr + PCI_IOBASE);
diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
new file mode 100644
index 0000000..dd084a3
--- /dev/null
+++ b/arch/arm64/include/asm/pci.h
@@ -0,0 +1,35 @@
+#ifndef __ASM_PCI_H
+#define __ASM_PCI_H
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm-generic/pci-bridge.h>
+#include <asm-generic/pci-dma-compat.h>
+
+#define PCIBIOS_MIN_IO		0
+#define PCIBIOS_MIN_MEM		0
+
+/*
+ * Set to 1 if the kernel should re-assign all PCI bus numbers
+ */
+#define pcibios_assign_all_busses() \
+	(pci_has_flag(PCI_REASSIGN_ALL_BUS))
+
+/*
+ * PCI address space differs from physical memory address space
+ */
+#define PCI_DMA_BUS_IS_PHYS	(0)
+
+extern int isa_dma_bridge_buggy;
+
+extern int pci_domain_nr(struct pci_bus *bus);
+extern int pci_proc_domain(struct pci_bus *bus);
+
+extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
+
+#endif  /* __KERNEL__ */
+#endif  /* __ASM_PCI_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d7fcc1..8cfec47 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -21,6 +21,7 @@ arm64-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)	+= sleep.o suspend.o
 arm64-obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
 arm64-obj-$(CONFIG_SCHED_HMP)		+= sched_hmp.o
+arm64-obj-$(CONFIG_PCI)			+= pci.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
new file mode 100644
index 0000000..7b652cf
--- /dev/null
+++ b/arch/arm64/kernel/pci.c
@@ -0,0 +1,112 @@
+/*
+ * Code borrowed from powerpc/kernel/pci-common.c
+ *
+ * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Copyright (C) 2014 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+
+#include <asm/pci-bridge.h>
+
+
+/*
+ * Return the domain number for this bus
+ */
+int pci_domain_nr(struct pci_bus *bus)
+{
+	struct pci_host_bridge *bridge = to_pci_host_bridge(bus->bridge);
+
+	if (bridge)
+		return bridge->domain_nr;
+
+	return 0;
+}
+
+int pci_proc_domain(struct pci_bus *bus)
+{
+	return pci_domain_nr(bus);
+}
+
+/*
+ * Called after each bus is probed, but before its children are examined
+ */
+void pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	struct resource *res;
+	int i;
+
+	if (bus->self != NULL) {
+		pci_read_bridge_bases(bus);
+
+		pci_bus_for_each_resource(bus, res, i) {
+			if (!res || !res->flags || res->parent)
+				continue;
+
+			/*
+			 * If we are going to reassign everything, we can
+			 * shrink the P2P resource to have zero size to
+			 * save space
+			 */
+			if (pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
+				res->flags |= IORESOURCE_UNSET;
+				res->start = 0;
+				res->end = -1;
+				continue;
+			}
+		}
+	}
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		/* Ignore fully discovered devices */
+		if (dev->is_added)
+			continue;
+
+		set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
+
+		/* Read default IRQs and fixup if necessary */
+		dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
+	}
+}
+EXPORT_SYMBOL(pcibios_fixup_bus);
+
+/*
+ * We don't have to worry about legacy ISA devices, so nothing to do here
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	return ALIGN(res->start, align);
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	return pci_enable_resources(dev, mask);
+}
+
+void pcibios_fixup_bridge_ranges(struct list_head *resources)
+{
+}
+
+int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
+{
+	BUG_ON(offset + SZ_64K - 1 > IO_SPACE_LIMIT);
+
+	return ioremap_page_range((unsigned long)PCI_IOBASE + offset,
+				(unsigned long)PCI_IOBASE + offset + SZ_64K,
+				phys_addr,
+				__pgprot(PROT_DEVICE_nGnRE));
+}
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH] [RFC] Add AArch64 support for PCI
From: Liviu Dudau @ 2014-02-03 18:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This patch adds support for PCI to AArch64. It is based on the patch posted
here [1] that adds support for creating generic host bridge structure from
device tree. With that in place, I was able to boot an FPGA platform that
has PCIe host bridge support and use a PCIe network card.

The API used is different from the one used by ARM architecture. There is
no pci_common_init_dev() function and no hw_pci structure, as that is no
longer needed. Once the last signature is added to the legal agreement, I
will post the host bridge driver code that I am using. Meanwhile, here
is an example of what the probe function looks like, posted as an example:

static int myhostbridge_probe(struct platform_device *pdev)
{
	int err;
	struct device_node *dev;
	struct pci_host_bridge *bridge;
	struct resource bus_range;
	struct myhostbridge_port *pp;
	LIST_HEAD(resources);

	dev = pdev->dev.of_node;

	if (!of_device_is_available(dev)) {
		pr_warn("%s: disabled\n", dev->full_name);
		return -ENODEV;
	}

	pp = kzalloc(sizeof(struct myhostbridge_port), GFP_KERNEL);
	if (!pp)
		return -ENOMEM;

	err = of_pci_parse_bus_range(dev, &bus_range);
	if (err) {
		bus_range.start = 0;
		bus_range.end = 255;
		bus_range.flags = IORESOURCE_BUS;
	}
	pci_add_resource(&resources, &bus_range);

	bridge = pci_host_bridge_of_init(&pdev->dev, 0, &myhostbridge_ops, pp, &resources);
	if (!bridge) {
		err = -EINVAL;
		goto bridge_init_fail;
	}

	err = myhostbridge_setup(bridge->bus);
	if (err)
		goto bridge_init_fail;

	/*
	 * Add flags here, this is just an example
	 */
	pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
	pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC);

	bus_range.end = pci_scan_child_bus(bridge->bus);
	pci_bus_update_busn_res_end(bridge->bus, bus_range.end);

	pci_assign_unassigned_bus_resources(bridge->bus);

	pci_bus_add_devices(bridge->bus);

	return 0;

bridge_init_fail:
	kfree(pp);
	pci_free_resource_list(&resources);
	return err;
}

Best regards,
Liviu

[1] http://marc.info/?l=linux-pci&m=139145254821334&w=2

Liviu Dudau (1):
  arm64: Add support for PCI

 arch/arm64/Kconfig            |  17 +++++++
 arch/arm64/include/asm/Kbuild |   1 +
 arch/arm64/include/asm/io.h   |   4 ++
 arch/arm64/include/asm/pci.h  |  35 +++++++++++++
 arch/arm64/kernel/Makefile    |   1 +
 arch/arm64/kernel/pci.c       | 112 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 170 insertions(+)
 create mode 100644 arch/arm64/include/asm/pci.h
 create mode 100644 arch/arm64/kernel/pci.c

-- 
1.8.5.3

^ permalink raw reply

* [PATCH] pci: Add support for creating a generic host_bridge from device tree
From: Liviu Dudau @ 2014-02-03 18:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391452428-22917-1-git-send-email-Liviu.Dudau@arm.com>

Several platforms use a rather generic version of parsing
the device tree to find the host bridge ranges. Move that
into the generic PCI code and use it to create a pci_host_bridge
structure that can be used by arch code.

Based on early attempts by Andrew Murray to unify the code.
Used powerpc and microblaze PCI code as starting point.

Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Cc: Catalin Marinas <Catalin.Marinas@arm.com>
Cc: Will Deacon <Will.Deacon@arm.com>
---
 drivers/pci/host-bridge.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/probe.c       | 11 ++++++
 include/linux/pci.h       | 14 ++++++++
 3 files changed, 117 insertions(+)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 06ace62..9d11deb 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -6,6 +6,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 
 #include "pci.h"
 
@@ -91,3 +92,94 @@ void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
 	res->end = region->end + offset;
 }
 EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+/**
+ * pci_host_bridge_of_get_ranges - Parse PCI host bridge resources from DT
+ * @dev: device node of the host bridge having the range property
+ * @resources: list where the range of resources will be added after DT parsing
+ *
+ * This function will parse the "ranges" property of a PCI host bridge device
+ * node and setup the resource mapping based on its content. It is expected
+ * that the property conforms with the Power ePAPR document.
+ *
+ * Each architecture will then apply their filtering based on the limitations
+ * of each platform. One general restriction seems to be the number of IO space
+ * ranges, the PCI framework makes intensive use of struct resource management,
+ * and for IORESOURCE_IO types they can only be requested if they are contained
+ * within the global ioport_resource, so that should be limited to one IO space
+ * range.
+ */
+static int pci_host_bridge_of_get_ranges(struct device_node *dev,
+					struct list_head *resources)
+{
+	struct resource *res;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
+	int err;
+
+	pr_info("PCI host bridge %s ranges:\n", dev->full_name);
+
+	/* Check for ranges property */
+	err = of_pci_range_parser_init(&parser, dev);
+	if (err)
+		return err;
+
+	pr_debug("Parsing ranges property...\n");
+	for_each_of_pci_range(&parser, &range) {
+		/* Read next ranges element */
+		pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ",
+				range.pci_space, range.pci_addr);
+		pr_debug("cpu_addr:0x%016llx size:0x%016llx\n",
+					range.cpu_addr, range.size);
+
+		/* If we failed translation or got a zero-sized region
+		 * (some FW try to feed us with non sensical zero sized regions
+		 * such as power3 which look like some kind of attempt
+		 * at exposing the VGA memory hole) then skip this range
+		 */
+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
+			continue;
+
+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+		if (!res) {
+			err = -ENOMEM;
+			goto bridge_ranges_nomem;
+		}
+
+		of_pci_range_to_resource(&range, dev, res);
+
+		pci_add_resource_offset(resources, res,
+				range.cpu_addr - range.pci_addr);
+	}
+
+	/* Apply architecture specific fixups for the ranges */
+	pcibios_fixup_bridge_ranges(resources);
+
+	return 0;
+
+bridge_ranges_nomem:
+	pci_free_resource_list(resources);
+	return err;
+}
+
+struct pci_host_bridge *
+pci_host_bridge_of_init(struct device *parent, int busno, struct pci_ops *ops,
+			void *host_data, struct list_head *resources)
+{
+	struct pci_bus *root_bus;
+	struct pci_host_bridge *bridge;
+
+	/* first parse the host bridge bus ranges */
+	if (pci_host_bridge_of_get_ranges(parent->of_node, resources))
+		return NULL;
+
+	/* then create the root bus */
+	root_bus = pci_create_root_bus(parent, busno, ops, host_data, resources);
+	if (!root_bus)
+		return NULL;
+
+	bridge = to_pci_host_bridge(root_bus->bridge);
+
+	return bridge;
+}
+EXPORT_SYMBOL(pci_host_bridge_of_init);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6e34498..16febae 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1787,6 +1787,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	list_for_each_entry_safe(window, n, resources, list) {
 		list_move_tail(&window->list, &bridge->windows);
 		res = window->res;
+		/*
+		 * IO resources are stored in the kernel with a CPU start
+		 * address of zero. Adjust the data accordingly and remember
+		 * the offset
+		 */
+		if (resource_type(res) == IORESOURCE_IO) {
+			bridge->io_offset = res->start;
+			res->end -= res->start;
+			window->offset -= res->start;
+			res->start = 0;
+		}
 		offset = window->offset;
 		if (res->flags & IORESOURCE_BUS)
 			pci_bus_insert_busn_res(b, bus, res->end);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index fb57c89..8953997 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -394,6 +394,8 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
 	struct device dev;
 	struct pci_bus *bus;		/* root bus */
+	resource_size_t io_offset;	/* CPU address offset for io resources */
+	int domain_nr;
 	struct list_head windows;	/* pci_host_bridge_windows */
 	void (*release_fn)(struct pci_host_bridge *);
 	void *release_data;
@@ -1762,11 +1764,23 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
 	return bus ? bus->dev.of_node : NULL;
 }
 
+struct pci_host_bridge *
+pci_host_bridge_of_init(struct device *parent, int busno, struct pci_ops *ops,
+			void *host_data, struct list_head *resources);
+
+void pcibios_fixup_bridge_ranges(struct list_head *resources);
 #else /* CONFIG_OF */
 static inline void pci_set_of_node(struct pci_dev *dev) { }
 static inline void pci_release_of_node(struct pci_dev *dev) { }
 static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
 static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
+
+static inline struct pci_host_bridge *
+pci_host_bridge_of_init(struct device *parent, struct pci_ops *ops,
+			void *host_data, struct list_head *resources)
+{
+	return NULL;
+}
 #endif  /* CONFIG_OF */
 
 #ifdef CONFIG_EEH
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH] [RFC] Support for creating generic host_bridge from device tree
From: Liviu Dudau @ 2014-02-03 18:33 UTC (permalink / raw)
  To: linux-arm-kernel

Following the discussion started here [1], I now have a proposal for tackling
generic support for host bridges described via device tree. It is an initial
stab at it, to try to get feedback and suggestions, but it is functional enough
that I have PCI Express for arm64 working on an FPGA using the patch that I am
also publishing that adds support for PCI for that platform.

Looking at the existing architectures that fit the requirements (use of device
tree and PCI) yields the powerpc and microblaze as generic enough to make them
candidates for conversion. I have a tentative patch for microblaze that I can
only compile test it, unfortunately using qemu-microblaze leads to an early
crash in the kernel.

As Bjorn has mentioned in the previous discussion, the idea is to add to
struct pci_host_bridge enough data to be able to reduce the size or remove the
architecture specific pci_controller structure. arm64 support actually manages
to get rid of all the architecture static data and has no pci_controller structure
defined. For host bridge drivers that means a change of API unless architectures
decide to provide a compatibility layer (comments here please).

In order to initialise a host bridge with the new API, the following example
code is sufficient for a _probe() function:

static int myhostbridge_probe(struct platform_device *pdev)
{
	int err;
	struct device_node *dev;
	struct pci_host_bridge *bridge;
	struct resource bus_range;
	struct myhostbridge_port *pp;
	LIST_HEAD(resources);

	dev = pdev->dev.of_node;

	if (!of_device_is_available(dev)) {
		pr_warn("%s: disabled\n", dev->full_name);
		return -ENODEV;
	}

	pp = kzalloc(sizeof(struct myhostbridge_port), GFP_KERNEL);
	if (!pp)
		return -ENOMEM;

	err = of_pci_parse_bus_range(dev, &bus_range);
	if (err) {
		bus_range.start = 0;
		bus_range.end = 255;
		bus_range.flags = IORESOURCE_BUS;
	}
	pci_add_resource(&resources, &bus_range);

	bridge = pci_host_bridge_of_init(&pdev->dev, 0, &myhostbridge_ops, pp, &resources);
	if (!bridge) {
		err = -EINVAL;
		goto bridge_init_fail;
	}

	err = myhostbridge_setup(bridge->bus);
	if (err)
		goto bridge_init_fail;

	/*
	 * Add flags here, this is just an example
	 */
	pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
	pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC);

	bus_range.end = pci_scan_child_bus(bridge->bus);
	pci_bus_update_busn_res_end(bridge->bus, bus_range.end);

	pci_assign_unassigned_bus_resources(bridge->bus);

	pci_bus_add_devices(bridge->bus);

	return 0;

bridge_init_fail:
	kfree(pp);
	pci_free_resource_list(&resources);
	return err;
}

Best regards,
Liviu Dudau

[1] http://thread.gmane.org/gmane.linux.kernel.pci/25946

Liviu Dudau (1):
  pci: Add support for creating a generic host_bridge from device tree

 drivers/pci/host-bridge.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/probe.c       | 11 ++++++
 include/linux/pci.h       | 14 ++++++++
 3 files changed, 117 insertions(+)

-- 
1.8.5.3

^ permalink raw reply

* [PATCH v5 0/4] perf: AARCH64 arch support
From: Jean Pihet @ 2014-02-03 18:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140124163548.GH31040@mudshark.cambridge.arm.com>

Hi Will, Arnaldo,

On 24 January 2014 17:35, Will Deacon <will.deacon@arm.com> wrote:
> Hi Jean,
>
> On Wed, Jan 22, 2014 at 02:11:15PM +0000, Jean Pihet wrote:
>> Add AARCH64 specific support. This includes the following:
>> - AARCH64 perf registers definition and hooks,
>> - compat mode registers use, i.e. profiling a 32-bit binary on
>>    a 64-bit system,
>> - unwinding using the dwarf information from the .debug_frame
>>    section of the ELF binary,
>> - unwinding using the frame pointer information; in 64-bit and
>>    compat modes.
>>
>> Note: support for unwinding using the dwarf information in compat
>> mode requires some changes to the libunwind code. Those changes
>> have been submitted on the libunwind ML and are in discussion.
>>
>> Tested on ARMv7, ARMv8 and x86_64 platforms. The compat mode has been
>> tested on ARMv8 using statically built 32-bit binaries.
>
> This is look alright to me now, but there are still two blockers:
>
>  (1) Getting the libunwind code merged
This one is independent of the kernel changes. The libunwind stuff is
under disuccsion atm, cf. libunwind ML.

>  (2) Splitting this into an arch/arm64 series and a tools/perf series, so
>      that acme can merge the latter independently (and avoid the mess we had
>      last time).
Split into:
- the tools/perf change: '[PATCH] perf: ARM64: wire up perf_regs and
unwind support'
and
- the arch/arm64 changes: '[PATCH v6 0/3] perf: AARCH64 arch support'.


>
> Anyway, for the series:
>
>   Acked-by: Will Deacon <will.deacon@arm.com>
Thanks! I have added your Acked-By in the series.

>
> Will

Jean

^ permalink raw reply

* [PATCH 3/3] ARM64: perf: support dwarf unwinding in compat mode
From: Jean Pihet @ 2014-02-03 18:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391451509-31265-1-git-send-email-jean.pihet@linaro.org>

Add support for unwinding using the dwarf information in compat
mode. Using the correct user stack pointer allows perf to record
the frames correctly in the native and compat modes.

Note that although the dwarf frame unwinding works ok using
libunwind in native mode (on ARMv7 & ARMv8), some changes are
required to the libunwind code for the compat mode. Those changes
are posted separately on the libunwind mailing list.

Tested on ARMv8 platform with v8 and compat v7 binaries, the latter
are statically built.

Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/compat.h | 2 +-
 arch/arm64/include/asm/ptrace.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index fda2704..e71f81f 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -228,7 +228,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
 	return (u32)(unsigned long)uptr;
 }
 
-#define compat_user_stack_pointer() (current_pt_regs()->compat_sp)
+#define compat_user_stack_pointer() (user_stack_pointer(current_pt_regs()))
 
 static inline void __user *arch_compat_alloc_user_space(long len)
 {
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index fbb0020..86d5b54 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -133,7 +133,7 @@ struct pt_regs {
 	(!((regs)->pstate & PSR_F_BIT))
 
 #define user_stack_pointer(regs) \
-	((regs)->sp)
+	(!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp)
 
 /*
  * Are the current registers suitable for user mode? (used to maintain
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH 2/3] ARM64: perf: add support for frame pointer unwinding in compat mode
From: Jean Pihet @ 2014-02-03 18:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391451509-31265-1-git-send-email-jean.pihet@linaro.org>

When profiling a 32-bit application, user space callchain unwinding
using the frame pointer is performed in compat mode. The code is taken
over from the AARCH32 code and adapted to work on AARCH64.

Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/kernel/perf_event.c | 75 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 67 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 5b1cd79..e868c72 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -1348,8 +1348,8 @@ early_initcall(init_hw_perf_events);
  * Callchain handling code.
  */
 struct frame_tail {
-	struct frame_tail   __user *fp;
-	unsigned long	    lr;
+	struct frame_tail	__user *fp;
+	unsigned long		lr;
 } __attribute__((packed));
 
 /*
@@ -1386,22 +1386,80 @@ user_backtrace(struct frame_tail __user *tail,
 	return buftail.fp;
 }
 
+/*
+ * The registers we're interested in are at the end of the variable
+ * length saved register structure. The fp points at the end of this
+ * structure so the address of this struct is:
+ * (struct compat_frame_tail *)(xxx->fp)-1
+ *
+ * This code has been adapted from the ARM OProfile support.
+ */
+struct compat_frame_tail {
+	compat_uptr_t	fp; /* a (struct compat_frame_tail *) in compat mode */
+	u32		sp;
+	u32		lr;
+} __attribute__((packed));
+
+static struct compat_frame_tail __user *
+compat_user_backtrace(struct compat_frame_tail __user *tail,
+		      struct perf_callchain_entry *entry)
+{
+	struct compat_frame_tail buftail;
+	unsigned long err;
+
+	/* Also check accessibility of one struct frame_tail beyond */
+	if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
+		return NULL;
+
+	pagefault_disable();
+	err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
+	pagefault_enable();
+
+	if (err)
+		return NULL;
+
+	perf_callchain_store(entry, buftail.lr);
+
+	/*
+	 * Frame pointers should strictly progress back up the stack
+	 * (towards higher addresses).
+	 */
+	if (tail + 1 >= (struct compat_frame_tail __user *)
+			compat_ptr(buftail.fp))
+		return NULL;
+
+	return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1;
+}
+
 void perf_callchain_user(struct perf_callchain_entry *entry,
 			 struct pt_regs *regs)
 {
-	struct frame_tail __user *tail;
-
 	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
 		/* We don't support guest os callchain now */
 		return;
 	}
 
 	perf_callchain_store(entry, regs->pc);
-	tail = (struct frame_tail __user *)regs->regs[29];
 
-	while (entry->nr < PERF_MAX_STACK_DEPTH &&
-	       tail && !((unsigned long)tail & 0xf))
-		tail = user_backtrace(tail, entry);
+	if (!compat_user_mode(regs)) {
+		/* AARCH64 mode */
+		struct frame_tail __user *tail;
+
+		tail = (struct frame_tail __user *)regs->regs[29];
+
+		while (entry->nr < PERF_MAX_STACK_DEPTH &&
+		       tail && !((unsigned long)tail & 0xf))
+			tail = user_backtrace(tail, entry);
+	} else {
+		/* AARCH32 compat mode */
+		struct compat_frame_tail __user *tail;
+
+		tail = (struct compat_frame_tail __user *)regs->compat_fp - 1;
+
+		while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
+			tail && !((unsigned long)tail & 0x3))
+			tail = compat_user_backtrace(tail, entry);
+	}
 }
 
 /*
@@ -1429,6 +1487,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,
 	frame.fp = regs->regs[29];
 	frame.sp = regs->sp;
 	frame.pc = regs->pc;
+
 	walk_stackframe(&frame, callchain_trace, entry);
 }
 
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH 1/3] ARM64: perf: add support for perf registers API
From: Jean Pihet @ 2014-02-03 18:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391451509-31265-1-git-send-email-jean.pihet@linaro.org>

This patch implements the functions required for the perf registers API,
allowing the perf tool to interface kernel register dumps with libunwind
in order to provide userspace backtracing.
Compat mode is also supported.

Only the general purpose user space registers are exported, i.e.:
 PERF_REG_ARM_X0,
 ...
 PERF_REG_ARM_X28,
 PERF_REG_ARM_FP,
 PERF_REG_ARM_LR,
 PERF_REG_ARM_SP,
 PERF_REG_ARM_PC
and not the PERF_REG_ARM_V* registers.

Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/Kconfig                      |  2 ++
 arch/arm64/include/asm/ptrace.h         |  1 +
 arch/arm64/include/uapi/asm/Kbuild      |  1 +
 arch/arm64/include/uapi/asm/perf_regs.h | 40 ++++++++++++++++++++++++++++++
 arch/arm64/kernel/Makefile              |  1 +
 arch/arm64/kernel/perf_regs.c           | 44 +++++++++++++++++++++++++++++++++
 6 files changed, 89 insertions(+)
 create mode 100644 arch/arm64/include/uapi/asm/perf_regs.h
 create mode 100644 arch/arm64/kernel/perf_regs.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index dd4327f..e9899bb 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -37,6 +37,8 @@ config ARM64
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
 	select HAVE_PERF_EVENTS
+	select HAVE_PERF_REGS
+	select HAVE_PERF_USER_STACK_DUMP
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 0e7fa49..fbb0020 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -68,6 +68,7 @@
 
 /* Architecturally defined mapping between AArch32 and AArch64 registers */
 #define compat_usr(x)	regs[(x)]
+#define compat_fp	regs[11]
 #define compat_sp	regs[13]
 #define compat_lr	regs[14]
 #define compat_sp_hyp	regs[15]
diff --git a/arch/arm64/include/uapi/asm/Kbuild b/arch/arm64/include/uapi/asm/Kbuild
index e4b78bd..942376d 100644
--- a/arch/arm64/include/uapi/asm/Kbuild
+++ b/arch/arm64/include/uapi/asm/Kbuild
@@ -9,6 +9,7 @@ header-y += byteorder.h
 header-y += fcntl.h
 header-y += hwcap.h
 header-y += kvm_para.h
+header-y += perf_regs.h
 header-y += param.h
 header-y += ptrace.h
 header-y += setup.h
diff --git a/arch/arm64/include/uapi/asm/perf_regs.h b/arch/arm64/include/uapi/asm/perf_regs.h
new file mode 100644
index 0000000..172b831
--- /dev/null
+++ b/arch/arm64/include/uapi/asm/perf_regs.h
@@ -0,0 +1,40 @@
+#ifndef _ASM_ARM64_PERF_REGS_H
+#define _ASM_ARM64_PERF_REGS_H
+
+enum perf_event_arm_regs {
+	PERF_REG_ARM64_X0,
+	PERF_REG_ARM64_X1,
+	PERF_REG_ARM64_X2,
+	PERF_REG_ARM64_X3,
+	PERF_REG_ARM64_X4,
+	PERF_REG_ARM64_X5,
+	PERF_REG_ARM64_X6,
+	PERF_REG_ARM64_X7,
+	PERF_REG_ARM64_X8,
+	PERF_REG_ARM64_X9,
+	PERF_REG_ARM64_X10,
+	PERF_REG_ARM64_X11,
+	PERF_REG_ARM64_X12,
+	PERF_REG_ARM64_X13,
+	PERF_REG_ARM64_X14,
+	PERF_REG_ARM64_X15,
+	PERF_REG_ARM64_X16,
+	PERF_REG_ARM64_X17,
+	PERF_REG_ARM64_X18,
+	PERF_REG_ARM64_X19,
+	PERF_REG_ARM64_X20,
+	PERF_REG_ARM64_X21,
+	PERF_REG_ARM64_X22,
+	PERF_REG_ARM64_X23,
+	PERF_REG_ARM64_X24,
+	PERF_REG_ARM64_X25,
+	PERF_REG_ARM64_X26,
+	PERF_REG_ARM64_X27,
+	PERF_REG_ARM64_X28,
+	PERF_REG_ARM64_X29,
+	PERF_REG_ARM64_LR,
+	PERF_REG_ARM64_SP,
+	PERF_REG_ARM64_PC,
+	PERF_REG_ARM64_MAX,
+};
+#endif /* _ASM_ARM64_PERF_REGS_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..9a5d592 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -15,6 +15,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
+arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
 arm64-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c
new file mode 100644
index 0000000..f2d6f0a
--- /dev/null
+++ b/arch/arm64/kernel/perf_regs.c
@@ -0,0 +1,44 @@
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/perf_event.h>
+#include <linux/bug.h>
+#include <asm/perf_regs.h>
+#include <asm/ptrace.h>
+
+u64 perf_reg_value(struct pt_regs *regs, int idx)
+{
+	if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM64_MAX))
+		return 0;
+
+	/*
+	 * Compat (i.e. 32 bit) mode:
+	 * - PC has been set in the pt_regs struct in kernel_entry,
+	 * - Handle SP and LR here.
+	 */
+	if (compat_user_mode(regs)) {
+		if ((u32)idx == PERF_REG_ARM64_SP)
+			return regs->compat_sp;
+		if ((u32)idx == PERF_REG_ARM64_LR)
+			return regs->compat_lr;
+	}
+
+	return regs->regs[idx];
+}
+
+#define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1))
+
+int perf_reg_validate(u64 mask)
+{
+	if (!mask || mask & REG_RESERVED)
+		return -EINVAL;
+
+	return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+	if (is_compat_thread(task_thread_info(task)))
+		return PERF_SAMPLE_REGS_ABI_32;
+	else
+		return PERF_SAMPLE_REGS_ABI_64;
+}
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH v6 0/3] perf: AARCH64 arch support
From: Jean Pihet @ 2014-02-03 18:18 UTC (permalink / raw)
  To: linux-arm-kernel

Add AARCH64 specific support. This includes the following:
- AARCH64 perf registers definition and hooks,
- compat mode registers use, i.e. profiling a 32-bit binary on
   a 64-bit system,
- unwinding using the dwarf information from the .debug_frame
   section of the ELF binary,
- unwinding using the frame pointer information; in 64-bit and
   compat modes.

Notes:
- the tools/perf change is submitted separately on LKML,
- support for unwinding using the dwarf information in compat
mode requires some changes to the libunwind code. Those changes
have been submitted on the libunwind ML and are in discussion.

Tested on ARMv7, ARMv8 and x86_64 platforms. The compat mode has been
tested on ARMv8 using statically built 32-bit binaries.


Jean Pihet (3):
  ARM64: perf: add support for perf registers API
  ARM64: perf: add support for frame pointer unwinding in compat mode
  ARM64: perf: support dwarf unwinding in compat mode

 arch/arm64/Kconfig                      |  2 +
 arch/arm64/include/asm/compat.h         |  2 +-
 arch/arm64/include/asm/ptrace.h         |  3 +-
 arch/arm64/include/uapi/asm/Kbuild      |  1 +
 arch/arm64/include/uapi/asm/perf_regs.h | 40 ++++++++++++++++++
 arch/arm64/kernel/Makefile              |  1 +
 arch/arm64/kernel/perf_event.c          | 75 +++++++++++++++++++++++++++++----
 arch/arm64/kernel/perf_regs.c           | 44 +++++++++++++++++++
 8 files changed, 158 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm64/include/uapi/asm/perf_regs.h
 create mode 100644 arch/arm64/kernel/perf_regs.c

-- 
1.7.11.7

^ permalink raw reply

* [PATCH] perf: ARM64: wire up perf_regs and unwind support
From: Jean Pihet @ 2014-02-03 18:17 UTC (permalink / raw)
  To: linux-arm-kernel

This patch hooks in the perf_regs and libunwind code for ARM64.
The tools/perf/arch/arm64 is created; it contains the arch specific
code for DWARF unwinding.

Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
---
 tools/perf/arch/arm64/Makefile            |  7 +++
 tools/perf/arch/arm64/include/perf_regs.h | 88 +++++++++++++++++++++++++++++++
 tools/perf/arch/arm64/util/dwarf-regs.c   | 80 ++++++++++++++++++++++++++++
 tools/perf/arch/arm64/util/unwind.c       | 82 ++++++++++++++++++++++++++++
 tools/perf/config/Makefile                |  8 ++-
 5 files changed, 264 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/arch/arm64/Makefile
 create mode 100644 tools/perf/arch/arm64/include/perf_regs.h
 create mode 100644 tools/perf/arch/arm64/util/dwarf-regs.c
 create mode 100644 tools/perf/arch/arm64/util/unwind.c

diff --git a/tools/perf/arch/arm64/Makefile b/tools/perf/arch/arm64/Makefile
new file mode 100644
index 0000000..fe9b61e
--- /dev/null
+++ b/tools/perf/arch/arm64/Makefile
@@ -0,0 +1,7 @@
+ifndef NO_DWARF
+PERF_HAVE_DWARF_REGS := 1
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
+endif
+ifndef NO_LIBUNWIND
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o
+endif
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
new file mode 100644
index 0000000..2359546
--- /dev/null
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -0,0 +1,88 @@
+#ifndef ARCH_PERF_REGS_H
+#define ARCH_PERF_REGS_H
+
+#include <stdlib.h>
+#include "../../util/types.h"
+#include <asm/perf_regs.h>
+
+#define PERF_REGS_MASK	((1ULL << PERF_REG_ARM64_MAX) - 1)
+#define PERF_REG_IP	PERF_REG_ARM64_PC
+#define PERF_REG_SP	PERF_REG_ARM64_SP
+
+static inline const char *perf_reg_name(int id)
+{
+	switch (id) {
+	case PERF_REG_ARM64_X0:
+		return "x0";
+	case PERF_REG_ARM64_X1:
+		return "x1";
+	case PERF_REG_ARM64_X2:
+		return "x2";
+	case PERF_REG_ARM64_X3:
+		return "x3";
+	case PERF_REG_ARM64_X4:
+		return "x4";
+	case PERF_REG_ARM64_X5:
+		return "x5";
+	case PERF_REG_ARM64_X6:
+		return "x6";
+	case PERF_REG_ARM64_X7:
+		return "x7";
+	case PERF_REG_ARM64_X8:
+		return "x8";
+	case PERF_REG_ARM64_X9:
+		return "x9";
+	case PERF_REG_ARM64_X10:
+		return "x10";
+	case PERF_REG_ARM64_X11:
+		return "x11";
+	case PERF_REG_ARM64_X12:
+		return "x12";
+	case PERF_REG_ARM64_X13:
+		return "x13";
+	case PERF_REG_ARM64_X14:
+		return "x14";
+	case PERF_REG_ARM64_X15:
+		return "x15";
+	case PERF_REG_ARM64_X16:
+		return "x16";
+	case PERF_REG_ARM64_X17:
+		return "x17";
+	case PERF_REG_ARM64_X18:
+		return "x18";
+	case PERF_REG_ARM64_X19:
+		return "x19";
+	case PERF_REG_ARM64_X20:
+		return "x20";
+	case PERF_REG_ARM64_X21:
+		return "x21";
+	case PERF_REG_ARM64_X22:
+		return "x22";
+	case PERF_REG_ARM64_X23:
+		return "x23";
+	case PERF_REG_ARM64_X24:
+		return "x24";
+	case PERF_REG_ARM64_X25:
+		return "x25";
+	case PERF_REG_ARM64_X26:
+		return "x26";
+	case PERF_REG_ARM64_X27:
+		return "x27";
+	case PERF_REG_ARM64_X28:
+		return "x28";
+	case PERF_REG_ARM64_X29:
+		return "x29";
+	case PERF_REG_ARM64_SP:
+		return "sp";
+	case PERF_REG_ARM64_LR:
+		return "lr";
+	case PERF_REG_ARM64_PC:
+		return "pc";
+	default:
+		return NULL;
+	}
+
+	return NULL;
+}
+
+#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/arm64/util/dwarf-regs.c b/tools/perf/arch/arm64/util/dwarf-regs.c
new file mode 100644
index 0000000..d49efeb
--- /dev/null
+++ b/tools/perf/arch/arm64/util/dwarf-regs.c
@@ -0,0 +1,80 @@
+/*
+ * Mapping of DWARF debug register numbers into register names.
+ *
+ * Copyright (C) 2010 Will Deacon, ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <stddef.h>
+#include <dwarf-regs.h>
+
+struct pt_regs_dwarfnum {
+	const char *name;
+	unsigned int dwarfnum;
+};
+
+#define STR(s) #s
+#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
+#define GPR_DWARFNUM_NAME(num) \
+	{.name = STR(%x##num), .dwarfnum = num}
+#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
+
+/*
+ * Reference:
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0057b/IHI0057B_aadwarf64.pdf
+ */
+static const struct pt_regs_dwarfnum regdwarfnum_table[] = {
+	GPR_DWARFNUM_NAME(0),
+	GPR_DWARFNUM_NAME(1),
+	GPR_DWARFNUM_NAME(2),
+	GPR_DWARFNUM_NAME(3),
+	GPR_DWARFNUM_NAME(4),
+	GPR_DWARFNUM_NAME(5),
+	GPR_DWARFNUM_NAME(6),
+	GPR_DWARFNUM_NAME(7),
+	GPR_DWARFNUM_NAME(8),
+	GPR_DWARFNUM_NAME(9),
+	GPR_DWARFNUM_NAME(10),
+	GPR_DWARFNUM_NAME(11),
+	GPR_DWARFNUM_NAME(12),
+	GPR_DWARFNUM_NAME(13),
+	GPR_DWARFNUM_NAME(14),
+	GPR_DWARFNUM_NAME(15),
+	GPR_DWARFNUM_NAME(16),
+	GPR_DWARFNUM_NAME(17),
+	GPR_DWARFNUM_NAME(18),
+	GPR_DWARFNUM_NAME(19),
+	GPR_DWARFNUM_NAME(20),
+	GPR_DWARFNUM_NAME(21),
+	GPR_DWARFNUM_NAME(22),
+	GPR_DWARFNUM_NAME(23),
+	GPR_DWARFNUM_NAME(24),
+	GPR_DWARFNUM_NAME(25),
+	GPR_DWARFNUM_NAME(26),
+	GPR_DWARFNUM_NAME(27),
+	GPR_DWARFNUM_NAME(28),
+	GPR_DWARFNUM_NAME(29),
+	REG_DWARFNUM_NAME("%lr", 30),
+	REG_DWARFNUM_NAME("%sp", 31),
+	REG_DWARFNUM_END,
+};
+
+/**
+ * get_arch_regstr() - lookup register name from it's DWARF register number
+ * @n:	the DWARF register number
+ *
+ * get_arch_regstr() returns the name of the register in struct
+ * regdwarfnum_table from it's DWARF register number. If the register is not
+ * found in the table, this returns NULL;
+ */
+const char *get_arch_regstr(unsigned int n)
+{
+	const struct pt_regs_dwarfnum *roff;
+	for (roff = regdwarfnum_table; roff->name != NULL; roff++)
+		if (roff->dwarfnum == n)
+			return roff->name;
+	return NULL;
+}
diff --git a/tools/perf/arch/arm64/util/unwind.c b/tools/perf/arch/arm64/util/unwind.c
new file mode 100644
index 0000000..8d37a4c
--- /dev/null
+++ b/tools/perf/arch/arm64/util/unwind.c
@@ -0,0 +1,82 @@
+
+#include <errno.h>
+#include <libunwind.h>
+#include "perf_regs.h"
+#include "../../util/unwind.h"
+
+int unwind__arch_reg_id(int regnum)
+{
+	switch (regnum) {
+	case UNW_AARCH64_X0:
+		return PERF_REG_ARM64_X0;
+	case UNW_AARCH64_X1:
+		return PERF_REG_ARM64_X1;
+	case UNW_AARCH64_X2:
+		return PERF_REG_ARM64_X2;
+	case UNW_AARCH64_X3:
+		return PERF_REG_ARM64_X3;
+	case UNW_AARCH64_X4:
+		return PERF_REG_ARM64_X4;
+	case UNW_AARCH64_X5:
+		return PERF_REG_ARM64_X5;
+	case UNW_AARCH64_X6:
+		return PERF_REG_ARM64_X6;
+	case UNW_AARCH64_X7:
+		return PERF_REG_ARM64_X7;
+	case UNW_AARCH64_X8:
+		return PERF_REG_ARM64_X8;
+	case UNW_AARCH64_X9:
+		return PERF_REG_ARM64_X9;
+	case UNW_AARCH64_X10:
+		return PERF_REG_ARM64_X10;
+	case UNW_AARCH64_X11:
+		return PERF_REG_ARM64_X11;
+	case UNW_AARCH64_X12:
+		return PERF_REG_ARM64_X12;
+	case UNW_AARCH64_X13:
+		return PERF_REG_ARM64_X13;
+	case UNW_AARCH64_X14:
+		return PERF_REG_ARM64_X14;
+	case UNW_AARCH64_X15:
+		return PERF_REG_ARM64_X15;
+	case UNW_AARCH64_X16:
+		return PERF_REG_ARM64_X16;
+	case UNW_AARCH64_X17:
+		return PERF_REG_ARM64_X17;
+	case UNW_AARCH64_X18:
+		return PERF_REG_ARM64_X18;
+	case UNW_AARCH64_X19:
+		return PERF_REG_ARM64_X19;
+	case UNW_AARCH64_X20:
+		return PERF_REG_ARM64_X20;
+	case UNW_AARCH64_X21:
+		return PERF_REG_ARM64_X21;
+	case UNW_AARCH64_X22:
+		return PERF_REG_ARM64_X22;
+	case UNW_AARCH64_X23:
+		return PERF_REG_ARM64_X23;
+	case UNW_AARCH64_X24:
+		return PERF_REG_ARM64_X24;
+	case UNW_AARCH64_X25:
+		return PERF_REG_ARM64_X25;
+	case UNW_AARCH64_X26:
+		return PERF_REG_ARM64_X26;
+	case UNW_AARCH64_X27:
+		return PERF_REG_ARM64_X27;
+	case UNW_AARCH64_X28:
+		return PERF_REG_ARM64_X28;
+	case UNW_AARCH64_X29:
+		return PERF_REG_ARM64_X29;
+	case UNW_AARCH64_X30:
+		return PERF_REG_ARM64_LR;
+	case UNW_AARCH64_SP:
+		return PERF_REG_ARM64_SP;
+	case UNW_AARCH64_PC:
+		return PERF_REG_ARM64_PC;
+	default:
+		pr_err("unwind: invalid reg id %d\n", regnum);
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index c48d449..5c0a6ed 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -29,11 +29,17 @@ ifeq ($(ARCH),x86)
   endif
   NO_PERF_REGS := 0
 endif
+
 ifeq ($(ARCH),arm)
   NO_PERF_REGS := 0
   LIBUNWIND_LIBS = -lunwind -lunwind-arm
 endif
 
+ifeq ($(ARCH),arm64)
+  NO_PERF_REGS := 0
+  LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
+endif
+
 ifeq ($(LIBUNWIND_LIBS),)
   NO_LIBUNWIND := 1
 else
@@ -327,7 +333,7 @@ ifndef NO_LIBUNWIND
     msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1);
     NO_LIBUNWIND := 1
   else
-    ifeq ($(ARCH),arm)
+    ifeq ($(ARCH),$(filter $(ARCH),arm arm64))
       $(call feature_check,libunwind-debug-frame)
       ifneq ($(feature-libunwind-debug-frame), 1)
         msg := $(warning No debug_frame support found in libunwind);
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH v4 2/5] arm: add new asm macro update_sctlr
From: Leif Lindholm @ 2014-02-03 18:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140203165718.GO14112@mudshark.cambridge.arm.com>

On Mon, Feb 03, 2014 at 04:57:18PM +0000, Will Deacon wrote:
> > mov[tw]: why?
> > Then we end up battling different available immediate fields in A32/T32
> > instruction sets and v5/v6/v7 architecture versions.
> 
> I was making the assumption that UEFI was going to be v7 only... is this not
> true?

There is no such requirement in the specification.
It even mentions requirements for ARMv4 in one place :)

But I also don't understand why ldr= should be avoided.
This is not performance sensitive (called once on system boot), and
it's already executing with the caches off, so even if it ends up
being a literal load it does not pollute.

/
    Leif

^ permalink raw reply

* [PATCH] arm: document "mach-virt" platform.
From: Christoffer Dall @ 2014-02-03 17:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52EF9D9F.5020600@codeaurora.org>

On Mon, Feb 03, 2014 at 08:46:07AM -0500, Christopher Covington wrote:
> Hi Christoffer,
> 
> On 02/02/2014 11:56 PM, Christoffer Dall wrote:
> > On Thu, Jan 30, 2014 at 11:54:46AM -0500, Christopher Covington wrote:
> >> I think it would be informative to provide pointers here to commonly used
> >> paravirtualized devices, especially VirtIO PCI/MMIO.
> > 
> > I disagree: that would only encourage limited testing or assumptions
> > about these specific devices when really this platform is just a
> > bare-bones platform driven by device tree which should make no
> > preference, whatsoever, about which devices are used with the platform.
> 
> I'd be all for clearly stating that no assumptions can be made. Perhaps you
> can explain though how providing less documentation will result in more
> testing? The assertion does not currently make sense to me.
> 
If the documentation states that this is commonly used with virtio/xen
pv drivers, then I'm afraid people will just assume that's the only
devices the platform is used with.

Any mention of specific devices or features steers the attention away
from the essential point of this documentation.

I don't see how adding this text helps.  Such documentation should go
elsewhere, in QEMU, or a Xen/KVM web page or something like that.

Anyway, I'm not religious about this point.

-Christoffer

^ permalink raw reply

* [PATCH v2 3/5] spi: sunxi: Add Allwinner A31 SPI controller driver
From: Kevin Hilman @ 2014-02-03 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140131081147.GC2950@lukather>

Maxime Ripard <maxime.ripard@free-electrons.com> writes:

> Hi Kevin,
>
> On Thu, Jan 30, 2014 at 03:52:16PM -0800, Kevin Hilman wrote:
>> On Wed, Jan 29, 2014 at 5:32 AM, Maxime Ripard
>> <maxime.ripard@free-electrons.com> wrote:
>> > On Wed, Jan 29, 2014 at 12:25:20PM +0000, Mark Brown wrote:
>> >> On Wed, Jan 29, 2014 at 12:10:48PM +0100, Maxime Ripard wrote:
>> >>
>> >> > +config SPI_SUN6I
>> >> > +   tristate "Allwinner A31 SPI controller"
>> >> > +   depends on ARCH_SUNXI || COMPILE_TEST
>> >> > +   select PM_RUNTIME
>> >> > +   help
>> >> > +     This enables using the SPI controller on the Allwinner A31 SoCs.
>> >> > +
>> >>
>> >> A select of PM_RUNTIME is both surprising and odd - why is that there?
>> >> The usual idiom is that the device starts out powered up (flagged using
>> >> pm_runtime_set_active()) and then runtime PM then suspends it when it's
>> >> compiled in.  That way if for some reason people want to avoid runtime
>> >> PM they can still use the device.
>> >
>> > Since pm_runtime_set_active and all the pm_runtime* callbacks in
>> > general are defined to pretty much empty functions, how the
>> > suspend/resume callbacks are called then? Obviously, we need them to
>> > be run, hence why I added the select here, but now I'm seeing a
>> > construct like what's following acceptable then?
>> 
>> Even with your 'select', The runtime PM callbacks will never be called
>> in the current driver.  pm_runtime_enable() doesn't do any runtime PM
>> transitions.  It just allows transitions to happen when they're
>> triggered by _get()/_put()/etc.
>
> Actually, pm_runtime_get_sync is called by the SPI framework whenever
> the device needs to be used. And pm_runtime_put whenever it's not used
> anymore, so the callbacks are actually called.

Ah, right.  I forgot that the SPI framework is using runtime PM now.

>> 
>> > pm_runtime_enable(&pdev->dev);
>> > if (!pm_runtime_enabled(&pdev->dev))
>> >    sun6i_spi_runtime_resume(&pdev->dev);
>> 
>> Similarily here, it's not the pm_runtime_enable that will fail when
>> runtime PM is disabled (or not built-in), it's a pm_runtime_get_sync()
>> that will fail.
>
> In the case where pm_runtime is disabled, pm_runtime_enabled will only
> return false, and hence the resume callback will be called. get_sync
> will fail too when the framework will call it, but since the device is
> already initialized, it's fine I guess.
>
>> What you want is something like this in ->probe()
>> 
>>    sun6i_spi_runtime_resume();
>>    /* now, device is always activated whether or not runtime PM is enabled */
>>    pm_runtime_enable();
>>    pm_runtime_set_active();  /* tells runtime PM core device is
>> already active */
>>    pm_runtime_get_sync();
>> 
>> This 'get' will increase the usecount, but not actually call the
>> callbacks because we told the RPM core that the device was already
>> activated with _set_active().
>> 
>> And then, in ->remove(), you'll want
>> 
>>    pm_runtime_put();
>>    pm_runtime_disable();
>> 
>> And if runtime PM is not enabled in the kernel, then the device will
>> be left on (which is kinda what you want if you didn't build runtime
>> PM into the kernel.)
>
> Yes, but that also mean that the device is actually on after the
> probe, even if it's never going to be used. From what I got reading
> the pm_runtime code, the suspend callback is called only whenever you
> call _put, so the device will be suspended only after it's been used
> the first time, right?
>
> Wouldn't it be better if it was suspended by default, and just waken
> up whenever the framework needs it?

Yes, but that's the job of runtime PM.  Without runtime PM, you have to
live with leaving the device powered up all the time.

Kevin

^ permalink raw reply

* [PATCH 2/5] cpu: add generic support for CPU feature based module autoloading
From: Ard Biesheuvel @ 2014-02-03 17:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391014246-9715-3-git-send-email-ard.biesheuvel@linaro.org>

Hello Greg,

Would you care to comment on this patch?

It adds some Kconfig clutter, but this is removed again in the next patch
(http://marc.info/?l=linux-arm-kernel&m=139101443708663&w=2),
which has already been acked by hpa here:
http://marc.info/?l=linux-arm-kernel&m=139101589509168&w=2

Example enabling it for arm64:
http://marc.info/?l=linux-arm-kernel&m=139101486308822&w=2

Example using it (optional AES instructions on arm64):
http://marc.info/?l=linux-arm-kernel&m=139101446008665&w=2

Best regards,
Ard.



On 29 January 2014 17:50, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> This patch adds support for advertising optional CPU features over udev using
> the modalias, and for declaring compatibility with/dependency upon such a
> feature in a module.
>
> This feature can be enabled by setting CONFIG_GENERIC_CPU_AUTOPROBE for the
> architecture, and supplying a file <asm/cpufeature.h> which defines how the
> numbers used in the modalias string map to actual CPU features.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  drivers/base/Kconfig              |  8 ++++++
>  drivers/base/cpu.c                | 39 +++++++++++++++++++++----
>  include/linux/cpufeature.h        | 60 +++++++++++++++++++++++++++++++++++++++
>  include/linux/mod_devicetable.h   |  9 ++++++
>  scripts/mod/devicetable-offsets.c |  3 ++
>  scripts/mod/file2alias.c          | 10 +++++++
>  6 files changed, 123 insertions(+), 6 deletions(-)
>  create mode 100644 include/linux/cpufeature.h
>
> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index ec36e7772e57..3f0d3732df7f 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -185,6 +185,14 @@ config GENERIC_CPU_DEVICES
>         bool
>         default n
>
> +config HAVE_CPU_AUTOPROBE
> +       def_bool ARCH_HAS_CPU_AUTOPROBE
> +
> +config GENERIC_CPU_AUTOPROBE
> +       bool
> +       depends on !ARCH_HAS_CPU_AUTOPROBE
> +       select HAVE_CPU_AUTOPROBE
> +
>  config SOC_BUS
>         bool
>
> diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
> index 270649012e64..8a38bf8c792f 100644
> --- a/drivers/base/cpu.c
> +++ b/drivers/base/cpu.c
> @@ -15,6 +15,7 @@
>  #include <linux/percpu.h>
>  #include <linux/acpi.h>
>  #include <linux/of.h>
> +#include <linux/cpufeature.h>
>
>  #include "base.h"
>
> @@ -286,12 +287,38 @@ static void cpu_device_release(struct device *dev)
>          */
>  }
>
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
> +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
> +static ssize_t print_cpu_modalias(struct device *dev,
> +                                 struct device_attribute *attr,
> +                                 char *buf)
> +{
> +       ssize_t n;
> +       u32 i;
> +
> +       n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
> +                   CPU_FEATURE_TYPEVAL);
> +
> +       for (i = 0; i < MAX_CPU_FEATURES; i++)
> +               if (cpu_have_feature(i)) {
> +                       if (PAGE_SIZE < n + sizeof(",XXXX\n")) {
> +                               WARN(1, "CPU features overflow page\n");
> +                               break;
> +                       }
> +                       n += sprintf(&buf[n], ",%04X", i);
> +               }
> +       buf[n++] = '\n';
> +       return n;
> +}
> +#else
> +#define print_cpu_modalias     arch_print_cpu_modalias
> +#endif
> +
>  static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
>  {
>         char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
>         if (buf) {
> -               arch_print_cpu_modalias(NULL, NULL, buf);
> +               print_cpu_modalias(NULL, NULL, buf);
>                 add_uevent_var(env, "MODALIAS=%s", buf);
>                 kfree(buf);
>         }
> @@ -319,7 +346,7 @@ int register_cpu(struct cpu *cpu, int num)
>         cpu->dev.offline_disabled = !cpu->hotpluggable;
>         cpu->dev.offline = !cpu_online(num);
>         cpu->dev.of_node = of_get_cpu_node(num, NULL);
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
>         cpu->dev.bus->uevent = cpu_uevent;
>  #endif
>         cpu->dev.groups = common_cpu_attr_groups;
> @@ -343,8 +370,8 @@ struct device *get_cpu_device(unsigned cpu)
>  }
>  EXPORT_SYMBOL_GPL(get_cpu_device);
>
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> -static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
> +static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
>  #endif
>
>  static struct attribute *cpu_root_attrs[] = {
> @@ -357,7 +384,7 @@ static struct attribute *cpu_root_attrs[] = {
>         &cpu_attrs[2].attr.attr,
>         &dev_attr_kernel_max.attr,
>         &dev_attr_offline.attr,
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
>         &dev_attr_modalias.attr,
>  #endif
>         NULL
> diff --git a/include/linux/cpufeature.h b/include/linux/cpufeature.h
> new file mode 100644
> index 000000000000..c4d4eb8ac9fe
> --- /dev/null
> +++ b/include/linux/cpufeature.h
> @@ -0,0 +1,60 @@
> +/*
> + * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __LINUX_CPUFEATURE_H
> +#define __LINUX_CPUFEATURE_H
> +
> +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
> +
> +#include <linux/mod_devicetable.h>
> +#include <asm/cpufeature.h>
> +
> +/*
> + * Macros imported from <asm/cpufeature.h>:
> + * - cpu_feature(x)            ordinal value of feature called 'x'
> + * - cpu_have_feature(u32 n)   whether feature #n is available
> + * - MAX_CPU_FEATURES          upper bound for feature ordinal values
> + * Optional:
> + * - CPU_FEATURE_TYPEFMT       format string fragment for printing the cpu type
> + * - CPU_FEATURE_TYPEVAL       set of values matching the format string above
> + */
> +
> +#ifndef CPU_FEATURE_TYPEFMT
> +#define CPU_FEATURE_TYPEFMT    "%s"
> +#endif
> +
> +#ifndef CPU_FEATURE_TYPEVAL
> +#define CPU_FEATURE_TYPEVAL    ELF_PLATFORM
> +#endif
> +
> +/*
> + * Use module_cpu_feature_match(feature, module_init_function) to
> + * declare that
> + * a) the module shall be probed upon discovery of CPU feature 'feature'
> + *    (typically at boot time using udev)
> + * b) the module must not be loaded if CPU feature 'feature' is not present
> + *    (not even by manual insmod).
> + *
> + * For a list of legal values for 'feature', please consult the file
> + * 'asm/cpufeature.h' of your favorite architecture.
> + */
> +#define module_cpu_feature_match(x, __init)                    \
> +static struct cpu_feature const cpu_feature_match_ ## x[] =    \
> +       { { .feature = cpu_feature(x) }, { } };                 \
> +MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x);             \
> +                                                               \
> +static int cpu_feature_match_ ## x ## _init(void)              \
> +{                                                              \
> +       if (!cpu_have_feature(cpu_feature(x)))                  \
> +               return -ENODEV;                                 \
> +       return __init();                                        \
> +}                                                              \
> +module_init(cpu_feature_match_ ## x ## _init)
> +
> +#endif
> +#endif
> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> index 45e921401b06..f2ac87c613a5 100644
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -564,6 +564,15 @@ struct x86_cpu_id {
>  #define X86_MODEL_ANY  0
>  #define X86_FEATURE_ANY 0      /* Same as FPU, you can't test for that */
>
> +/*
> + * Generic table type for matching CPU features.
> + * @feature:   the bit number of the feature (0 - 65535)
> + */
> +
> +struct cpu_feature {
> +       __u16   feature;
> +};
> +
>  #define IPACK_ANY_FORMAT 0xff
>  #define IPACK_ANY_ID (~0)
>  struct ipack_device_id {
> diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
> index bb5d115ca671..f282516acc7b 100644
> --- a/scripts/mod/devicetable-offsets.c
> +++ b/scripts/mod/devicetable-offsets.c
> @@ -174,6 +174,9 @@ int main(void)
>         DEVID_FIELD(x86_cpu_id, model);
>         DEVID_FIELD(x86_cpu_id, vendor);
>
> +       DEVID(cpu_feature);
> +       DEVID_FIELD(cpu_feature, feature);
> +
>         DEVID(mei_cl_device_id);
>         DEVID_FIELD(mei_cl_device_id, name);
>
> diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
> index 23708636b05c..8a69005228d8 100644
> --- a/scripts/mod/file2alias.c
> +++ b/scripts/mod/file2alias.c
> @@ -1135,6 +1135,16 @@ static int do_x86cpu_entry(const char *filename, void *symval,
>  }
>  ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
>
> +/* LOOKS like cpu:type:*:feature:*FEAT* */
> +static int do_cpu_entry(const char *filename, void *symval, char *alias)
> +{
> +       DEF_FIELD(symval, cpu_feature, feature);
> +
> +       sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
> +       return 1;
> +}
> +ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry);
> +
>  /* Looks like: mei:S */
>  static int do_mei_entry(const char *filename, void *symval,
>                         char *alias)
> --
> 1.8.3.2
>

^ permalink raw reply

* [PATCH] at91: pmc: Fixed irq's name allocation for programmable clocks
From: boris brezillon @ 2014-02-03 17:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391445961-20755-1-git-send-email-jjhiblot@traphandler.com>

Hello JJ,

On 03/02/2014 17:46, Jean-Jacques Hiblot wrote:
> The name provided to request_irq() must be valid until the irq is
> released.
> This patch allocates and formats the string with kasprintf().

Thanks for reporting this bug.

>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
> ---
>   drivers/clk/at91/clk-programmable.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
> index 8e242c7..0f8bf0f 100644
> --- a/drivers/clk/at91/clk-programmable.c
> +++ b/drivers/clk/at91/clk-programmable.c
> @@ -19,6 +19,7 @@
>   #include <linux/sched.h>
>   #include <linux/interrupt.h>
>   #include <linux/irq.h>
> +#include <linux/string.h>
>   
>   #include "pmc.h"
>   
> @@ -247,7 +248,7 @@ at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq,
>   	struct clk_programmable *prog;
>   	struct clk *clk = NULL;
>   	struct clk_init_data init;
> -	char irq_name[11];
> +	char *irq_name;
>   
>   	if (id > PROG_ID_MAX)
>   		return ERR_PTR(-EINVAL);
> @@ -269,7 +270,7 @@ at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq,
>   	prog->irq = irq;
>   	init_waitqueue_head(&prog->wait);
>   	irq_set_status_flags(prog->irq, IRQ_NOAUTOEN);
> -	snprintf(irq_name, sizeof(irq_name), "clk-prog%d", id);
> +	irq_name = kasprintf(GFP_KERNEL, "clk-prog%d", id);

Could you either use a static table with the prog clk names or store the 
name in
the clk_programmable struct ?
This way we could avoid the additional dynamic allocation.

static prog_clk_names = {
   "clk-prog0",
[...]
   "clk-prog7",
};

[...]
     ret = request_irq(prog->irq, clk_programmable_irq_handler, 
IRQF_TRIGGER_HIGH, prog_clk_names[id], prog);


or

struct clk_programmable {
[...]
     char irq_name[11];
[...]
};

[...]

snprintf(prog->irq_name, sizeof(prog->irq_name), "clk-prog%d", id);
ret = request_irq(prog->irq, clk_programmable_irq_handler, 
IRQF_TRIGGER_HIGH, prog->irq_name, prog);

Best Regards,

Boris
>   	ret = request_irq(prog->irq, clk_programmable_irq_handler,
>   			  IRQF_TRIGGER_HIGH, irq_name, prog);
>   	if (ret)

^ permalink raw reply

* [PATCH v4 2/5] arm: add new asm macro update_sctlr
From: Will Deacon @ 2014-02-03 16:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140203164636.GJ11329@bivouac.eciton.net>

On Mon, Feb 03, 2014 at 04:46:36PM +0000, Leif Lindholm wrote:
> On Mon, Feb 03, 2014 at 04:00:51PM +0000, Will Deacon wrote:
> > > > > With the two call sites in uefi_phys.S as:
> > > > > 
> > > > > 	ldr	r5, =(CR_M)
> > > > > 	update_sctlr	r12, , r5
> > > > > and
> > > > > 	ldr	r4, =(CR_I | CR_C | CR_M)
> > > > > 	update_sctlr	r12, r4
> > > > 
> > > > These ldr= could be movs, right?
> > > 
> > > The first one could.
> > > The second one could be movw on armv7+.
> > > 
> > > > If so, I definitely prefer this to putting an ldr = into the macro itself
> > > > (option 2).
> > > 
> > > And your preference between 1) and 2) is?
> > 
> > (1), using bic and mov[tw] where possible.
> 
> (1): ok, thanks.
> 
> bic: sure, that was an oversight.
> 
> mov[tw]: why?
> Then we end up battling different available immediate fields in A32/T32
> instruction sets and v5/v6/v7 architecture versions.

I was making the assumption that UEFI was going to be v7 only... is this not
true?

Will

^ permalink raw reply

* a LLC sched domain bug for panda board?
From: Alex Shi @ 2014-02-03 16:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKfTPtDJ267W9UMRj-pgyha0yf1L-VWBMKgi+QdVEA4zFJYXLw@mail.gmail.com>

On 02/04/2014 12:28 AM, Vincent Guittot wrote:
> On 3 February 2014 17:27, Vincent Guittot <vincent.guittot@linaro.org> wrote:
>> Have you checked that CONFIG_SCHED_LC is set ?
> 
> sorry it's CONFIG_SCHED_MC

Thanks for reminder! no it wasn't set. Does it means
arch/arm/configs/omap2plus_defconfig need add this config?

> 
>>
>>
>> On 3 February 2014 17:17, Alex Shi <alex.shi@linaro.org> wrote:
>>> I just run the 3.14-rc1 kernel on panda board. The only domain for it is
>>> 'CPU' domain, but this domain has no SD_SHARE_PKG_RESOURCES setting, it
>>> has no sd_llc.
>>>
>>> Guess the right domain for this board should be MC. So is it a bug?
>>>
>>> ..
>>> /proc/sys/kernel/sched_domain/cpu0/domain0/name:CPU
>>> ..
>>> /proc/sys/kernel/sched_domain/cpu1/domain0/name:CPU
>>>
>>> --
>>> Thanks
>>>     Alex
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>>> the body of a message to majordomo at vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>> Please read the FAQ at  http://www.tux.org/lkml/


-- 
Thanks
    Alex

^ permalink raw reply

* [PATCH v4 2/5] arm: add new asm macro update_sctlr
From: Leif Lindholm @ 2014-02-03 16:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140203160051.GG14112@mudshark.cambridge.arm.com>

On Mon, Feb 03, 2014 at 04:00:51PM +0000, Will Deacon wrote:
> > > > With the two call sites in uefi_phys.S as:
> > > > 
> > > > 	ldr	r5, =(CR_M)
> > > > 	update_sctlr	r12, , r5
> > > > and
> > > > 	ldr	r4, =(CR_I | CR_C | CR_M)
> > > > 	update_sctlr	r12, r4
> > > 
> > > These ldr= could be movs, right?
> > 
> > The first one could.
> > The second one could be movw on armv7+.
> > 
> > > If so, I definitely prefer this to putting an ldr = into the macro itself
> > > (option 2).
> > 
> > And your preference between 1) and 2) is?
> 
> (1), using bic and mov[tw] where possible.

(1): ok, thanks.

bic: sure, that was an oversight.

mov[tw]: why?
Then we end up battling different available immediate fields in A32/T32
instruction sets and v5/v6/v7 architecture versions.

/
    Leif

^ 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