linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ARM: cns3xxx: Don't allocate PCI addresses on stack
@ 2014-08-25  0:51 Mark Brown
  2014-08-25 10:34 ` Arnd Bergmann
  0 siblings, 1 reply; 4+ messages in thread
From: Mark Brown @ 2014-08-25  0:51 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Brown <broonie@linaro.org>

The cns3xxx PCIe code allocates a PCI bus structure on the stack, causing
warnings due to the excessibe size of the resulting stack frame:

arch/arm/mach-cns3xxx/pcie.c:311:1: warning: the frame size of 1072 bytes is larger than 1024 bytes [-Wframe-larger-than=]

Avoid this by dynamically allocating the structure, though I am not
convinced that we should be locally creating the struct pci_bus in the
first place.

Signed-off-by: Mark Brown <broonie@linaro.org>
---
 arch/arm/mach-cns3xxx/pcie.c | 49 ++++++++++++++++++++++++++------------------
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 413134c..67964f9 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -19,6 +19,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
+#include <linux/slab.h>
 #include <asm/mach/map.h>
 #include "cns3xxx.h"
 #include "core.h"
@@ -266,11 +267,7 @@ static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci)
 	struct pci_sys_data sd = {
 		.domain = port,
 	};
-	struct pci_bus bus = {
-		.number = 0,
-		.ops = &cns3xxx_pcie_ops,
-		.sysdata = &sd,
-	};
+	struct pci_bus *bus;
 	u16 mem_base  = cnspci->res_mem.start >> 16;
 	u16 mem_limit = cnspci->res_mem.end   >> 16;
 	u16 io_base   = cnspci->res_io.start  >> 16;
@@ -280,34 +277,46 @@ static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci)
 	u16 pos;
 	u16 dc;
 
-	pci_bus_write_config_byte(&bus, devfn, PCI_PRIMARY_BUS, 0);
-	pci_bus_write_config_byte(&bus, devfn, PCI_SECONDARY_BUS, 1);
-	pci_bus_write_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, 1);
+	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+	if (!bus)
+		return;
+
+	bus->number = 0;
+	bus->ops = &cns3xxx_pcie_ops;
+	bus->sysdata = &sd;
 
-	pci_bus_read_config_byte(&bus, devfn, PCI_PRIMARY_BUS, &tmp8);
-	pci_bus_read_config_byte(&bus, devfn, PCI_SECONDARY_BUS, &tmp8);
-	pci_bus_read_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, &tmp8);
+	pci_bus_write_config_byte(bus, devfn, PCI_PRIMARY_BUS, 0);
+	pci_bus_write_config_byte(bus, devfn, PCI_SECONDARY_BUS, 1);
+	pci_bus_write_config_byte(bus, devfn, PCI_SUBORDINATE_BUS, 1);
 
-	pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_BASE, mem_base);
-	pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_LIMIT, mem_limit);
-	pci_bus_write_config_word(&bus, devfn, PCI_IO_BASE_UPPER16, io_base);
-	pci_bus_write_config_word(&bus, devfn, PCI_IO_LIMIT_UPPER16, io_limit);
+	pci_bus_read_config_byte(bus, devfn, PCI_PRIMARY_BUS, &tmp8);
+	pci_bus_read_config_byte(bus, devfn, PCI_SECONDARY_BUS, &tmp8);
+	pci_bus_read_config_byte(bus, devfn, PCI_SUBORDINATE_BUS, &tmp8);
 
-	if (!cnspci->linked)
+	pci_bus_write_config_word(bus, devfn, PCI_MEMORY_BASE, mem_base);
+	pci_bus_write_config_word(bus, devfn, PCI_MEMORY_LIMIT, mem_limit);
+	pci_bus_write_config_word(bus, devfn, PCI_IO_BASE_UPPER16, io_base);
+	pci_bus_write_config_word(bus, devfn, PCI_IO_LIMIT_UPPER16, io_limit);
+
+	if (!cnspci->linked) {
+		kfree(bus);
 		return;
+	}
 
 	/* Set Device Max_Read_Request_Size to 128 byte */
 	devfn = PCI_DEVFN(1, 0);
-	pos = pci_bus_find_capability(&bus, devfn, PCI_CAP_ID_EXP);
-	pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
+	pos = pci_bus_find_capability(bus, devfn, PCI_CAP_ID_EXP);
+	pci_bus_read_config_word(bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
 	dc &= ~(0x3 << 12);	/* Clear Device Control Register [14:12] */
-	pci_bus_write_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, dc);
-	pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
+	pci_bus_write_config_word(bus, devfn, pos + PCI_EXP_DEVCTL, dc);
+	pci_bus_read_config_word(bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
 	if (!(dc & (0x3 << 12)))
 		pr_info("PCIe: Set Device Max_Read_Request_Size to 128 byte\n");
 
 	/* Disable PCIe0 Interrupt Mask INTA to INTD */
 	__raw_writel(~0x3FFF, MISC_PCIE_INT_MASK(port));
+
+	kfree(bus);
 }
 
 static int cns3xxx_pcie_abort_handler(unsigned long addr, unsigned int fsr,
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH] ARM: cns3xxx: Don't allocate PCI addresses on stack
  2014-08-25  0:51 [PATCH] ARM: cns3xxx: Don't allocate PCI addresses on stack Mark Brown
@ 2014-08-25 10:34 ` Arnd Bergmann
  2014-08-25 11:30   ` Arnd Bergmann
  0 siblings, 1 reply; 4+ messages in thread
From: Arnd Bergmann @ 2014-08-25 10:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Sunday 24 August 2014 19:51:34 Mark Brown wrote:
> From: Mark Brown <broonie@linaro.org>
> 
> The cns3xxx PCIe code allocates a PCI bus structure on the stack, causing
> warnings due to the excessibe size of the resulting stack frame:
> 
> arch/arm/mach-cns3xxx/pcie.c:311:1: warning: the frame size of 1072 bytes is larger than 1024 bytes [-Wframe-larger-than=]
> 
> Avoid this by dynamically allocating the structure, though I am not
> convinced that we should be locally creating the struct pci_bus in the
> first place.
> 
> Signed-off-by: Mark Brown <broonie@linaro.org>
> 

We should certainly not make up a pci_bus here just for the purpose
of calling a common code function that comes back through a callback
to the locally defined cns3xxx_pci_read_config/cns3xxx_pci_write_config.

However, refactoring the code to do it right seems like actual work
and I'm not sure we can find anybody to do it, so your hack seems
like the best approximation.

	Arnd

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] ARM: cns3xxx: Don't allocate PCI addresses on stack
  2014-08-25 10:34 ` Arnd Bergmann
