Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Rob Herring @ 2014-02-12 23:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1882539.R1gpoLLYks@wuerfel>

On Wed, Feb 12, 2014 at 1:12 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 12 February 2014 13:45:21 Jason Cooper wrote:
>> On Wed, Feb 12, 2014 at 07:17:41PM +0100, Arnd Bergmann wrote:
>> > On Wednesday 12 February 2014 12:45:54 Jason Cooper wrote:
>> > > I brought this up at last weeks devicetree irc meeting.  My goal is to
>> > > provide early randomness for kaslr on ARM.  Currently, my idea is modify
>> > > the init script to save an additional random seed from /dev/urandom to
>> > > /boot/random-seed.
>> > >
>> > > The bootloader would then load this file into ram, and pass the
>> > > address/size to the kernel either via dt, or commandline.  kaslr (run in
>> > > the decompressor) would consume some of this randomness, and then
>> > > random.c would consume the rest in a non-crediting initialization.
>> >
>> > I like the idea, but wouldn't it be easier to pass actual random data
>> > using DT, rather than the address/size?
>>
>> I thought about that at first, but that requires either that the
>> bootloader be upgraded to insert the data, or that userspace is
>> modifying the dtb at least twice per boot.
>>
>> I chose address/size to facilitate modifying existing/fielded devices.
>> The user could modify the dtb once, and modify the bootloader
>> environment to load X amount to Y address.  As a fallback, it could be
>> expressed on the commandline for non-DT bootloaders.
>
> Ah, so you are interested in boot loaders that can be scripted to do
> what you had in mind but cannot be scripted to add or modify a DT
> property. I hadn't considered that, but you are probably right that
> this is at least 90% of the systems you'd find in the wild today.
>
> Thinking this a bit further, I wonder if (at least upstream) u-boot
> has a way to modify DT properties in a scripted way that would allow
> the direct property. It sounds like a generally useful feature not
> just for randomness, so if that doesn't already work, maybe someone
> can implement it. In the simplest case, you'd only need to find the
> address of an existing property in the dtb and load a file to
> that location.

You would be referring to the u-boot fdt command which can read and
set properties. Of course, like all u-boot commands, that may or may
not be enabled by a vendor's u-boot. :(

Rob

^ permalink raw reply

* [PATCH] ARM: shmobile: set proper DMA masks for Ether devices
From: Simon Horman @ 2014-02-12 23:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52FB5BD0.10707@cogentembedded.com>

On Wed, Feb 12, 2014 at 03:32:32PM +0400, Sergei Shtylyov wrote:
> Hello.
> 
> On 12-02-2014 5:35, Simon Horman wrote:
> 
> >>Ether MAC is a DMA-capable device and so should have 'dev.dma_mask' and
> >>'dev.coherent_dma_mask' fields set properly, to reflect 32-bit DMA addressing
> >>ability.  Currently, the code works without DMA masks but in the future, when
> >>support for NETIF_F_HIGHDMA & NETIF_F_SG would be added to the 'sh_eth' driver,
> >>the DMA masks should start to matter...
> 
> >>Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> 
> >Hi Sergei,
> 
> >please split this series up so there is a separate patch for each board.
> 
>    Hm, I, contrariwise, gathered all board patches in the single
> patch. Could you elaborate on why you deem it necessary to split it?

In my experience it helps to have the patches split out for two reasons:
1. If there is a problem on one board its patch can be reverted without
   having to bother with making a partial revert in order to leave the
   other boards alone.
2. It makes backporting easier in the case where there is interest in
   one board but not another.

Moreover, the boards are separate entities and in general I would
like their patches to be separate. The same goes for SoCs.

I realise this is more fine-grained than what other maintainers prefer
but it is an approach that seems to work well for us.

^ permalink raw reply

* [PATCH 2/2] PCI: mvebu - Call request_resources on the apertures
From: Arnd Bergmann @ 2014-02-12 23:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392245828-23244-2-git-send-email-jgunthorpe@obsidianresearch.com>

On Wednesday 12 February 2014 15:57:08 Jason Gunthorpe wrote:
> It is typical for host drivers to request a resource for the
> aperture, once this is done the PCI core will properly populate
> resources for all BARs in the system.
> 
> With this patch cat /proc/iomem will now show:
> 
> e0000000-efffffff : PCI MEM 0000
>   e0000000-e00fffff : PCI Bus 0000:01
>     e0000000-e001ffff : 0000:01:00.0
> 
> Tested on Kirkwood
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> ---
>  drivers/pci/host/pci-mvebu.c | 24 +++++++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
> 
> Arnd: Please confirm your SOB line, thanks.
> 

Yes, that's good. Thanks for taking care of this.

	Arnd

^ permalink raw reply

* [PATCH 1/2] ARM: tegra: enable I2C Mux driver for PCA9546 in defconfig
From: Bryan Wu @ 2014-02-12 23:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52FBF739.1060605@wwwdotorg.org>

On Wed, Feb 12, 2014 at 2:35 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 02/12/2014 02:55 PM, Bryan Wu wrote:
>> On Wed, Feb 12, 2014 at 12:17 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 02/12/2014 01:09 PM, Bryan Wu wrote:
>>>> On Wed, Feb 12, 2014 at 11:08 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>> On 02/07/2014 04:54 PM, Bryan Wu wrote:
>>>>>> PCA9546 is used in Cardhu Tegra30 board to connect to 3 cameras.
>>>>>> Enabling this driver for Tegra V4L2 soc camera driver and camera
>>>>>> sensor drivers.
> ...
>>>>> Note that your patches were sent with an email "From" address that
>>>>> didn't match your signed-off-by tag, yet "git send-email" didn't insert
>>>>> a "From" header in the email body. Can you please check your git user ID
>>>>> and/or email settings. Consequently, I had to adjust the git author
>>>>> field in git to match your s-o-b line.
> ...
>>> Why not just put the correct values in ~/.gitconfig?
>>>
>>> Perhaps this is because you switch between NVIDIA and non-NVIDIA email
>>> addresses and/or mail servers, so you can't make ~/.gitconfig static and
>>> universally correct? If you have a recent enough git, what I do is:
> ...
>> Awesome, I will firstly update my .gitconfig. Actually I basically
>> just have one outbound server which is gmail server. Although I put
>> From: @nvidia.com, I still use gmail server to send out patch emails.
>> Still don't wanna touch our internal email server.
>
> You shouldn't send email with a from address @nvidia.com from a server
> other than NVIDIA's servers. If you do, plenty of people will drop the
> email as SPAM, since NVIDIA publishes SPF[1] records (and perhaps other
> email configuration) for nvidia.com. Since there are good reasons not to
> use NVIDIA's email servers, that means: tell git the actual email
> address you're sending from (for the email settings; you should set the
> author/commit ID to your @nvidia.com address still).
>
> [1] http://www.openspf.org/
>
> $ dig -t spf nvidia.com
> ...
> nvidia.com.             180     IN      SPF     \
>         "v=spf1 mx/24 mx:nvidia.com/24 -all"
>

Sure, I think I just missed to set the author as @nvidia.com but SOB
is @nvidia.com in this patchset. And I still should use --from "Bryan
Wu <cooloney@gmail.com>" for sending out email from gmail server.
Right?

Thanks,
-Bryan

^ permalink raw reply

* [PATCH 1/2] bus: mvebu-mbus: Fix incorrect size for PCI aperture resources
From: Arnd Bergmann @ 2014-02-12 23:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392245828-23244-1-git-send-email-jgunthorpe@obsidianresearch.com>

On Wednesday 12 February 2014 15:57:07 Jason Gunthorpe wrote:
> reg[0] is the DT base, reg[1] is the DT length in bytes,
> struct resource.end is the inclusive end address, so a -1 is
> required.
> 
> Tested on kirkwood.
> 
> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>

Acked-by: Arnd Bergmann <arnd@arndb.de>

^ permalink raw reply

* [PATCH] input: sirfsoc-onkey - report onkey untouch event by detecting pin status
From: Dmitry Torokhov @ 2014-02-12 23:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026859-4977-1-git-send-email-21cnbao@gmail.com>

Hi Barry,

