aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/opal.h2
-rw-r--r--arch/powerpc/platforms/powernv/opal.c17
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c9
-rw-r--r--arch/powerpc/platforms/powernv/pci.c12
-rw-r--r--arch/powerpc/platforms/powernv/pci.h2
-rw-r--r--arch/powerpc/platforms/powernv/powernv.h2
-rw-r--r--arch/powerpc/platforms/powernv/setup.c12
7 files changed, 56 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index b6c8b58b1d76..b2906adb89d3 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -563,6 +563,8 @@ extern void opal_nvram_init(void);
563 563
564extern int opal_machine_check(struct pt_regs *regs); 564extern int opal_machine_check(struct pt_regs *regs);
565 565
566extern void opal_shutdown(void);
567
566#endif /* __ASSEMBLY__ */ 568#endif /* __ASSEMBLY__ */
567 569
568#endif /* __OPAL_H */ 570#endif /* __OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 12d9846aa87e..27907cb18b8a 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -15,6 +15,7 @@
15#include <linux/of.h> 15#include <linux/of.h>
16#include <linux/of_platform.h> 16#include <linux/of_platform.h>
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/slab.h>
18#include <asm/opal.h> 19#include <asm/opal.h>
19#include <asm/firmware.h> 20#include <asm/firmware.h>
20 21
@@ -28,6 +29,8 @@ struct opal {
28static struct device_node *opal_node; 29static struct device_node *opal_node;
29static DEFINE_SPINLOCK(opal_write_lock); 30static DEFINE_SPINLOCK(opal_write_lock);
30extern u64 opal_mc_secondary_handler[]; 31extern u64 opal_mc_secondary_handler[];
32static unsigned int *opal_irqs;
33static unsigned int opal_irq_count;
31 34
32int __init early_init_dt_scan_opal(unsigned long node, 35int __init early_init_dt_scan_opal(unsigned long node,
33 const char *uname, int depth, void *data) 36 const char *uname, int depth, void *data)
@@ -323,6 +326,8 @@ static int __init opal_init(void)
323 irqs = of_get_property(opal_node, "opal-interrupts", &irqlen); 326 irqs = of_get_property(opal_node, "opal-interrupts", &irqlen);
324 pr_debug("opal: Found %d interrupts reserved for OPAL\n", 327 pr_debug("opal: Found %d interrupts reserved for OPAL\n",
325 irqs ? (irqlen / 4) : 0); 328 irqs ? (irqlen / 4) : 0);
329 opal_irq_count = irqlen / 4;
330 opal_irqs = kzalloc(opal_irq_count * sizeof(unsigned int), GFP_KERNEL);
326 for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) { 331 for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) {
327 unsigned int hwirq = be32_to_cpup(irqs); 332 unsigned int hwirq = be32_to_cpup(irqs);
328 unsigned int irq = irq_create_mapping(NULL, hwirq); 333 unsigned int irq = irq_create_mapping(NULL, hwirq);
@@ -334,7 +339,19 @@ static int __init opal_init(void)
334 if (rc) 339 if (rc)
335 pr_warning("opal: Error %d requesting irq %d" 340 pr_warning("opal: Error %d requesting irq %d"
336 " (0x%x)\n", rc, irq, hwirq); 341 " (0x%x)\n", rc, irq, hwirq);
342 opal_irqs[i] = irq;
337 } 343 }
338 return 0; 344 return 0;
339} 345}
340subsys_initcall(opal_init); 346subsys_initcall(opal_init);
347
348void opal_shutdown(void)
349{
350 unsigned int i;
351
352 for (i = 0; i < opal_irq_count; i++) {
353 if (opal_irqs[i])
354 free_irq(opal_irqs[i], 0);
355 opal_irqs[i] = 0;
356 }
357}
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 1da578b7c1bf..3937aaae5bc4 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1048,6 +1048,12 @@ static u32 pnv_ioda_bdfn_to_pe(struct pnv_phb *phb, struct pci_bus *bus,
1048 return phb->ioda.pe_rmap[(bus->number << 8) | devfn]; 1048 return phb->ioda.pe_rmap[(bus->number << 8) | devfn];
1049} 1049}
1050 1050
1051static void pnv_pci_ioda_shutdown(struct pnv_phb *phb)
1052{
1053 opal_pci_reset(phb->opal_id, OPAL_PCI_IODA_TABLE_RESET,
1054 OPAL_ASSERT_RESET);
1055}
1056
1051void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) 1057void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
1052{ 1058{
1053 struct pci_controller *hose; 1059 struct pci_controller *hose;
@@ -1178,6 +1184,9 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
1178 /* Setup TCEs */ 1184 /* Setup TCEs */
1179 phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; 1185 phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup;
1180 1186
1187 /* Setup shutdown function for kexec */
1188 phb->shutdown = pnv_pci_ioda_shutdown;
1189
1181 /* Setup MSI support */ 1190 /* Setup MSI support */
1182 pnv_pci_init_ioda_msis(phb); 1191 pnv_pci_init_ioda_msis(phb);
1183 1192
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 55dfca844ddf..163bd7422f1c 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -450,6 +450,18 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
450 pnv_pci_dma_fallback_setup(hose, pdev); 450 pnv_pci_dma_fallback_setup(hose, pdev);
451} 451}
452 452
453void pnv_pci_shutdown(void)
454{
455 struct pci_controller *hose;
456
457 list_for_each_entry(hose, &hose_list, list_node) {
458 struct pnv_phb *phb = hose->private_data;
459
460 if (phb && phb->shutdown)
461 phb->shutdown(phb);
462 }
463}
464
453/* Fixup wrong class code in p7ioc and p8 root complex */ 465/* Fixup wrong class code in p7ioc and p8 root complex */
454static void pnv_p7ioc_rc_quirk(struct pci_dev *dev) 466static void pnv_p7ioc_rc_quirk(struct pci_dev *dev)
455{ 467{
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 48dc4bb856a1..25d76c4df50b 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -86,6 +86,7 @@ struct pnv_phb {
86 void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev); 86 void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
87 void (*fixup_phb)(struct pci_controller *hose); 87 void (*fixup_phb)(struct pci_controller *hose);
88 u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); 88 u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
89 void (*shutdown)(struct pnv_phb *phb);
89 90
90 union { 91 union {
91 struct { 92 struct {
@@ -158,4 +159,5 @@ extern void pnv_pci_init_ioda_hub(struct device_node *np);
158extern void pnv_pci_init_ioda2_phb(struct device_node *np); 159extern void pnv_pci_init_ioda2_phb(struct device_node *np);
159extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, 160extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
160 u64 *startp, u64 *endp); 161 u64 *startp, u64 *endp);
162
161#endif /* __POWERNV_PCI_H */ 163#endif /* __POWERNV_PCI_H */
diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h
index 8a9df7f9667e..a1c6f83fc391 100644
--- a/arch/powerpc/platforms/powernv/powernv.h
+++ b/arch/powerpc/platforms/powernv/powernv.h
@@ -9,8 +9,10 @@ static inline void pnv_smp_init(void) { }
9 9
10#ifdef CONFIG_PCI 10#ifdef CONFIG_PCI
11extern void pnv_pci_init(void); 11extern void pnv_pci_init(void);
12extern void pnv_pci_shutdown(void);
12#else 13#else
13static inline void pnv_pci_init(void) { } 14static inline void pnv_pci_init(void) { }
15static inline void pnv_pci_shutdown(void) { }
14#endif 16#endif
15 17
16#endif /* _POWERNV_H */ 18#endif /* _POWERNV_H */
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index db1ad1c8f68f..c20381caaa3e 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -126,6 +126,17 @@ static void pnv_progress(char *s, unsigned short hex)
126{ 126{
127} 127}
128 128
129static void pnv_shutdown(void)
130{
131 /* Let the PCI code clear up IODA tables */
132 pnv_pci_shutdown();
133
134 /* And unregister all OPAL interrupts so they don't fire
135 * up while we kexec
136 */
137 opal_shutdown();
138}
139
129#ifdef CONFIG_KEXEC 140#ifdef CONFIG_KEXEC
130static void pnv_kexec_cpu_down(int crash_shutdown, int secondary) 141static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
131{ 142{
@@ -187,6 +198,7 @@ define_machine(powernv) {
187 .init_IRQ = pnv_init_IRQ, 198 .init_IRQ = pnv_init_IRQ,
188 .show_cpuinfo = pnv_show_cpuinfo, 199 .show_cpuinfo = pnv_show_cpuinfo,
189 .progress = pnv_progress, 200 .progress = pnv_progress,
201 .machine_shutdown = pnv_shutdown,
190 .power_save = power7_idle, 202 .power_save = power7_idle,
191 .calibrate_decr = generic_calibrate_decr, 203 .calibrate_decr = generic_calibrate_decr,
192#ifdef CONFIG_KEXEC 204#ifdef CONFIG_KEXEC