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,
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
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");
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.
linaro-kernel@lists.linaro.org