On Mon, Feb 10, 2014 at 06:07:39PM +0800, Barry Song wrote:
>  
>  static int sirfsoc_pwrc_remove(struct platform_device *pdev)
>  {
> +	struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(&pdev->dev);
> +
>  	device_init_wakeup(&pdev->dev, 0);
>  
> +	cancel_delayed_work_sync(&pwrcdrv->work);
> +

This is racy: interrupt is freed later and can schedule work again.

Thanks.

-- 
Dmitry

^ permalink raw reply

* [PATCH 2/2] PCI: mvebu - Call request_resources on the apertures
From: Jason Gunthorpe @ 2014-02-12 22:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392245828-23244-1-git-send-email-jgunthorpe@obsidianresearch.com>

It is typical for host drivers to request a resource for the
aperture, once this is done the PCI core will properly populate
resources for all BARs in the system.

With this patch cat /proc/iomem will now show:

e0000000-efffffff : PCI MEM 0000
  e0000000-e00fffff : PCI Bus 0000:01
    e0000000-e001ffff : 0000:01:00.0

Tested on Kirkwood

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
 drivers/pci/host/pci-mvebu.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

Arnd: Please confirm your SOB line, thanks.

diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index ef8691a..360a024 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -109,7 +109,9 @@ struct mvebu_pcie {
 	struct mvebu_pcie_port *ports;
 	struct msi_chip *msi;
 	struct resource io;
+	char io_name[30];
 	struct resource realio;
+	char mem_name[30];
 	struct resource mem;
 	struct resource busn;
 	int nports;
@@ -681,10 +683,30 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
 {
 	struct mvebu_pcie *pcie = sys_to_pcie(sys);
 	int i;
+	int domain = 0;
 
-	if (resource_size(&pcie->realio) != 0)
+#ifdef CONFIG_PCI_DOMAINS
+	domain = sys->domain;
+#endif
+
+	snprintf(pcie->mem_name, sizeof(pcie->mem_name), "PCI MEM %04x",
+		 domain);
+	pcie->mem.name = pcie->mem_name;
+
+	snprintf(pcie->io_name, sizeof(pcie->io_name), "PCI I/O %04x", domain);
+	pcie->realio.name = pcie->io_name;
+
+	if (request_resource(&iomem_resource, &pcie->mem))
+		return 0;
+
+	if (resource_size(&pcie->realio) != 0) {
+		if (request_resource(&ioport_resource, &pcie->realio)) {
+			release_resource(&pcie->mem);
+			return 0;
+		}
 		pci_add_resource_offset(&sys->resources, &pcie->realio,
 					sys->io_offset);
+	}
 	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
 	pci_add_resource(&sys->resources, &pcie->busn);
 
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 1/2] bus: mvebu-mbus: Fix incorrect size for PCI aperture resources
From: Jason Gunthorpe @ 2014-02-12 22:57 UTC (permalink / raw)
  To: linux-arm-kernel

reg[0] is the DT base, reg[1] is the DT length in bytes,
struct resource.end is the inclusive end address, so a -1 is
required.

Tested on kirkwood.

Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
 drivers/bus/mvebu-mbus.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 2394e97..7fd54e9 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -876,14 +876,14 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
 	ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg));
 	if (!ret) {
 		mem->start = reg[0];
-		mem->end = mem->start + reg[1];
+		mem->end = mem->start + reg[1] - 1;
 		mem->flags = IORESOURCE_MEM;
 	}
 
 	ret = of_property_read_u32_array(np, "pcie-io-aperture", reg, ARRAY_SIZE(reg));
 	if (!ret) {
 		io->start = reg[0];
-		io->end = io->start + reg[1];
+		io->end = io->start + reg[1] - 1;
 		io->flags = IORESOURCE_IO;
 	}
 }
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH v2] ARM: mm: report both sections from PMD
From: Kees Cook @ 2014-02-12 22:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 2-level page table systems, the PMD has 2 section entries. Report
these, otherwise ARM_PTDUMP will miss reporting permission changes on
odd section boundaries.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
v2:
 - reorganize, suggested by Catalin Marinas.
---
 arch/arm/include/asm/pgtable-3level.h |    4 ----
 arch/arm/include/asm/pgtable.h        |    4 ++++
 arch/arm/mm/dump.c                    |    8 +++++++-
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 03243f7eeddf..fb3de59ee811 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -138,10 +138,6 @@
 #define pud_none(pud)		(!pud_val(pud))
 #define pud_bad(pud)		(!(pud_val(pud) & 2))
 #define pud_present(pud)	(pud_val(pud))
-#define pmd_table(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
-						 PMD_TYPE_TABLE)
-#define pmd_sect(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
-						 PMD_TYPE_SECT)
 #define pmd_large(pmd)		pmd_sect(pmd)
 
 #define pud_clear(pudp)			\
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 7d59b524f2af..934aa5b60c7c 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -183,6 +183,10 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 #define pmd_none(pmd)		(!pmd_val(pmd))
 #define pmd_present(pmd)	(pmd_val(pmd))
+#define pmd_table(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
+						 PMD_TYPE_TABLE)
+#define pmd_sect(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
+						 PMD_TYPE_SECT)
 
 static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 {
diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c
index 2b342177f5de..32635b474832 100644
--- a/arch/arm/mm/dump.c
+++ b/arch/arm/mm/dump.c
@@ -260,8 +260,14 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
 
 	for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
 		addr = start + i * PMD_SIZE;
-		if (pmd_none(*pmd) || pmd_large(*pmd) || !pmd_present(*pmd))
+		if (pmd_none(*pmd) || pmd_large(*pmd) || !pmd_present(*pmd)) {
 			note_page(st, addr, 3, pmd_val(*pmd));
+			if (SECTION_SIZE < PMD_SIZE &&
+			    pmd_sect(*pmd) && pmd_sect(pmd[1])) {
+				note_page(st, addr + SECTION_SIZE, 3,
+					  pmd_val(pmd[1]));
+			}
+		}
 		else
 			walk_pte(st, pmd, addr);
 	}
-- 
1.7.9.5


-- 
Kees Cook
Chrome OS Security

^ permalink raw reply related

* [PATCH v2] ARM: mm: fix reporting of read-only PMD bits
From: Kees Cook @ 2014-02-12 22:43 UTC (permalink / raw)
  To: linux-arm-kernel

On non-LPAE, read-only PMD bits are defined with the combination
"PMD_SECT_APX | PMD_SECT_AP_WRITE". Adjusted the bit masks to correctly
detect this.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
v2:
 - reorder bits, suggested by Olof Johansson.
---
 arch/arm/mm/dump.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c
index 2b3a56414271..2b342177f5de 100644
--- a/arch/arm/mm/dump.c
+++ b/arch/arm/mm/dump.c
@@ -123,19 +123,19 @@ static const struct prot_bits section_bits[] = {
 #ifndef CONFIG_ARM_LPAE
 	/* These are approximate */
 	{
-		.mask	= PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
-		.val	= 0,
+		.mask	= PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
+		.val	= PMD_SECT_APX | PMD_SECT_AP_WRITE,
 		.set	= "    ro",
 	}, {
-		.mask	= PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
+		.mask	= PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
 		.val	= PMD_SECT_AP_WRITE,
 		.set	= "    RW",
 	}, {
-		.mask	= PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
+		.mask	= PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
 		.val	= PMD_SECT_AP_READ,
 		.set	= "USR ro",
 	}, {
-		.mask	= PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
+		.mask	= PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
 		.val	= PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
 		.set	= "USR RW",
 #else
-- 
1.7.9.5


-- 
Kees Cook
Chrome OS Security

^ permalink raw reply related

* [PATCH 1/2] ARM: tegra: enable I2C Mux driver for PCA9546 in defconfig
From: Stephen Warren @ 2014-02-12 22:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK5ve-+2AGO0UCf4UOMLoqGmQLp7QN08OJbZxUc-oYZzjPdFcQ@mail.gmail.com>

On 02/12/2014 02:55 PM, Bryan Wu wrote:
> On Wed, Feb 12, 2014 at 12:17 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 02/12/2014 01:09 PM, Bryan Wu wrote:
>>> On Wed, Feb 12, 2014 at 11:08 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>> On 02/07/2014 04:54 PM, Bryan Wu wrote:
>>>>> PCA9546 is used in Cardhu Tegra30 board to connect to 3 cameras.
>>>>> Enabling this driver for Tegra V4L2 soc camera driver and camera
>>>>> sensor drivers.
...
>>>> Note that your patches were sent with an email "From" address that
>>>> didn't match your signed-off-by tag, yet "git send-email" didn't insert
>>>> a "From" header in the email body. Can you please check your git user ID
>>>> and/or email settings. Consequently, I had to adjust the git author
>>>> field in git to match your s-o-b line.
...
>> Why not just put the correct values in ~/.gitconfig?
>>
>> Perhaps this is because you switch between NVIDIA and non-NVIDIA email
>> addresses and/or mail servers, so you can't make ~/.gitconfig static and
>> universally correct? If you have a recent enough git, what I do is:
...
> Awesome, I will firstly update my .gitconfig. Actually I basically
> just have one outbound server which is gmail server. Although I put
> From: @nvidia.com, I still use gmail server to send out patch emails.
> Still don't wanna touch our internal email server.

You shouldn't send email with a from address @nvidia.com from a server
other than NVIDIA's servers. If you do, plenty of people will drop the
email as SPAM, since NVIDIA publishes SPF[1] records (and perhaps other
email configuration) for nvidia.com. Since there are good reasons not to
use NVIDIA's email servers, that means: tell git the actual email
address you're sending from (for the email settings; you should set the
author/commit ID to your @nvidia.com address still).

[1] http://www.openspf.org/

$ dig -t spf nvidia.com
...
nvidia.com.		180	IN	SPF	\
	"v=spf1 mx/24 mx:nvidia.com/24 -all"

^ permalink raw reply

* [PATCH v2 2/3] ARM: bios32: use pci_enable_resource to enable PCI resources
From: Jason Gunthorpe @ 2014-02-12 22:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392236171-10512-3-git-send-email-will.deacon@arm.com>

On Wed, Feb 12, 2014 at 08:16:10PM +0000, Will Deacon wrote:
> This patch moves bios32 over to using the generic code for enabling PCI
> resources. Since the core code takes care of bridge resources too, we
> can also drop the explicit IO and MEMORY enabling for them in the arch
> code.

Tested-By: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> (on Kirkwood)

PCI: bus1: Fast back to back transfers disabled
pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
pci 0000:00:01.0: BAR 8: assigned [mem 0xe0000000-0xe00fffff]
pci 0000:01:00.0: BAR 0: assigned [mem 0xe0000000-0xe001ffff]
pci 0000:00:01.0: PCI bridge to [bus 01]
pci 0000:00:01.0:   bridge window [mem 0xe0000000-0xe00fffff]
pci 0000:00:01.0: enabling device (0140 -> 0142)

Jason

^ permalink raw reply

* [PATCH 2/3] PCI: ARM: add support for virtual PCI host controller
From: Jason Gunthorpe @ 2014-02-12 22:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140212221526.60fd7f8b@skate>

On Wed, Feb 12, 2014 at 10:15:26PM +0100, Thomas Petazzoni wrote:

> > +#ifdef CONFIG_PCI_DOMAINS
> > +       domain = sys->domain;
> > +#endif
> > +
> > +       snprintf(pcie->mem_name, sizeof(pcie->mem_name), "PCI MEM %04x", domain);
> > +       pcie->mem.name = pcie->mem_name;
> > +
> > +       snprintf(pcie->io_name, sizeof(pcie->io_name), "PCI I/O %04x", domain);
> > +       pcie->realio.name = pcie->io_name;
> 
> I honestly don't know what PCI domains are, but this change looks
> fairly harmless to me. I would however use kasprintf() instead maybe. I
> can submit patches for those two changes if you want.

For this purpose imagine that each PCI host controller driver gets a
unique domain, and every domain has a unique
aperture. domain:bus:device:function is the full unique path to a PCI
device.

So when you look at the resource hierarchy it makes some logical
sense:

e0000000-efffffff : PCI MEM 0000
  e0000000-e00fffff : PCI Bus 0000:01
    e0000000-e001ffff : 0000:01:00.0

PCI Domain -> domain + subordinate bus # -> domain:bus:device:function, bar #

The ARM PCI BIOS code used bus number, and Will's version ended up
using the DT path to the PCI node. Would be nice to see an
agreement/common code :)
 