@ 2014-08-25 11:30   ` Arnd Bergmann
  2014-08-26  7:18     ` Mark Brown
  0 siblings, 1 reply; 4+ messages in thread
From: Arnd Bergmann @ 2014-08-25 11:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 25 August 2014 12:34:25 Arnd Bergmann wrote:
> On Sunday 24 August 2014 19:51:34 Mark Brown wrote:
> > From: Mark Brown <broonie@linaro.org>
> > 
> > The cns3xxx PCIe code allocates a PCI bus structure on the stack, causing
> > warnings due to the excessibe size of the resulting stack frame:
> > 
> > arch/arm/mach-cns3xxx/pcie.c:311:1: warning: the frame size of 1072 bytes is larger than 1024 bytes [-Wframe-larger-than=]
> > 
> > Avoid this by dynamically allocating the structure, though I am not
> > convinced that we should be locally creating the struct pci_bus in the
> > first place.
> > 
> > Signed-off-by: Mark Brown <broonie@linaro.org>
> > 
> 
> We should certainly not make up a pci_bus here just for the purpose
> of calling a common code function that comes back through a callback
> to the locally defined cns3xxx_pci_read_config/cns3xxx_pci_write_config.
> 
> However, refactoring the code to do it right seems like actual work
> and I'm not sure we can find anybody to do it, so your hack seems
> like the best approximation.

I may have spoken too fast. Here is a patch that should deal with the
problem more cleanly, and also help prepare that code for a potential
move to the changed PCI probing infrastructure that is getting
done for arm64.

Completely untested.

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

diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 413134c54452..5b26b574bcbe 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -55,7 +55,7 @@ static struct cns3xxx_pcie *pbus_to_cnspci(struct pci_bus *bus)
 }
 
 static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus,
-				  unsigned int devfn, int where)
+					  unsigned int devfn)
 {
 	struct cns3xxx_pcie *cnspci = pbus_to_cnspci(bus);
 	int busno = bus->number;
@@ -86,61 +86,87 @@ static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus,
 	} else /* remote PCI bus */
 		base = cnspci->cfg1_regs;
 
