ARM: cns3xxx: Don't allocate PCI addresses on stack
Subsystems (2)
PATCH 1/1 ARM: cns3xxx: Don't allocate PCI addresses on stack
From: Mark Brown <[email protected]>
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.
--- arch/arm/mach-cns3xxx/pcie.c | 49 ++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 20 deletions(-)
arch/arm/mach-cns3xxx/pcie.c +29 -20
@@ -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,
Signature · 1 line
2.1.0.rc1
PATCH 1/1 ARM: cns3xxx: Don't allocate PCI addresses on stack
Quoted 5 lines · On Sunday 24 August 2014 19:51:34 Mark Brown wrote:
From: Mark Brown <[email protected]>
The cns3xxx PCIe code allocates a PCI bus structure on the stack, causing warnings due to the excessibe size of the resulting stack frame:
Quoted 8 lines
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_busin the first place.Signed-off-by Mark Brown <[email protected]>
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
PATCH 1/1 ARM: cns3xxx: Don't allocate PCI addresses on stack
Quoted 15 lines · On Monday 25 August 2014 12:34:25 Arnd Bergmann wrote:
Quoted 5 lines · On Sunday 24 August 2014 19:51:34 Mark Brown wrote:
From: Mark Brown <[email protected]>
The cns3xxx PCIe code allocates a PCI bus structure on the stack, causing warnings due to the excessibe size of the resulting stack frame:
Quoted 8 lines
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_busin the first place.Signed-off-by Mark Brown <[email protected]>
Quoted 7 lines
We should certainly not make up a
pci_bushere 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.
arch/arm/mach-cns3xxx/pcie.c +74 -53
@@ -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" );
PATCH 1/1 ARM: cns3xxx: Don't allocate PCI addresses on stack
Quoted 6 lines · Arnd Bergmann
Quoted 3 lines · 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.
Quoted 8 lines
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 <[email protected]>
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>