> > Still missing release_region..
> 
> To match which request_region?

Ah, sorry, Arnd added one:

diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 13478ec..b55e9a6 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -680,9 +680,17 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
        struct mvebu_pcie *pcie = sys_to_pcie(sys);
        int i;

-       if (resource_size(&pcie->realio) != 0)
+       if (request_resource(&iomem_resource, &pcie->mem))
+               return 0;
+
+       if (resource_size(&pcie->realio) != 0) {
+               if (request_resource(&ioport_resource, &pcie->realio)) {
+                       release_resource(&pcie->mem);
+                       return 0;
+               }
                pci_add_resource_offset(&sys->resources, &pcie->realio,
                                        sys->io_offset);
+       }
        pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
        pci_add_resource(&sys->resources, &pcie->busn);


Which is why I didn't use kasprintf, that would complicate freeing
further.

Ideally we'd be able to use a devm_request_region someday.

Jason

^ permalink raw reply related

* [PATCH] dma: mv_xor: Silence a bunch of LPAE-related warnings
From: Olof Johansson @ 2014-02-12 21:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAPcyv4gWJA7Cv39pxtuOqj0RyivODNuae7Q0Ku27RQO8=M3HbQ@mail.gmail.com>

On Tue, Feb 04, 2014 at 10:58:31AM -0800, Dan Williams wrote:
> On Tue, Feb 4, 2014 at 10:57 AM, Dan Williams <dan.j.williams@intel.com> wrote:
> > On Tue, Feb 4, 2014 at 10:30 AM, Olof Johansson <olof@lixom.net> wrote:
> >> On Tue, Feb 4, 2014 at 9:00 AM, Jason Cooper <jason@lakedaemon.net> wrote:
> >>> On Tue, Feb 04, 2014 at 10:53:29AM +0530, Vinod Koul wrote:
> >>>> On Mon, Feb 03, 2014 at 05:13:23PM -0800, Olof Johansson wrote:
> >>>> > Enabling some of the mvebu platforms in the multiplatform config for ARM
> >>>> > enabled these drivers, which also triggered a bunch of warnings when LPAE
> >>>> > is enabled (thus making phys_addr_t 64-bit).
> >>>> >
> >>>> > Most changes are switching printk formats, but also a bit of changes to what
> >>>> > used to be array-based pointer arithmetic that could just be done with the
> >>>> > address types instead.
> >>>> >
> >>>> > The warnings were:
> >>>> >
> >>>> > drivers/dma/mv_xor.c: In function 'mv_xor_tx_submit':
> >>>> > drivers/dma/mv_xor.c:500:3: warning: format '%x' expects argument of type
> >>>> >     'unsigned int', but argument 4 has type 'dma_addr_t' [-Wformat]
> >>>> > drivers/dma/mv_xor.c: In function 'mv_xor_alloc_chan_resources':
> >>>> > drivers/dma/mv_xor.c:553:13: warning: cast to pointer from integer of
> >>>> >     different size [-Wint-to-pointer-cast]
> >>>> > drivers/dma/mv_xor.c:555:4: warning: cast from pointer to integer of
> >>>> >     different size [-Wpointer-to-int-cast]
> >>>> > drivers/dma/mv_xor.c: In function 'mv_xor_prep_dma_memcpy':
> >>>> > drivers/dma/mv_xor.c:584:2: warning: format '%x' expects argument of type
> >>>> >     'unsigned int', but argument 5 has type 'dma_addr_t' [-Wformat]
> >>>> > drivers/dma/mv_xor.c:584:2: warning: format '%x' expects argument of type
> >>>> >     'unsigned int', but argument 6 has type 'dma_addr_t' [-Wformat]
> >>>> > drivers/dma/mv_xor.c: In function 'mv_xor_prep_dma_xor':
> >>>> > drivers/dma/mv_xor.c:628:2: warning: format '%u' expects argument of type
> >>>> >     'unsigned int', but argument 7 has type 'dma_addr_t' [-Wformat]
> >>>> >
> >>>> > Signed-off-by: Olof Johansson <olof@lixom.net>
> >>>> Acked-by: Vinod Koul <vinod.koul@intel.com>
> >>>
> >>> Olof, would you like me to queue it up?  Or do you want to take it
> >>> directly?
> >>>
> >>> Acked-by: Jason Cooper <jason@lakedaemon.net>
> >>
> >> I'm confused. I sent the patch to the drivers/dma maintainers and they
> >> just acked it without asking me to pick it up myself.
> >>
> >> Vinod, did you ack it for me to pick it up, or for some other reason?
> >> If you don't want to take it through your tree I'll be happy to take
> >> it through arm-soc, just looking to clarify.
> >>
> >> (Jason, I can apply it directly)
> >
> > Vinod will correct me if I am wrong, but I take his acks to mean "yup,
> > take it through your tree".  For this specific problem I thought we
> > had a comprehensive fix pending from Joe Perches to add a new %pX
> > format specifier for dma addresses?
> 
> Never mind... that's what you are using.  Sorry for the noise.

Yep. Applied now, btw.


-Olof

^ permalink raw reply

* [PATCH 1/2] ARM: tegra: enable I2C Mux driver for PCA9546 in defconfig
From: Bryan Wu @ 2014-02-12 21:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52FBD6C9.2010905@wwwdotorg.org>

On Wed, Feb 12, 2014 at 12:17 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 02/12/2014 01:09 PM, Bryan Wu wrote:
>> On Wed, Feb 12, 2014 at 11:08 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 02/07/2014 04:54 PM, Bryan Wu wrote:
>>>> PCA9546 is used in Cardhu Tegra30 board to connect to 3 cameras.
>>>> Enabling this driver for Tegra V4L2 soc camera driver and camera
>>>> sensor drivers.
>>>
>>> I've squashed patch 1/2 into Tegra's for-3.15/defconfig branch, and
>>> applied patch 2/2 to Tegra's for-3.15/dt branch.
>>>
>>> Note that your patches were sent with an email "From" address that
>>> didn't match your signed-off-by tag, yet "git send-email" didn't insert
>>> a "From" header in the email body. Can you please check your git user ID
>>> and/or email settings. Consequently, I had to adjust the git author
>>> field in git to match your s-o-b line.
>>
>> My bad. I need to update my git send-email script to use --from "Bryan
>> Wu <pengw@nvidia.com>" instead of --from "Bryan Wu
>> <cooloney@gmail.com>"
>>
>> Need I resubmit this patchset?
>
> No need to resent; I fixed them up.
>
> Why not just put the correct values in ~/.gitconfig?
>
> Perhaps this is because you switch between NVIDIA and non-NVIDIA email
> addresses and/or mail servers, so you can't make ~/.gitconfig static and
> universally correct? If you have a recent enough git, what I do is:
>
> $ cat ~/.gitconfig
> [include]
>         path = .gitconfig-user
>         path = .gitconfig-email-server
> ...
>
> $ cat ~/.gitconfig-user-nvidia
> [user]
>         name = Stephen Warren
>         email = swarren at nvidia.com
>
> $ cat ~/.gitconfig-user-wwwdotorg
> [user]
>         name = Stephen Warren
>         email = swarren at wwwdotorg.org
>
> ~/.gitconfig-user is a symlink to one of ~/.gitconfig-user-*, and I have
> a script that deletes the link and points it at a new location:
>
> $ cat `which git-switch-user`
> #!/bin/bash
>
> cd $HOME
> mainfile=.gitconfig-user
> newlink=${mainfile}-$1
> if [ ! -f ${newlink} ]; then
>     echo ERROR: ${newlink} not found
>     exit 1
> fi
>
> rm -f ${mainfile}
> ln -s ${newlink} ${mainfile}
>
> ... and the same thing for email servers.
>
> Then, I can run e.g.:
>
> git-switch-email-server nvidia; \
> git send-email --to internal at nvidia.com *.patch; \
> git-switch-email-server severn-port-forwarded

Awesome, I will firstly update my .gitconfig. Actually I basically
just have one outbound server which is gmail server. Although I put
From: @nvidia.com, I still use gmail server to send out patch emails.
Still don't wanna touch our internal email server.

Thanks a lot and it's really helpful.
-Bryan

^ permalink raw reply

* [PATCH v2 3/3] PCI: ARM: add support for generic PCI host controller
From: Kumar Gala @ 2014-02-12 21:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392236171-10512-4-git-send-email-will.deacon@arm.com>


On Feb 12, 2014, at 2:16 PM, Will Deacon <will.deacon@arm.com> wrote:

> This patch adds support for a generic PCI host controller, such as a
> firmware-initialised device with static windows or an emulation by
> something such as kvmtool.
> 
> The controller itself has no configuration registers and has its address
> spaces described entirely by the device-tree (using the bindings from
> ePAPR). Both CAM and ECAM are supported for Config Space accesses.
> 
> Corresponding documentation is added for the DT binding.
> 
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
> .../devicetree/bindings/pci/arm-generic-pci.txt    |  51 ++++
> drivers/pci/host/Kconfig                           |   7 +
> drivers/pci/host/Makefile                          |   1 +
> drivers/pci/host/pci-arm-generic.c                 | 318 +++++++++++++++++++++
> 4 files changed, 377 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/pci/arm-generic-pci.txt
> create mode 100644 drivers/pci/host/pci-arm-generic.c
> 
> diff --git a/Documentation/devicetree/bindings/pci/arm-generic-pci.txt b/Documentation/devicetree/bindings/pci/arm-generic-pci.txt
> new file mode 100644
> index 000000000000..cc7a35ecfa2d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/arm-generic-pci.txt
> @@ -0,0 +1,51 @@
> +* ARM generic PCI host controller
> +
> +Firmware-initialised PCI host controllers and PCI emulations, such as the
> +virtio-pci implementations found in kvmtool and other para-virtualised
> +systems, do not require driver support for complexities such as regulator and
> +clock management. In fact, the controller may not even require the
> +configuration of a control interface by the operating system, instead
> +presenting a set of fixed windows describing a subset of IO, Memory and
> +Configuration Spaces.
> +
> +Such a controller can be described purely in terms of the standardized device
> +tree bindings communicated in pci.txt:
> +
> +- compatible     : Must be "arm,pci-cam-generic" or "arm,pci-ecam-generic"
> +                   depending on the layout of configuration space (CAM vs
> +                   ECAM respectively)

What?s arm specific here?  I don?t have a great suggestion, but seems odd for this to be vendor prefixed with "arm".

> +
> +- ranges         : As described in IEEE Std 1275-1994, but must provide
> +                   at least a definition of one or both of IO and Memory
> +                   Space.
> +
> +- #address-cells : Must be 3
> +
> +- #size-cells    : Must be 2
> +
> +- reg            : The Configuration Space base address, as accessed by the
> +                   parent bus.

Isn?t the size fixed here for cam or ecam?

> +
> +Configuration Space is assumed to be memory-mapped (as opposed to being
> +accessed via an ioport) and laid out with a direct correspondence to the
> +geography of a PCI bus address by concatenating the various components to form
> +an offset.
> +
> +For CAM, this 24-bit offset is:
> +
> +        cfg_offset(bus, device, function, register) =
> +                   bus << 16 | device << 11 | function << 8 | register
> +
> +Whilst ECAM extends this by 4 bits to accomodate 4k of function space:
> +
> +        cfg_offset(bus, device, function, register) =
> +                   bus << 20 | device << 15 | function << 12 | register
> +
> +Interrupt mapping is exactly as described in `Open Firmware Recommended
> +Practice: Interrupt Mapping' and requires the following properties:
> +
> +- #interrupt-cells   : Must be 1
> +
> +- interrupt-map      : <see aforementioned specification>
> +
> +- interrupt-map-mask : <see aforementioned specification>

Examples are always nice :)

- k

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

^ permalink raw reply

* [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Kees Cook @ 2014-02-12 21:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140212174554.GM27395@titan.lakedaemon.net>

On Wed, Feb 12, 2014 at 9:45 AM, Jason Cooper <jason@lakedaemon.net> wrote:
> I brought this up at last weeks devicetree irc meeting.  My goal is to
> provide early randomness for kaslr on ARM.  Currently, my idea is modify
> the init script to save an additional random seed from /dev/urandom to
> /boot/random-seed.

I'm all for a good entropy source for early boot. :)

I need to figure out what's needed for relocation support first
though, before we can really tackle kernel base-address randomization
on ARM. I haven't had a chance to look around too closely yet, but it
seems like only x86 and ppc do this currently? Has anyone looked in
detail and what would be needed on ARM for CONFIG_RELOCATABLE
behavior?

-Kees

-- 
Kees Cook
Chrome OS Security

^ permalink raw reply

* [PATCH 2/3] PCI: ARM: add support for virtual PCI host controller
From: Thomas Petazzoni @ 2014-02-12 21:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140212194313.GA17248@obsidianresearch.com>

Dear Jason Gunthorpe,

On Wed, 12 Feb 2014 12:43:13 -0700, Jason Gunthorpe wrote:

> diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
> index 2394e97..7fd54e9 100644
> --- a/drivers/bus/mvebu-mbus.c
> +++ b/drivers/bus/mvebu-mbus.c
> @@ -876,14 +876,14 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
>         ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg));
>         if (!ret) {
>                 mem->start = reg[0];
> -               mem->end = mem->start + reg[1];
> +               mem->end = mem->start + reg[1] - 1;
>                 mem->flags = IORESOURCE_MEM;
>         }
>  
>         ret = of_property_read_u32_array(np, "pcie-io-aperture", reg, ARRAY_SIZE(reg));
>         if (!ret) {
>                 io->start = reg[0];
> -               io->end = io->start + reg[1];
> +               io->end = io->start + reg[1] - 1;
>                 io->flags = IORESOURCE_IO;
>         }
>  }

This certainly looks good.

> Fixes the wrong length (e0000000-f0000000 should be e0000000-efffffff)
> 
> And this fixes the <BAD>:
> 
> diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
> index ef8691a..fbb89cb 100644
> --- a/drivers/pci/host/pci-mvebu.c
> +++ b/drivers/pci/host/pci-mvebu.c
> @@ -109,7 +109,9 @@ struct mvebu_pcie {
>         struct mvebu_pcie_port *ports;
>         struct msi_chip *msi;
>         struct resource io;
> +       char io_name[30];
>         struct resource realio;
> +       char mem_name[30];
>         struct resource mem;
>         struct resource busn;
>         int nports;
> @@ -681,10 +683,29 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
>  {
>         struct mvebu_pcie *pcie = sys_to_pcie(sys);
>         int i;
> +       int domain = 0;
>  
> +#ifdef CONFIG_PCI_DOMAINS
> +       domain = sys->domain;
> +#endif
> +
> +       snprintf(pcie->mem_name, sizeof(pcie->mem_name), "PCI MEM %04x", domain);
> +       pcie->mem.name = pcie->mem_name;
> +
> +       snprintf(pcie->io_name, sizeof(pcie->io_name), "PCI I/O %04x", domain);
> +       pcie->realio.name = pcie->io_name;

I honestly don't know what PCI domains are, but this change looks
fairly harmless to me. I would however use kasprintf() instead maybe. I
can submit patches for those two changes if you want.

> Still missing release_region..

To match which request_region?

> > Since the mvebu_pcie_setup() function seems very generic at this,
> > we should probably try to factor out that code into a common
> > helper, at least for arm64, but ideally shared with arm32
> > as well.
> 
> Yah, especially since people are not getting it completely right..
> 
> But some of the trouble here is a lack of a generic pci host driver
> structure, eg I have to pull the domain number out of the ARM32
> specific structure ..

There is indeed a good deal of duplication of PCI related code in the
different architectures. The PCI_DOMAINS Kconfig option is for example
replicated in multiple architectures.

Best regards,

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH] PCI: MVEBU: Use Device ID and revision from underlying endpoint
From: Bjorn Helgaas @ 2014-02-12 21:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391597749-29807-1-git-send-email-andrew@lunn.ch>

On Wed, Feb 05, 2014 at 11:55:49AM +0100, Andrew Lunn wrote:
> Marvell SoCs place the SoC number into the PCIe endpoint device ID.
> The SoC stepping is placed into the PCIe revision. The old plat-orion
> PCIe driver allowed this information to be seen in user space with a
> simple lspci command.
> 
> The new driver places a virtual PCI-PCI bridge on top of these
> endpoints. It has its own hard coded PCI device ID. Thus it is no
> longer possible to see what the SoC is using lspci.
> 
> When initializing the PCI-PCI bridge, set its device ID and revision
> from the underlying endpoint, thus restoring this functionality.
> Debian would like to use this in order to aid installing the correct
> DTB file.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Applied to pci/host-mvebu with acks from Thomas and Jason.  Since it fixes
a regression, I cherry-picked it into for-linus for v3.14.  Thanks!

Bjorn

> ---
>  drivers/pci/host/pci-mvebu.c | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
> index 13478ecd4113..0e79665afd44 100644
> --- a/drivers/pci/host/pci-mvebu.c
> +++ b/drivers/pci/host/pci-mvebu.c
> @@ -60,14 +60,6 @@
>  #define PCIE_DEBUG_CTRL         0x1a60
>  #define  PCIE_DEBUG_SOFT_RESET		BIT(20)
>  
> -/*
> - * This product ID is registered by Marvell, and used when the Marvell
> - * SoC is not the root complex, but an endpoint on the PCIe bus. It is
> - * therefore safe to re-use this PCI ID for our emulated PCI-to-PCI
> - * bridge.
> - */
> -#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 0x7846
> -
>  /* PCI configuration space of a PCI-to-PCI bridge */
>  struct mvebu_sw_pci_bridge {
>  	u16 vendor;
> @@ -388,7 +380,8 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port)
>  
>  	bridge->class = PCI_CLASS_BRIDGE_PCI;
>  	bridge->vendor = PCI_VENDOR_ID_MARVELL;
> -	bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
> +	bridge->device = mvebu_readl(port, PCIE_DEV_ID_OFF) >> 16;
> +	bridge->revision = mvebu_readl(port, PCIE_DEV_REV_OFF) & 0xff;
>  	bridge->header_type = PCI_HEADER_TYPE_BRIDGE;
>  	bridge->cache_line_size = 0x10;
>  
> -- 
> 1.8.5.2
> 

^ permalink raw reply

* [PATCH v4 3/8] at91: dt: Add at91sam9261 dt SoC support
From: Alexandre Belloni @ 2014-02-12 21:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392199607-27452-4-git-send-email-jjhiblot@traphandler.com>

Sorry, one more comment on that patch:

On 12/02/2014 at 11:06:42 +0100, Jean-Jacques Hiblot wrote :
> +			pinctrl at fffff400 {
> +				#address-cells = <1>;
> +				#size-cells = <1>;
> +				compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
> +				ranges = <0xfffff400 0xfffff400 0xa00>;
> +
I believe you got the range wrong, shouldn't it be:
				ranges = <0xfffff400 0xfffff400 0x600>;


-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH v2 3/3] PCI: ARM: add support for generic PCI host controller
From: Arnd Bergmann @ 2014-02-12 20:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392236171-10512-4-git-send-email-will.deacon@arm.com>

On Wednesday 12 February 2014 20:16:11 Will Deacon wrote:
> +- ranges         : As described in IEEE Std 1275-1994, but must provide
> +                   at least a definition of one or both of IO and Memory
> +                   Space.

I'd say *must* provide at least non-prefetchable memory. *may* provide
prefetchable memory and/or I/O space.

> +- #address-cells : Must be 3
> +
> +- #size-cells    : Must be 2
> +
> +- reg            : The Configuration Space base address, as accessed by the
> +                   parent bus.
> +
> +Configuration Space is assumed to be memory-mapped (as opposed to being
> +accessed via an ioport) and laid out with a direct correspondence to the
> +geography of a PCI bus address by concatenating the various components to form
> +an offset.
> +
> +For CAM, this 24-bit offset is:
> +
> +        cfg_offset(bus, device, function, register) =
> +                   bus << 16 | device << 11 | function << 8 | register
> +
> +Whilst ECAM extends this by 4 bits to accomodate 4k of function space:
> +
> +        cfg_offset(bus, device, function, register) =
> +                   bus << 20 | device << 15 | function << 12 | register
> +
> +Interrupt mapping is exactly as described in `Open Firmware Recommended
> +Practice: Interrupt Mapping' and requires the following properties:
> +
> +- #interrupt-cells   : Must be 1
> +
> +- interrupt-map      : <see aforementioned specification>
> +
> +- interrupt-map-mask : <see aforementioned specification>