-	offset = ((busno & 0xf) << 20) | (devfn << 12) | (where & 0xffc);
+	offset = ((busno & 0xf) << 20) | (devfn << 12);
 	return base + offset;
 }
 
-static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
-				   int where, int size, u32 *val)
+static u32 cns3xxx_pci_raw_read_config(void __iomem *base, int where,
+				       int size)
+{
+	u32 v;
+	u32 mask = (0x1ull << (size * 8)) - 1;
+	int shift = (where % 4) * 8;
+
+	v = __raw_readl(base + (where & 0xffc));
+
+	return (v >> shift) & mask;
+}
+
+static u32 cns3xxx_pci_fake_read_config(void __iomem *base, int where,
+				        int size)
 {
 	u32 v;
-	void __iomem *base;
 	u32 mask = (0x1ull << (size * 8)) - 1;
 	int shift = (where % 4) * 8;
 
-	base = cns3xxx_pci_cfg_base(bus, devfn, where);
+	v = __raw_readl(base + (where & 0xffc));
+
+	/*
+	 * RC's class is 0xb, but Linux PCI driver needs 0x604
+	 * for a PCIe bridge. So we must fixup the class code
+	 * to 0x604 here.
+	 */
+	v &= 0xff;
+	v |= 0x604 << 16;
+
+	return (v >> shift) & mask;
+}
+
+static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+				   int where, int size, u32 *val)
+{
+	void __iomem *base;
+
+	base = cns3xxx_pci_cfg_base(bus, devfn);
 	if (!base) {
 		*val = 0xffffffff;
 		return PCIBIOS_SUCCESSFUL;
 	}
 
-	v = __raw_readl(base);
-
 	if (bus->number == 0 && devfn == 0 &&
-			(where & 0xffc) == PCI_CLASS_REVISION) {
-		/*
-		 * RC's class is 0xb, but Linux PCI driver needs 0x604
-		 * for a PCIe bridge. So we must fixup the class code
-		 * to 0x604 here.
-		 */
-		v &= 0xff;
-		v |= 0x604 << 16;
-	}
-
-	*val = (v >> shift) & mask;
+	    (where & 0xffc) == PCI_CLASS_REVISION)
+		*val = cns3xxx_pci_fake_read_config(base, where, size);
+	else
+		*val = cns3xxx_pci_raw_read_config(base, where, size);
 
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int cns3xxx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
-				    int where, int size, u32 val)
+static void cns3xxx_pci_raw_write_config(void __iomem *base, int where,
+					 int size, u32 val)
 {
 	u32 v;
-	void __iomem *base;
 	u32 mask = (0x1ull << (size * 8)) - 1;
 	int shift = (where % 4) * 8;
 
-	base = cns3xxx_pci_cfg_base(bus, devfn, where);
-	if (!base)
-		return PCIBIOS_SUCCESSFUL;
-
-	v = __raw_readl(base);
+	v = __raw_readl(base + (where & 0xffc));
 
 	v &= ~(mask << shift);
 	v |= (val & mask) << shift;
 
-	__raw_writel(v, base);
+	__raw_writel(v, base + (where & 0xffc));
+}
+
+static int cns3xxx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+				    int where, int size, u32 val)
+{
+	void __iomem *base;
 
+	base = cns3xxx_pci_cfg_base(bus, devfn);
+	if (!base)
+		return PCIBIOS_SUCCESSFUL;
+
+	cns3xxx_pci_raw_write_config(base, where, size, val);
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -262,47 +288,42 @@ static void __init cns3xxx_pcie_check_link(struct cns3xxx_pcie *cnspci)
 
 static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci)
 {
+	void __iomem *regs = cnspci->host_regs;
 	int port = cnspci->hw_pci.domain;
-	struct pci_sys_data sd = {
-		.domain = port,
-	};
-	struct pci_bus bus = {
-		.number = 0,
-		.ops = &cns3xxx_pcie_ops,
-		.sysdata = &sd,
-	};
 	u16 mem_base  = cnspci->res_mem.start >> 16;
 	u16 mem_limit = cnspci->res_mem.end   >> 16;
 	u16 io_base   = cnspci->res_io.start  >> 16;
 	u16 io_limit  = cnspci->res_io.end    >> 16;
-	u32 devfn = 0;
-	u8 tmp8;
 	u16 pos;
 	u16 dc;
 
-	pci_bus_write_config_byte(&bus, devfn, PCI_PRIMARY_BUS, 0);
-	pci_bus_write_config_byte(&bus, devfn, PCI_SECONDARY_BUS, 1);
-	pci_bus_write_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, 1);
+	cns3xxx_pci_raw_write_config(regs, PCI_PRIMARY_BUS, 1, 0);
+	cns3xxx_pci_raw_write_config(regs, PCI_SECONDARY_BUS, 1, 1);
+	cns3xxx_pci_raw_write_config(regs, PCI_SUBORDINATE_BUS, 1, 1);
 
