aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2012-03-14 05:36:09 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-05-15 11:49:05 -0400
commita68ad4d892c6254310d2bfc3d6b0c0d989377636 (patch)
tree28e30e1a250a2dc2e90b3ec2751e9f7d1879e440
parent881b6ef0cca3395ac0171472a1ce768fede7535b (diff)
MIPS: ath79: allow to use board specific pci_plat_dev_init functions
Th current implementation causes NULL pointer dereference if 'pci_data' is not set: pci 0000:00:00.0: BAR 0: assigned [mem 0x10000000-0x1000ffff 64bit] pci 0000:00:00.0: BAR 0: set to [mem 0x10000000-0x1000ffff 64bit] (PCI address [0x10000000-0x1000ffff]) CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 802daca0, ra == 802e78a4 Oops[#1]: Cpu 0 $ 0 : 00000000 80420000 00000000 00000000 $ 4 : 00000000 00000000 00000001 00000001 $ 8 : 00000001 0000032c 81c54700 00000001 $12 : 0000032d 0000000f 00000000 ffffffff $16 : 81c14c00 00000001 802dac74 80195f98 $20 : 802ea050 00000000 00000000 00000000 $24 : 00000003 800617f0 $28 : 81c20000 81c21e70 00000000 802e78a4 Hi : 00000000 Lo : 4190ab00 epc : 802daca0 0x802daca0 Not tainted ra : 802e78a4 0x802e78a4 Status: 1000c003 KERNEL EXL IE Cause : 00800008 BadVA : 00000000 PrId : 00019374 (MIPS 24Kc) Modules linked in: Process swapper (pid: 1, threadinfo=81c20000, task=81c18000, tls=00000000) Stack : 00000000 8027d5d8 802e8ae0 00000000 01000000 802e8b5c 81c50600 00000000 802ff290 00000000 80420000 802ea0bc 00000000 00000000 80420000 802ff290 80420000 80060930 33390000 00000000 00002308 80140a80 00000028 802d0000 00000000 800ba024 802ff004 802ff0c8 802ff290 00000000 00000000 00000000 00000000 802d897c 01234567 7f827068 00000000 0045f798 00460000 00000000 This can be avoided by calling the 'ar724x_pci_add_data' function from the board specific setup code. However it makes no sense to use that function for every board, especially when the board does not needs to set the platform_data field of any PCI device. The patch allows the board setup code to specify a board specific function if that is required. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3499/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/ath79/mach-ubnt-xm.c13
-rw-r--r--arch/mips/ath79/pci.c14
-rw-r--r--arch/mips/ath79/pci.h4
3 files changed, 23 insertions, 8 deletions
diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c
index 1e6b986cb470..ca47ba57a206 100644
--- a/arch/mips/ath79/mach-ubnt-xm.c
+++ b/arch/mips/ath79/mach-ubnt-xm.c
@@ -85,16 +85,27 @@ static struct ath9k_platform_data ubnt_xm_eeprom_data;
85static struct ar724x_pci_data ubnt_xm_pci_data[] = { 85static struct ar724x_pci_data ubnt_xm_pci_data[] = {
86 { 86 {
87 .irq = ATH79_PCI_IRQ(0), 87 .irq = ATH79_PCI_IRQ(0),
88 .pdata = &ubnt_xm_eeprom_data,
89 }, 88 },
90}; 89};
91 90
91static int ubnt_xm_pci_plat_dev_init(struct pci_dev *dev)
92{
93 switch (PCI_SLOT(dev->devfn)) {
94 case 0:
95 dev->dev.platform_data = &ubnt_xm_eeprom_data;
96 break;
97 }
98
99 return 0;
100}
101
92static void __init ubnt_xm_pci_init(void) 102static void __init ubnt_xm_pci_init(void)
93{ 103{
94 memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR, 104 memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
95 sizeof(ubnt_xm_eeprom_data.eeprom_data)); 105 sizeof(ubnt_xm_eeprom_data.eeprom_data));
96 106
97 ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data)); 107 ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
108 ath79_pci_set_plat_dev_init(ubnt_xm_pci_plat_dev_init);
98 ath79_register_pci(); 109 ath79_register_pci();
99} 110}
100#else 111#else
diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 14f981c295d2..2b4c730ccbcb 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -14,6 +14,7 @@
14#include <asm/mach-ath79/pci.h> 14#include <asm/mach-ath79/pci.h>
15#include "pci.h" 15#include "pci.h"
16 16
17static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
17static struct ar724x_pci_data *pci_data; 18static struct ar724x_pci_data *pci_data;
18static int pci_data_size; 19static int pci_data_size;
19 20
@@ -38,14 +39,15 @@ int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
38 39
39int pcibios_plat_dev_init(struct pci_dev *dev) 40int pcibios_plat_dev_init(struct pci_dev *dev)
40{ 41{
41 unsigned int devfn = dev->devfn; 42 if (ath79_pci_plat_dev_init)
42 43 return ath79_pci_plat_dev_init(dev);
43 if (devfn > pci_data_size - 1)
44 return PCIBIOS_DEVICE_NOT_FOUND;
45 44
46 dev->dev.platform_data = pci_data[devfn].pdata; 45 return 0;
46}
47 47
48 return PCIBIOS_SUCCESSFUL; 48void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev))
49{
50 ath79_pci_plat_dev_init = func;
49} 51}
50 52
51int __init ath79_register_pci(void) 53int __init ath79_register_pci(void)
diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h
index e0601c4a7fc6..de30e158932d 100644
--- a/arch/mips/ath79/pci.h
+++ b/arch/mips/ath79/pci.h
@@ -13,14 +13,16 @@
13 13
14struct ar724x_pci_data { 14struct ar724x_pci_data {
15 int irq; 15 int irq;
16 void *pdata;
17}; 16};
18 17
19void ar724x_pci_add_data(struct ar724x_pci_data *data, int size); 18void ar724x_pci_add_data(struct ar724x_pci_data *data, int size);
20 19
21#ifdef CONFIG_PCI 20#ifdef CONFIG_PCI
21void ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev));
22int ath79_register_pci(void); 22int ath79_register_pci(void);
23#else 23#else
24static inline void
25ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *)) {}
24static inline int ath79_register_pci(void) { return 0; } 26static inline int ath79_register_pci(void) { return 0; }
25#endif 27#endif
26 28