We probably want to add an optional 'bus-range' property (the default being
<0 255> if absent), so we don't have to map all the config space.

> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index 47d46c6d8468..491d74c36f6a 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -33,4 +33,11 @@ config PCI_RCAR_GEN2
>  	  There are 3 internal PCI controllers available with a single
>  	  built-in EHCI/OHCI host controller present on each one.
>  
> +config PCI_ARM_GENERIC
> +	bool "ARM generic PCI host controller"
> +	depends on ARM && OF
> +	help
> +	  Say Y here if you want to support a simple generic PCI host
> +	  controller, such as the one emulated by kvmtool.
> +
>  endmenu

Looks good for now. In the long run, I'd hope to get rid of the 'ARM'
part here and make it work on any architecture, but that requires
significant work that we should not depend on here.


> +struct gen_pci_cfg_window {
> +	u64					cpu_phys;
> +	void __iomem				*base;
> +	u8					bus;
> +	spinlock_t				lock;
> +	const struct gen_pci_cfg_accessors	*accessors;
> +};
> +
> +struct gen_pci_resource {
> +	struct list_head			list;
> +	struct resource				cpu_res;
> +	resource_size_t				offset;
> +};

Your gen_pci_resource is actually identical to struct pci_host_bridge_window,
which I guess is coincidence, but it would be nice to actually use
the standard structure to make it easier to integrate with common
infrastructure later.

> +
> +struct gen_pci {
> +	struct device				*dev;
> +	struct resource				*io_res;
> +	struct list_head			mem_res;
> +	struct gen_pci_cfg_window		cfg;
> +};

How about making this structure derived from pci_host_bridge?
That would already contain a lot of the members, and gets two things
right: 

* it's useful to have an embedded 'struct device' here, and use dev->parent
  to point to the device from DT
* for I/O, we actually want a pci_host_bridge_window, not just a resource,
  since we should keep track of the offset

> +static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
> +					      unsigned int devfn,
> +					      int where)
> +{
> +	struct pci_sys_data *sys = bus->sysdata;
> +	struct gen_pci *pci = sys->private_data;
> +	u32 busn = bus->number;
> +
> +	spin_lock(&pci->cfg.lock);
> +	if (pci->cfg.bus != busn) {
> +		resource_size_t offset;
> +
> +		devm_iounmap(pci->dev, pci->cfg.base);
> +		offset = pci->cfg.cpu_phys + (busn << 20);
> +		pci->cfg.base = devm_ioremap(pci->dev, offset, SZ_1M);
> +		pci->cfg.bus = busn;
> +	}
> +
> +	return pci->cfg.base + ((devfn << 12) | where);
> +}

Nice idea, but unfortunately broken: we need config space access from
atomic context, since there are drivers doing that.

> +static int gen_pci_probe(struct platform_device *pdev)
> +{
> +	struct hw_pci hw;
> +	struct of_pci_range range;
> +	struct of_pci_range_parser parser;
> +	struct gen_pci *pci;
> +	const __be32 *reg;
> +	const struct of_device_id *of_id;
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;

Could you try to move almost all of this function into gen_pci_setup()?
I suspect this will make it easier later to share this driver with other
architectures.

> +
> +	hw = (struct hw_pci) {
> +		.nr_controllers	= 1,
> +		.private_data	= (void **)&pci,
> +		.setup		= gen_pci_setup,
> +		.map_irq	= of_irq_parse_and_map_pci,
> +		.ops		= &gen_pci_ops,
> +	};
> +
> +	pci_common_init_dev(dev, &hw);
> +	return 0;
> +}

A missing part here seems to be a way to propagate errors from
the pci_common_init_dev or gen_pci_setup back to the caller.

This seems to be a result of the arm pcibios implementation not
being meant for loadable modules, but I suspect it can be fixed.
The nr_controllers>1 logic gets a bit in the way there, but it's
also a model that seems to be getting out of fashion:
kirkwood/dove/orion5x/mv78xx0 use it at the moment, but are
migrating over to the new pci-mvebu code that doesn't as they
get rid of the non-DT probing. pci-rcar-gen2.c uses it, but it
seems they already ran into problems with that and are changing
it. That pretty much leaves iop13xx as the only user, but at
that point we can probably move the loop into iop13xx specific
code.

	Arnd

^ permalink raw reply

* [PATCH v4 6/6] arm64: add early_ioremap support
From: Mark Salter @ 2014-02-12 20:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392238575-10000-1-git-send-email-msalter@redhat.com>

Add support for early IO or memory mappings which are needed
before the normal ioremap() is usable. This also adds fixmap
support for permanent fixed mappings such as that used by the
earlyprintk device register region.

Signed-off-by: Mark Salter <msalter@redhat.com>
---
 Documentation/arm64/memory.txt   |  4 +-
 arch/arm64/Kconfig               |  1 +
 arch/arm64/include/asm/Kbuild    |  1 +
 arch/arm64/include/asm/fixmap.h  | 67 +++++++++++++++++++++++++++++++
 arch/arm64/include/asm/io.h      |  1 +
 arch/arm64/include/asm/memory.h  |  2 +-
 arch/arm64/kernel/early_printk.c |  8 +++-
 arch/arm64/kernel/head.S         |  9 ++---
 arch/arm64/kernel/setup.c        |  2 +
 arch/arm64/mm/ioremap.c          | 85 ++++++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/mmu.c              | 41 -------------------
 11 files changed, 169 insertions(+), 52 deletions(-)
 create mode 100644 arch/arm64/include/asm/fixmap.h

diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt
index 5e054bf..953c81e 100644
--- a/Documentation/arm64/memory.txt
+++ b/Documentation/arm64/memory.txt
@@ -35,7 +35,7 @@ ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap
 
 ffffffbe00000000	ffffffbffbbfffff	  ~8GB		[guard, future vmmemap]
 
-ffffffbffbc00000	ffffffbffbdfffff	   2MB		earlyprintk device
+ffffffbffbc00000	ffffffbffbdfffff	   2MB		fixed mappings
 
 ffffffbffbe00000	ffffffbffbe0ffff	  64KB		PCI I/O space
 
@@ -60,7 +60,7 @@ fffffdfc00000000	fffffdfdffffffff	   8GB		vmemmap
 
 fffffdfe00000000	fffffdfffbbfffff	  ~8GB		[guard, future vmmemap]
 
-fffffdfffbc00000	fffffdfffbdfffff	   2MB		earlyprintk device
+fffffdfffbc00000	fffffdfffbdfffff	   2MB		fixed mappings
 
 fffffdfffbe00000	fffffdfffbe0ffff	  64KB		PCI I/O space
 
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..da4304a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -16,6 +16,7 @@ config ARM64
 	select DCACHE_WORD_ACCESS
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+	select GENERIC_EARLY_IOREMAP
 	select GENERIC_IOMAP
 	select GENERIC_IRQ_PROBE
 	select GENERIC_IRQ_SHOW
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 71c53ec..27e3c6b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -10,6 +10,7 @@ generic-y += delay.h
 generic-y += div64.h
 generic-y += dma.h
 generic-y += emergency-restart.h
+generic-y += early_ioremap.h
 generic-y += errno.h
 generic-y += ftrace.h
 generic-y += hw_irq.h
diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
new file mode 100644
index 0000000..9c1fb65
--- /dev/null
+++ b/arch/arm64/include/asm/fixmap.h
@@ -0,0 +1,67 @@
+/*
+ * fixmap.h: compile-time virtual memory allocation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998 Ingo Molnar
+ * Copyright (C) 2013 Mark Salter <msalter@redhat.com>
+ *
+ * Adapted from arch/x86_64 version.
+ *
+ */
+
+#ifndef _ASM_ARM64_FIXMAP_H
+#define _ASM_ARM64_FIXMAP_H
+
+#ifndef __ASSEMBLY__
+#include <linux/kernel.h>
+#include <asm/page.h>
+
+/*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+ * in the boot process.
+ *
+ * These 'compile-time allocated' memory buffers are
+ * page-sized. Use set_fixmap(idx,phys) to associate
+ * physical memory with fixmap indices.
+ *
+ */
+enum fixed_addresses {
+	FIX_EARLYCON,
+	__end_of_permanent_fixed_addresses,
+
+	/*
+	 * Temporary boot-time mappings, used by early_ioremap(),
+	 * before ioremap() is functional.
+	 */
+#ifdef CONFIG_ARM64_64K_PAGES
+#define NR_FIX_BTMAPS		4
+#else
+#define NR_FIX_BTMAPS		64
+#endif
+#define FIX_BTMAPS_SLOTS	7
+#define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
+
+	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
+	FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
+	__end_of_fixed_addresses
+};
+
+#define FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
+
+#define FIXMAP_PAGE_IO     __pgprot(PROT_DEVICE_nGnRE)
+
+extern void __early_set_fixmap(enum fixed_addresses idx,
+			       phys_addr_t phys, pgprot_t flags);
+
+#define __set_fixmap __early_set_fixmap
+
+#include <asm-generic/fixmap.h>
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_ARM64_FIXMAP_H */
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 4cc813e..8fb2152 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -27,6 +27,7 @@
 #include <asm/byteorder.h>
 #include <asm/barrier.h>
 #include <asm/pgtable.h>
+#include <asm/early_ioremap.h>
 
 #include <xen/xen.h>
 
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 9dc5dc3..e94f945 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -49,7 +49,7 @@
 #define PAGE_OFFSET		(UL(0xffffffffffffffff) << (VA_BITS - 1))
 #define MODULES_END		(PAGE_OFFSET)
 #define MODULES_VADDR		(MODULES_END - SZ_64M)
-#define EARLYCON_IOBASE		(MODULES_VADDR - SZ_4M)
+#define FIXADDR_TOP		(MODULES_VADDR - SZ_2M - PAGE_SIZE)
 #define TASK_SIZE_64		(UL(1) << VA_BITS)
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c
index fbb6e18..850d9a4 100644
--- a/arch/arm64/kernel/early_printk.c
+++ b/arch/arm64/kernel/early_printk.c
@@ -26,6 +26,8 @@
 #include <linux/amba/serial.h>
 #include <linux/serial_reg.h>
 
+#include <asm/fixmap.h>
+
 static void __iomem *early_base;
 static void (*printch)(char ch);
 
@@ -141,8 +143,10 @@ static int __init setup_early_printk(char *buf)
 	}
 	/* no options parsing yet */
 
-	if (paddr)
-		early_base = early_io_map(paddr, EARLYCON_IOBASE);
+	if (paddr) {
+		set_fixmap_io(FIX_EARLYCON, paddr);
+		early_base = (void __iomem *)fix_to_virt(FIX_EARLYCON);
+	}
 
 	printch = match->printch;
 	early_console = &early_console_dev;
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 0b281ff..c86bfdf 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -412,7 +412,7 @@ ENDPROC(__calc_phys_offset)
  *   - identity mapping to enable the MMU (low address, TTBR0)
  *   - first few MB of the kernel linear mapping to jump to once the MMU has
  *     been enabled, including the FDT blob (TTBR1)
- *   - UART mapping if CONFIG_EARLY_PRINTK is enabled (TTBR1)
+ *   - pgd entry for fixed mappings (TTBR1)
  */
 __create_page_tables:
 	pgtbl	x25, x26, x24			// idmap_pg_dir and swapper_pg_dir addresses
@@ -465,15 +465,12 @@ __create_page_tables:
 	sub	x6, x6, #1			// inclusive range
 	create_block_map x0, x7, x3, x5, x6
 1:
-#ifdef CONFIG_EARLY_PRINTK
 	/*
-	 * Create the pgd entry for the UART mapping. The full mapping is done
-	 * later based earlyprintk kernel parameter.
+	 * Create the pgd entry for the fixed mappings.
 	 */
-	ldr	x5, =EARLYCON_IOBASE		// UART virtual address
+	ldr	x5, =FIXADDR_TOP		// Fixed mapping virtual address
 	add	x0, x26, #2 * PAGE_SIZE		// section table address
 	create_pgd_entry x26, x0, x5, x6, x7
-#endif
 	ret
 ENDPROC(__create_page_tables)
 	.ltorg
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 1c66cfb..4d2ac74 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -42,6 +42,7 @@
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
+#include <asm/fixmap.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
 #include <asm/cputable.h>
@@ -328,6 +329,7 @@ void __init setup_arch(char **cmdline_p)
 	*cmdline_p = boot_command_line;
 
 	init_mem_pgprot();
+	early_ioremap_init();
 
 	parse_early_param();
 
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
index 2bb1d58..7ec3283 100644
--- a/arch/arm64/mm/ioremap.c
+++ b/arch/arm64/mm/ioremap.c
@@ -25,6 +25,10 @@
 #include <linux/vmalloc.h>
 #include <linux/io.h>
 
+#include <asm/fixmap.h>
+#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+
 static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
 				      pgprot_t prot, void *caller)
 {
@@ -98,3 +102,84 @@ void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
 				__builtin_return_address(0));
 }
 EXPORT_SYMBOL(ioremap_cache);
+
+#ifndef CONFIG_ARM64_64K_PAGES
+static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
+#endif
+
+static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+
+	pgd = pgd_offset_k(addr);
+	BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd));
+
+	pud = pud_offset(pgd, addr);
+	BUG_ON(pud_none(*pud) || pud_bad(*pud));
+
+	return pmd_offset(pud, addr);
+}
+
+static inline pte_t * __init early_ioremap_pte(unsigned long addr)
+{
+	pmd_t *pmd = early_ioremap_pmd(addr);
+
+	BUG_ON(pmd_none(*pmd) || pmd_bad(*pmd));
+
+	return pte_offset_kernel(pmd, addr);
+}
+
+void __init early_ioremap_init(void)
+{
+	pmd_t *pmd;
+
+	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+#ifndef CONFIG_ARM64_64K_PAGES
+	/* need to populate pmd for 4k pagesize only */
+	pmd_populate_kernel(&init_mm, pmd, bm_pte);
+#endif
+	/*
+	 * The boot-ioremap range spans multiple pmds, for which
+	 * we are not prepared:
+	 */
+	BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
+		     != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
+
+	if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
+		WARN_ON(1);
+		pr_warn("pmd %p != %p\n",
+			pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
+		pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
+			fix_to_virt(FIX_BTMAP_BEGIN));
+		pr_warn("fix_to_virt(FIX_BTMAP_END):   %08lx\n",
+			fix_to_virt(FIX_BTMAP_END));
+
+		pr_warn("FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
+		pr_warn("FIX_BTMAP_BEGIN:     %d\n",
+			FIX_BTMAP_BEGIN);
+	}
+
+	early_ioremap_setup();
+}
+
+void __init __early_set_fixmap(enum fixed_addresses idx,
+			       phys_addr_t phys, pgprot_t flags)
+{
+	unsigned long addr = __fix_to_virt(idx);
+	pte_t *pte;
+
+	if (idx >= __end_of_fixed_addresses) {
+		BUG();
+		return;
+	}
+
+	pte = early_ioremap_pte(addr);
+
+	if (pgprot_val(flags))
+		set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
+	else {
+		pte_clear(&init_mm, addr, pte);
+		flush_tlb_kernel_range(addr, addr+PAGE_SIZE);
+	}
+}
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index ba259a0..6b7e895 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -260,47 +260,6 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt,
 	} while (pgd++, addr = next, addr != end);
 }
 
-#ifdef CONFIG_EARLY_PRINTK
-/*
- * Create an early I/O mapping using the pgd/pmd entries already populated
- * in head.S as this function is called too early to allocated any memory. The
- * mapping size is 2MB with 4KB pages or 64KB or 64KB pages.
- */
-void __iomem * __init early_io_map(phys_addr_t phys, unsigned long virt)
-{
-	unsigned long size, mask;
-	bool page64k = IS_ENABLED(CONFIG_ARM64_64K_PAGES);
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-
-	/*
-	 * No early pte entries with !ARM64_64K_PAGES configuration, so using
-	 * sections (pmd).
-	 */
-	size = page64k ? PAGE_SIZE : SECTION_SIZE;
-	mask = ~(size - 1);
-
-	pgd = pgd_offset_k(virt);
-	pud = pud_offset(pgd, virt);
-	if (pud_none(*pud))
-		return NULL;
-	pmd = pmd_offset(pud, virt);
-
-	if (page64k) {
-		if (pmd_none(*pmd))
-			return NULL;
-		pte = pte_offset_kernel(pmd, virt);
-		set_pte(pte, __pte((phys & mask) | PROT_DEVICE_nGnRE));
-	} else {
-		set_pmd(pmd, __pmd((phys & mask) | PROT_SECT_DEVICE_nGnRE));
-	}
-
-	return (void __iomem *)((virt & mask) + (phys & ~mask));
-}
-#endif
-
 static void __init map_mem(void)
 {
 	struct memblock_region *reg;
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v4 5/6] arm64: initialize pgprot info earlier in boot
From: Mark Salter @ 2014-02-12 20:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392238575-10000-1-git-send-email-msalter@redhat.com>