-	pci_bus_read_config_byte(&bus, devfn, PCI_PRIMARY_BUS, &tmp8);
-	pci_bus_read_config_byte(&bus, devfn, PCI_SECONDARY_BUS, &tmp8);
-	pci_bus_read_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, &tmp8);
+	cns3xxx_pci_raw_read_config(regs, PCI_PRIMARY_BUS, 1);
+	cns3xxx_pci_raw_read_config(regs, PCI_SECONDARY_BUS, 1);
+	cns3xxx_pci_raw_read_config(regs, PCI_SUBORDINATE_BUS, 1);
 
-	pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_BASE, mem_base);
-	pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_LIMIT, mem_limit);
-	pci_bus_write_config_word(&bus, devfn, PCI_IO_BASE_UPPER16, io_base);
-	pci_bus_write_config_word(&bus, devfn, PCI_IO_LIMIT_UPPER16, io_limit);
+	cns3xxx_pci_raw_write_config(regs, PCI_MEMORY_BASE, 2, mem_base);
+	cns3xxx_pci_raw_write_config(regs, PCI_MEMORY_LIMIT, 2, mem_limit);
+	cns3xxx_pci_raw_write_config(regs, PCI_IO_BASE_UPPER16, 2, io_base);
+	cns3xxx_pci_raw_write_config(regs, PCI_IO_LIMIT_UPPER16, 2, io_limit);
 
 	if (!cnspci->linked)
 		return;
 
+	regs = cnspci->cfg0_regs + (PCI_DEVFN(1, 0) << 12);
+
 	/* Set Device Max_Read_Request_Size to 128 byte */
-	devfn = PCI_DEVFN(1, 0);
-	pos = pci_bus_find_capability(&bus, devfn, PCI_CAP_ID_EXP);
-	pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
+	pos = cns3xxx_pci_raw_read_config(regs, PCI_CAPABILITY_LIST, 1);
+	while (cns3xxx_pci_raw_read_config(regs, pos, 1) != PCI_CAP_ID_EXP)
+		pos = cns3xxx_pci_raw_read_config(regs, pos + PCI_CAP_LIST_NEXT, 1);
+		
+	dc = cns3xxx_pci_raw_read_config(regs, pos + PCI_EXP_DEVCTL, 2);
 	dc &= ~(0x3 << 12);	/* Clear Device Control Register [14:12] */
-	pci_bus_write_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, dc);
-	pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
+	cns3xxx_pci_raw_write_config(regs, pos + PCI_EXP_DEVCTL, 2, dc);
+	dc = cns3xxx_pci_raw_read_config(regs, pos + PCI_EXP_DEVCTL, 2);
 	if (!(dc & (0x3 << 12)))
 		pr_info("PCIe: Set Device Max_Read_Request_Size to 128 byte\n");
 

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH] ARM: cns3xxx: Don't allocate PCI addresses on stack
  2014-08-25 11:30   ` Arnd Bergmann
@ 2014-08-26  7:18     ` Mark Brown
  0 siblings, 0 replies; 4+ messages in thread
From: Mark Brown @ 2014-08-26  7:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 25, 2014 at 01:30:22PM +0200, Arnd Bergmann wrote:
> On Monday 25 August 2014 12:34:25 Arnd Bergmann wrote:

> > However, refactoring the code to do it right seems like actual work
> > and I'm not sure we can find anybody to do it, so your hack seems
> > like the best approximation.

> I may have spoken too fast. Here is a patch that should deal with the
> problem more cleanly, and also help prepare that code for a potential
> move to the changed PCI probing infrastructure that is getting
> done for arm64.

> Completely untested.

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

Right, this looks reasonably sensible to me.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140826/07eba653/attachment.sig>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-08-26  7:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-25  0:51 [PATCH] ARM: cns3xxx: Don't allocate PCI addresses on stack Mark Brown
2014-08-25 10:34 ` Arnd Bergmann
2014-08-25 11:30   ` Arnd Bergmann
2014-08-26  7:18     ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).