Presently, paging_init() calls init_mem_pgprot() to initialize pgprot
values used by macros such as PAGE_KERNEL, PAGE_KERNEL_EXEC, etc. The
new fixmap and early_ioremap support also needs to use these macros
before paging_init() is called. This patch moves the init_mem_pgprot()
call out of paging_init() and into setup_arch() so that pgprot_default
gets initialized in time for fixmap and early_ioremap.

Signed-off-by: Mark Salter <msalter@redhat.com>
---
 arch/arm64/include/asm/mmu.h | 1 +
 arch/arm64/kernel/setup.c    | 2 ++
 arch/arm64/mm/mmu.c          | 3 +--
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 2494fc0..f600d40 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -27,5 +27,6 @@ typedef struct {
 extern void paging_init(void);
 extern void setup_mm_for_reboot(void);
 extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
+extern void init_mem_pgprot(void);
 
 #endif
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index c8e9eff..1c66cfb 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -327,6 +327,8 @@ void __init setup_arch(char **cmdline_p)
 
 	*cmdline_p = boot_command_line;
 
+	init_mem_pgprot();
+
 	parse_early_param();
 
 	arm64_memblock_init();
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index f8dc7e8..ba259a0 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -125,7 +125,7 @@ early_param("cachepolicy", early_cachepolicy);
 /*
  * Adjust the PMD section entries according to the CPU in use.
  */
-static void __init init_mem_pgprot(void)
+void __init init_mem_pgprot(void)
 {
 	pteval_t default_pgprot;
 	int i;
@@ -357,7 +357,6 @@ void __init paging_init(void)
 {
 	void *zero_page;
 
-	init_mem_pgprot();
 	map_mem();
 
 	/*
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v4 4/6] arm: add early_ioremap support
From: Mark Salter @ 2014-02-12 20:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392238575-10000-1-git-send-email-msalter@redhat.com>

This patch uses the generic early_ioremap code to implement
early_ioremap for ARM. The ARM-specific bits come mostly from
an earlier patch from Leif Lindholm <leif.lindholm@linaro.org>
here:

  https://lkml.org/lkml/2013/10/3/279

Signed-off-by: Mark Salter <msalter@redhat.com>
Tested-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---
 arch/arm/Kconfig              | 10 +++++
 arch/arm/include/asm/Kbuild   |  1 +
 arch/arm/include/asm/fixmap.h | 20 ++++++++++
 arch/arm/include/asm/io.h     |  1 +
 arch/arm/kernel/setup.c       |  2 +
 arch/arm/mm/Makefile          |  4 ++
 arch/arm/mm/early_ioremap.c   | 93 +++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mm/mmu.c             |  2 +
 8 files changed, 133 insertions(+)
 create mode 100644 arch/arm/mm/early_ioremap.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e254198..7a35ef6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1874,6 +1874,16 @@ config UACCESS_WITH_MEMCPY
 	  However, if the CPU data cache is using a write-allocate mode,
 	  this option is unlikely to provide any performance gain.
 
+config EARLY_IOREMAP
+	bool "Provide early_ioremap() support for kernel initialization"
+	select GENERIC_EARLY_IOREMAP
+	help
+	  Provide a mechanism for kernel initialisation code to temporarily
+	  map, in a highmem-agnostic way, memory pages in before ioremap()
+	  and friends are available (before paging_init() has run). It uses
+	  the same virtual memory range as kmap so all early mappings must
+	  be unmapped before paging_init() is called.
+
 config SECCOMP
 	bool
 	prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 3278afe..6fcfd7d 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -4,6 +4,7 @@ generic-y += auxvec.h
 generic-y += bitsperlong.h
 generic-y += cputime.h
 generic-y += current.h
+generic-y += early_ioremap.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index 68ea615..ff8fa3e 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -21,8 +21,28 @@ enum fixed_addresses {
 	FIX_KMAP_BEGIN,
 	FIX_KMAP_END = (FIXADDR_TOP - FIXADDR_START) >> PAGE_SHIFT,
 	__end_of_fixed_addresses
+/*
+ * 224 temporary boot-time mappings, used by early_ioremap(),
+ * before ioremap() is functional.
+ *
+ * (P)re-using the FIXADDR region, which is used for highmem
+ * later on, and statically aligned to 1MB.
+ */
+#define NR_FIX_BTMAPS		32
+#define FIX_BTMAPS_SLOTS	7
+#define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
+#define FIX_BTMAP_END		FIX_KMAP_BEGIN
+#define FIX_BTMAP_BEGIN		(FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1)
 };
 
+#define FIXMAP_PAGE_COMMON (L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN)
+
+#define FIXMAP_PAGE_NORMAL (FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK)
+#define FIXMAP_PAGE_IO	   (FIXMAP_PAGE_COMMON | L_PTE_MT_DEV_NONSHARED)
+
+extern void __early_set_fixmap(enum fixed_addresses idx,
+			       phys_addr_t phys, pgprot_t flags);
+
 #include <asm-generic/fixmap.h>
 
 #endif
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 8aa4cca..637e0cd 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -28,6 +28,7 @@
 #include <asm/byteorder.h>
 #include <asm/memory.h>
 #include <asm-generic/pci_iomap.h>
+#include <asm/early_ioremap.h>
 #include <xen/xen.h>
 
 /*
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b0df976..9c8b751 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -30,6 +30,7 @@
 #include <linux/bug.h>
 #include <linux/compiler.h>
 #include <linux/sort.h>
+#include <linux/io.h>
 
 #include <asm/unified.h>
 #include <asm/cp15.h>
@@ -880,6 +881,7 @@ void __init setup_arch(char **cmdline_p)
 	const struct machine_desc *mdesc;
 
 	setup_processor();
+	early_ioremap_init();
 	mdesc = setup_machine_fdt(__atags_pointer);
 	if (!mdesc)
 		mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 7f39ce2..501af98 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -12,6 +12,10 @@ ifneq ($(CONFIG_MMU),y)
 obj-y				+= nommu.o
 endif
 
+ifeq ($(CONFIG_MMU),y)
+obj-$(CONFIG_EARLY_IOREMAP)	+= early_ioremap.o
+endif
+
 obj-$(CONFIG_ARM_PTDUMP)	+= dump.o
 obj-$(CONFIG_MODULES)		+= proc-syms.o
 
diff --git a/arch/arm/mm/early_ioremap.c b/arch/arm/mm/early_ioremap.c
new file mode 100644
index 0000000..c3e2bf2
--- /dev/null
+++ b/arch/arm/mm/early_ioremap.c
@@ -0,0 +1,93 @@
+/*
+ * early_ioremap() support for ARM
+ *
+ * Based on existing support in arch/x86/mm/ioremap.c
+ *
+ * Restrictions: currently only functional before paging_init()
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/fixmap.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+#include <asm/mach/map.h>
+
+static pte_t bm_pte[PTRS_PER_PTE] __aligned(PTE_HWTABLE_SIZE) __initdata;
+
+static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+{
+	unsigned int index = pgd_index(addr);
+	pgd_t *pgd = cpu_get_pgd() + index;
+	pud_t *pud = pud_offset(pgd, addr);
+	pmd_t *pmd = pmd_offset(pud, addr);
+
+	return pmd;
+}
+
+static inline pte_t * __init early_ioremap_pte(unsigned long addr)
+{
+	return &bm_pte[pte_index(addr)];
+}
+
+void __init early_ioremap_init(void)
+{
+	pmd_t *pmd;
+
+	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+
+	pmd_populate_kernel(NULL, pmd, bm_pte);
+
+	/*
+	 * Make sure we don't span multiple pmds.
+	 */
+	BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
+		     != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
+
+	if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
+		WARN_ON(1);
+		pr_warn("pmd %p != %p\n",
+			pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
+		pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
+			fix_to_virt(FIX_BTMAP_BEGIN));
+		pr_warn("fix_to_virt(FIX_BTMAP_END):   %08lx\n",
+			fix_to_virt(FIX_BTMAP_END));
+		pr_warn("FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
+		pr_warn("FIX_BTMAP_BEGIN:     %d\n", FIX_BTMAP_BEGIN);
+	}
+
+	early_ioremap_setup();
+}
+
+void __init __early_set_fixmap(enum fixed_addresses idx,
+			       phys_addr_t phys, pgprot_t flags)
+{
+	unsigned long addr = __fix_to_virt(idx);
+	pte_t *pte;
+	u64 desc;
+
+	if (idx > FIX_KMAP_END) {
+		BUG();
+		return;
+	}
+	pte = early_ioremap_pte(addr);
+
+	if (pgprot_val(flags))
+		set_pte_at(NULL, 0xfff00000, pte,
+			   pfn_pte(phys >> PAGE_SHIFT, flags));
+	else
+		pte_clear(NULL, addr, pte);
+	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+	desc = *pte;
+}
+
+void __init
+early_ioremap_shutdown(void)
+{
+	pmd_t *pmd;
+	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+	pmd_clear(pmd);
+}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 4f08c13..5067294 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -35,6 +35,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/pci.h>
+#include <asm/early_ioremap.h>
 
 #include "mm.h"
 #include "tcm.h"
@@ -1489,6 +1490,7 @@ void __init paging_init(const struct machine_desc *mdesc)
 {
 	void *zero_page;
 
+	early_ioremap_reset();
 	build_mem_type_table();
 	prepare_page_table();
 	map_lowmem();
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v4 2/6] mm: create generic early_ioremap() support
From: Mark Salter @ 2014-02-12 20:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392238575-10000-1-git-send-email-msalter@redhat.com>

This patch creates a generic implementation of early_ioremap() support
based on the existing x86 implementation. early_ioremp() is useful for
early boot code which needs to temporarily map I/O or memory regions
before normal mapping functions such as ioremap() are available.

Some architectures have optional MMU. In the no-MMU case, the remap
functions simply return the passed in physical address and the unmap
functions do nothing.

Signed-off-by: Mark Salter <msalter@redhat.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---
 include/asm-generic/early_ioremap.h |  42 ++++++
 mm/Kconfig                          |   3 +
 mm/Makefile                         |   1 +
 mm/early_ioremap.c                  | 271 ++++++++++++++++++++++++++++++++++++
 4 files changed, 317 insertions(+)
 create mode 100644 include/asm-generic/early_ioremap.h
 create mode 100644 mm/early_ioremap.c

diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h
new file mode 100644
index 0000000..a5de55c
--- /dev/null
+++ b/include/asm-generic/early_ioremap.h
@@ -0,0 +1,42 @@
+#ifndef _ASM_EARLY_IOREMAP_H_
+#define _ASM_EARLY_IOREMAP_H_
+
+#include <linux/types.h>
+
+/*
+ * early_ioremap() and early_iounmap() are for temporary early boot-time
+ * mappings, before the real ioremap() is functional.
+ */
+extern void __iomem *early_ioremap(resource_size_t phys_addr,
+				   unsigned long size);
+extern void *early_memremap(resource_size_t phys_addr,
+			    unsigned long size);
+extern void early_iounmap(void __iomem *addr, unsigned long size);
+extern void early_memunmap(void *addr, unsigned long size);
+
+/*
+ * Weak function called by early_ioremap_reset(). It does nothing, but
+ * architectures may provide their own version to do any needed cleanups.
+ */
+extern void early_ioremap_shutdown(void);
+
+#if defined(CONFIG_GENERIC_EARLY_IOREMAP) && defined(CONFIG_MMU)
+/* Arch-specific initialization */
+extern void early_ioremap_init(void);
+
+/* Generic initialization called by architecture code */
+extern void early_ioremap_setup(void);
+
+/*
+ * Called as last step in paging_init() so library can act
+ * accordingly for subsequent map/unmap requests.
+ */
+extern void early_ioremap_reset(void);
+
+#else
+static inline void early_ioremap_init(void) { }
+static inline void early_ioremap_setup(void) { }
+static inline void early_ioremap_reset(void) { }
+#endif
+
+#endif /* _ASM_EARLY_IOREMAP_H_ */
diff --git a/mm/Kconfig b/mm/Kconfig
index 2d9f150..bf846a2 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -577,3 +577,6 @@ config PGTABLE_MAPPING
 
 	  You can check speed with zsmalloc benchmark[1].
 	  [1] https://github.com/spartacus06/zsmalloc
+
+config GENERIC_EARLY_IOREMAP
+	bool
diff --git a/mm/Makefile b/mm/Makefile
index 310c90a..9d9c587 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -61,3 +61,4 @@ obj-$(CONFIG_CLEANCACHE) += cleancache.o
 obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o
 obj-$(CONFIG_ZBUD)	+= zbud.o
 obj-$(CONFIG_ZSMALLOC)	+= zsmalloc.o
+obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
new file mode 100644
index 0000000..6591759
--- /dev/null
+++ b/mm/early_ioremap.c
@@ -0,0 +1,271 @@
+/*
+ * Provide common bits of early_ioremap() support for architectures needing
+ * temporary mappings during boot before ioremap() is available.
+ *
+ * This is mostly a direct copy of the x86 early_ioremap implementation.
+ *
+ * (C) Copyright 1995 1996, 2014 Linus Torvalds
+ *
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/fixmap.h>
+
+#ifdef CONFIG_MMU
+static int early_ioremap_debug __initdata;
+
+static int __init early_ioremap_debug_setup(char *str)
+{
+	early_ioremap_debug = 1;
+
+	return 0;
+}
+early_param("early_ioremap_debug", early_ioremap_debug_setup);
+
+static int after_paging_init __initdata;
+
+void __init __attribute__((weak)) early_ioremap_shutdown(void)
+{
+}
+
+void __init early_ioremap_reset(void)
+{
+	early_ioremap_shutdown();
+	after_paging_init = 1;
+}
+
+/*
+ * Generally, ioremap() is available after paging_init() has been called.
+ * Architectures wanting to allow early_ioremap after paging_init() can
+ * define __late_set_fixmap and __late_clear_fixmap to do the right thing.
+ */
+#ifndef __late_set_fixmap
+static inline void __init __late_set_fixmap(enum fixed_addresses idx,
+					    phys_addr_t phys, pgprot_t prot)
+{
+	BUG();
+}
+#endif
+
+#ifndef __late_clear_fixmap
+static inline void __init __late_clear_fixmap(enum fixed_addresses idx)
+{
+	BUG();
+}
+#endif
+
+static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
+static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
+static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
+
+void __init early_ioremap_setup(void)
+{
+	int i;
+
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		if (prev_map[i]) {
+			WARN_ON(1);
+			break;
+		}
+	}
+
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
+		slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);
+}
+
+static int __init check_early_ioremap_leak(void)
+{
+	int count = 0;
+	int i;
+
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
+		if (prev_map[i])
+			count++;
+
+	if (!count)
+		return 0;
+	WARN(1, KERN_WARNING
+	       "Debug warning: early ioremap leak of %d areas detected.\n",
+		count);
+	pr_warn("please boot with early_ioremap_debug and report the dmesg.\n");
+
+	return 1;
+}
+late_initcall(check_early_ioremap_leak);
+
+static void __init __iomem *
+__early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot)
+{
+	unsigned long offset;
+	resource_size_t last_addr;
+	unsigned int nrpages;
+	enum fixed_addresses idx;
+	int i, slot;
+
+	WARN_ON(system_state != SYSTEM_BOOTING);
+
+	slot = -1;
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		if (!prev_map[i]) {
+			slot = i;
+			break;
+		}
+	}
+
+	if (slot < 0) {
+		pr_info("%s(%08llx, %08lx) not found slot\n",
+			__func__, (u64)phys_addr, size);
+		WARN_ON(1);
+		return NULL;
+	}
+
+	if (early_ioremap_debug) {
+		pr_info("%s(%08llx, %08lx) [%d] => ",
+			__func__, (u64)phys_addr, size, slot);
+		dump_stack();
+	}
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	prev_size[slot] = size;
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+	/*
+	 * Mappings have to fit in the FIX_BTMAP area.
+	 */
+	nrpages = size >> PAGE_SHIFT;
+	if (nrpages > NR_FIX_BTMAPS) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	/*
+	 * Ok, go for it..
+	 */
+	idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
+	while (nrpages > 0) {
+		if (after_paging_init)
+			__late_set_fixmap(idx, phys_addr, prot);
+		else
+			__early_set_fixmap(idx, phys_addr, prot);
+		phys_addr += PAGE_SIZE;
+		--idx;
+		--nrpages;
+	}
+	if (early_ioremap_debug)
+		pr_cont("%08lx + %08lx\n", offset, slot_virt[slot]);
+
+	prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]);
+	return prev_map[slot];
+}
+
+void __init early_iounmap(void __iomem *addr, unsigned long size)
+{
+	unsigned long virt_addr;
+	unsigned long offset;
+	unsigned int nrpages;
+	enum fixed_addresses idx;
+	int i, slot;
+
+	slot = -1;
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		if (prev_map[i] == addr) {
+			slot = i;
+			break;
+		}
+	}
+
+	if (slot < 0) {
+		pr_info("early_iounmap(%p, %08lx) not found slot\n",
+			addr, size);
+		WARN_ON(1);
+		return;
+	}
+
+	if (prev_size[slot] != size) {
+		pr_info("early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
+			addr, size, slot, prev_size[slot]);
+		WARN_ON(1);
+		return;
+	}
+
+	if (early_ioremap_debug) {
+		pr_info("early_iounmap(%p, %08lx) [%d]\n", addr,
+			size, slot);
+		dump_stack();
+	}
+
+	virt_addr = (unsigned long)addr;
+	if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)) {
+		WARN_ON(1);
+		return;
+	}
+	offset = virt_addr & ~PAGE_MASK;
+	nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT;
+
+	idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
+	while (nrpages > 0) {
+		if (after_paging_init)
+			__late_clear_fixmap(idx);
+		else
+			__early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR);
+		--idx;
+		--nrpages;
+	}
+	prev_map[slot] = NULL;
+}
+
+/* Remap an IO device */
+void __init __iomem *
+early_ioremap(resource_size_t phys_addr, unsigned long size)
+{
+	return __early_ioremap(phys_addr, size, FIXMAP_PAGE_IO);
+}
+
+/* Remap memory */
+void __init *
+early_memremap(resource_size_t phys_addr, unsigned long size)
+{
+	return (__force void *)__early_ioremap(phys_addr, size,
+					       FIXMAP_PAGE_NORMAL);
+}
+#else /* CONFIG_MMU */
+
+void __init __iomem *
+early_ioremap(resource_size_t phys_addr, unsigned long size)
+{
+	return (__force void __iomem *)phys_addr;
+}
+
+/* Remap memory */
+void __init *
+early_memremap(resource_size_t phys_addr, unsigned long size)
+{
+	return (void *)phys_addr;
+}
+
+void __init early_iounmap(void __iomem *addr, unsigned long size)
+{
+}
+
+#endif /* CONFIG_MMU */
+
+
+void __init early_memunmap(void *addr, unsigned long size)
+{
+	early_iounmap((__force void __iomem *)addr, size);
+}
-- 
1.8.5.3

^ permalink raw reply related


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