diff options
Diffstat (limited to 'arch/powerpc/platforms')
| -rw-r--r-- | arch/powerpc/platforms/Kconfig | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/Kconfig | 1 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/opal.c | 30 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/pci-ioda.c | 36 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/pci.c | 18 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/pci.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/powernv.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/setup.c | 16 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/smp.c | 62 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/Kconfig | 1 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/msi.c | 75 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/suspend.c | 22 | ||||
| -rw-r--r-- | arch/powerpc/platforms/wsp/ics.c | 2 |
13 files changed, 207 insertions, 62 deletions
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index a881232a3cce..b62aab3e22ec 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
| @@ -128,7 +128,7 @@ config PPC_RTAS_DAEMON | |||
| 128 | 128 | ||
| 129 | config RTAS_PROC | 129 | config RTAS_PROC |
| 130 | bool "Proc interface to RTAS" | 130 | bool "Proc interface to RTAS" |
| 131 | depends on PPC_RTAS | 131 | depends on PPC_RTAS && PROC_FS |
| 132 | default y | 132 | default y |
| 133 | 133 | ||
| 134 | config RTAS_FLASH | 134 | config RTAS_FLASH |
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig index d3e840d643af..c24684c818ab 100644 --- a/arch/powerpc/platforms/powernv/Kconfig +++ b/arch/powerpc/platforms/powernv/Kconfig | |||
| @@ -6,6 +6,7 @@ config PPC_POWERNV | |||
| 6 | select PPC_ICP_NATIVE | 6 | select PPC_ICP_NATIVE |
| 7 | select PPC_P7_NAP | 7 | select PPC_P7_NAP |
| 8 | select PPC_PCI_CHOICE if EMBEDDED | 8 | select PPC_PCI_CHOICE if EMBEDDED |
| 9 | select EPAPR_BOOT | ||
| 9 | default y | 10 | default y |
| 10 | 11 | ||
| 11 | config POWERNV_MSI | 12 | config POWERNV_MSI |
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index ade4463226c6..628c564ceadb 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 { | |||
| 28 | static struct device_node *opal_node; | 29 | static struct device_node *opal_node; |
| 29 | static DEFINE_SPINLOCK(opal_write_lock); | 30 | static DEFINE_SPINLOCK(opal_write_lock); |
| 30 | extern u64 opal_mc_secondary_handler[]; | 31 | extern u64 opal_mc_secondary_handler[]; |
| 32 | static unsigned int *opal_irqs; | ||
| 33 | static unsigned int opal_irq_count; | ||
| 31 | 34 | ||
| 32 | int __init early_init_dt_scan_opal(unsigned long node, | 35 | int __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) |
| @@ -53,7 +56,11 @@ int __init early_init_dt_scan_opal(unsigned long node, | |||
| 53 | opal.entry, entryp, entrysz); | 56 | opal.entry, entryp, entrysz); |
| 54 | 57 | ||
| 55 | powerpc_firmware_features |= FW_FEATURE_OPAL; | 58 | powerpc_firmware_features |= FW_FEATURE_OPAL; |
| 56 | if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { | 59 | if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) { |
| 60 | powerpc_firmware_features |= FW_FEATURE_OPALv2; | ||
| 61 | powerpc_firmware_features |= FW_FEATURE_OPALv3; | ||
| 62 | printk("OPAL V3 detected !\n"); | ||
| 63 | } else if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { | ||
| 57 | powerpc_firmware_features |= FW_FEATURE_OPALv2; | 64 | powerpc_firmware_features |= FW_FEATURE_OPALv2; |
| 58 | printk("OPAL V2 detected !\n"); | 65 | printk("OPAL V2 detected !\n"); |
| 59 | } else { | 66 | } else { |
| @@ -144,6 +151,13 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | |||
| 144 | rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { | 151 | rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { |
| 145 | len = total_len; | 152 | len = total_len; |
| 146 | rc = opal_console_write(vtermno, &len, data); | 153 | rc = opal_console_write(vtermno, &len, data); |
| 154 | |||
| 155 | /* Closed or other error drop */ | ||
| 156 | if (rc != OPAL_SUCCESS && rc != OPAL_BUSY && | ||
| 157 | rc != OPAL_BUSY_EVENT) { | ||
| 158 | written = total_len; | ||
| 159 | break; | ||
| 160 | } | ||
| 147 | if (rc == OPAL_SUCCESS) { | 161 | if (rc == OPAL_SUCCESS) { |
| 148 | total_len -= len; | 162 | total_len -= len; |
| 149 | data += len; | 163 | data += len; |
| @@ -316,6 +330,8 @@ static int __init opal_init(void) | |||
| 316 | irqs = of_get_property(opal_node, "opal-interrupts", &irqlen); | 330 | irqs = of_get_property(opal_node, "opal-interrupts", &irqlen); |
| 317 | pr_debug("opal: Found %d interrupts reserved for OPAL\n", | 331 | pr_debug("opal: Found %d interrupts reserved for OPAL\n", |
| 318 | irqs ? (irqlen / 4) : 0); | 332 | irqs ? (irqlen / 4) : 0); |
| 333 | opal_irq_count = irqlen / 4; | ||
| 334 | opal_irqs = kzalloc(opal_irq_count * sizeof(unsigned int), GFP_KERNEL); | ||
| 319 | for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) { | 335 | for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) { |
| 320 | unsigned int hwirq = be32_to_cpup(irqs); | 336 | unsigned int hwirq = be32_to_cpup(irqs); |
| 321 | unsigned int irq = irq_create_mapping(NULL, hwirq); | 337 | unsigned int irq = irq_create_mapping(NULL, hwirq); |
| @@ -327,7 +343,19 @@ static int __init opal_init(void) | |||
| 327 | if (rc) | 343 | if (rc) |
| 328 | pr_warning("opal: Error %d requesting irq %d" | 344 | pr_warning("opal: Error %d requesting irq %d" |
| 329 | " (0x%x)\n", rc, irq, hwirq); | 345 | " (0x%x)\n", rc, irq, hwirq); |
| 346 | opal_irqs[i] = irq; | ||
| 330 | } | 347 | } |
| 331 | return 0; | 348 | return 0; |
| 332 | } | 349 | } |
| 333 | subsys_initcall(opal_init); | 350 | subsys_initcall(opal_init); |
| 351 | |||
| 352 | void opal_shutdown(void) | ||
| 353 | { | ||
| 354 | unsigned int i; | ||
| 355 | |||
| 356 | for (i = 0; i < opal_irq_count; i++) { | ||
| 357 | if (opal_irqs[i]) | ||
| 358 | free_irq(opal_irqs[i], 0); | ||
| 359 | opal_irqs[i] = 0; | ||
| 360 | } | ||
| 361 | } | ||
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 1da578b7c1bf..9c9d15e4cdf2 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
| @@ -68,16 +68,6 @@ define_pe_printk_level(pe_err, KERN_ERR); | |||
| 68 | define_pe_printk_level(pe_warn, KERN_WARNING); | 68 | define_pe_printk_level(pe_warn, KERN_WARNING); |
| 69 | define_pe_printk_level(pe_info, KERN_INFO); | 69 | define_pe_printk_level(pe_info, KERN_INFO); |
| 70 | 70 | ||
| 71 | static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev) | ||
| 72 | { | ||
| 73 | struct device_node *np; | ||
| 74 | |||
| 75 | np = pci_device_to_OF_node(dev); | ||
| 76 | if (!np) | ||
| 77 | return NULL; | ||
| 78 | return PCI_DN(np); | ||
| 79 | } | ||
| 80 | |||
| 81 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) | 71 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) |
| 82 | { | 72 | { |
| 83 | unsigned long pe; | 73 | unsigned long pe; |
| @@ -110,7 +100,7 @@ static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev) | |||
| 110 | { | 100 | { |
| 111 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | 101 | struct pci_controller *hose = pci_bus_to_host(dev->bus); |
| 112 | struct pnv_phb *phb = hose->private_data; | 102 | struct pnv_phb *phb = hose->private_data; |
| 113 | struct pci_dn *pdn = pnv_ioda_get_pdn(dev); | 103 | struct pci_dn *pdn = pci_get_pdn(dev); |
| 114 | 104 | ||
| 115 | if (!pdn) | 105 | if (!pdn) |
| 116 | return NULL; | 106 | return NULL; |
| @@ -173,7 +163,7 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) | |||
| 173 | 163 | ||
| 174 | /* Add to all parents PELT-V */ | 164 | /* Add to all parents PELT-V */ |
| 175 | while (parent) { | 165 | while (parent) { |
| 176 | struct pci_dn *pdn = pnv_ioda_get_pdn(parent); | 166 | struct pci_dn *pdn = pci_get_pdn(parent); |
| 177 | if (pdn && pdn->pe_number != IODA_INVALID_PE) { | 167 | if (pdn && pdn->pe_number != IODA_INVALID_PE) { |
| 178 | rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number, | 168 | rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number, |
| 179 | pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); | 169 | pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); |
| @@ -252,7 +242,7 @@ static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev) | |||
| 252 | { | 242 | { |
| 253 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | 243 | struct pci_controller *hose = pci_bus_to_host(dev->bus); |
| 254 | struct pnv_phb *phb = hose->private_data; | 244 | struct pnv_phb *phb = hose->private_data; |
| 255 | struct pci_dn *pdn = pnv_ioda_get_pdn(dev); | 245 | struct pci_dn *pdn = pci_get_pdn(dev); |
| 256 | struct pnv_ioda_pe *pe; | 246 | struct pnv_ioda_pe *pe; |
| 257 | int pe_num; | 247 | int pe_num; |
| 258 | 248 | ||
| @@ -323,7 +313,7 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe) | |||
| 323 | struct pci_dev *dev; | 313 | struct pci_dev *dev; |
| 324 | 314 | ||
| 325 | list_for_each_entry(dev, &bus->devices, bus_list) { | 315 | list_for_each_entry(dev, &bus->devices, bus_list) { |
| 326 | struct pci_dn *pdn = pnv_ioda_get_pdn(dev); | 316 | struct pci_dn *pdn = pci_get_pdn(dev); |
| 327 | 317 | ||
| 328 | if (pdn == NULL) { | 318 | if (pdn == NULL) { |
| 329 | pr_warn("%s: No device node associated with device !\n", | 319 | pr_warn("%s: No device node associated with device !\n", |
| @@ -436,7 +426,7 @@ static void pnv_pci_ioda_setup_PEs(void) | |||
| 436 | 426 | ||
| 437 | static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev) | 427 | static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev) |
| 438 | { | 428 | { |
| 439 | struct pci_dn *pdn = pnv_ioda_get_pdn(pdev); | 429 | struct pci_dn *pdn = pci_get_pdn(pdev); |
| 440 | struct pnv_ioda_pe *pe; | 430 | struct pnv_ioda_pe *pe; |
| 441 | 431 | ||
| 442 | /* | 432 | /* |
| @@ -768,6 +758,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, | |||
| 768 | unsigned int is_64, struct msi_msg *msg) | 758 | unsigned int is_64, struct msi_msg *msg) |
| 769 | { | 759 | { |
| 770 | struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev); | 760 | struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev); |
| 761 | struct pci_dn *pdn = pci_get_pdn(dev); | ||
| 771 | struct irq_data *idata; | 762 | struct irq_data *idata; |
| 772 | struct irq_chip *ichip; | 763 | struct irq_chip *ichip; |
| 773 | unsigned int xive_num = hwirq - phb->msi_base; | 764 | unsigned int xive_num = hwirq - phb->msi_base; |
| @@ -783,6 +774,10 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, | |||
| 783 | if (pe->mve_number < 0) | 774 | if (pe->mve_number < 0) |
| 784 | return -ENXIO; | 775 | return -ENXIO; |
| 785 | 776 | ||
| 777 | /* Force 32-bit MSI on some broken devices */ | ||
| 778 | if (pdn && pdn->force_32bit_msi) | ||
| 779 | is_64 = 0; | ||
| 780 | |||
| 786 | /* Assign XIVE to PE */ | 781 | /* Assign XIVE to PE */ |
| 787 | rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num); | 782 | rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num); |
| 788 | if (rc) { | 783 | if (rc) { |
| @@ -1035,7 +1030,7 @@ static int pnv_pci_enable_device_hook(struct pci_dev *dev) | |||
| 1035 | if (!phb->initialized) | 1030 | if (!phb->initialized) |
| 1036 | return 0; | 1031 | return 0; |
| 1037 | 1032 | ||
| 1038 | pdn = pnv_ioda_get_pdn(dev); | 1033 | pdn = pci_get_pdn(dev); |
| 1039 | if (!pdn || pdn->pe_number == IODA_INVALID_PE) | 1034 | if (!pdn || pdn->pe_number == IODA_INVALID_PE) |
| 1040 | return -EINVAL; | 1035 | return -EINVAL; |
| 1041 | 1036 | ||
| @@ -1048,6 +1043,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]; | 1043 | return phb->ioda.pe_rmap[(bus->number << 8) | devfn]; |
| 1049 | } | 1044 | } |
| 1050 | 1045 | ||
| 1046 | static void pnv_pci_ioda_shutdown(struct pnv_phb *phb) | ||
| 1047 | { | ||
| 1048 | opal_pci_reset(phb->opal_id, OPAL_PCI_IODA_TABLE_RESET, | ||
| 1049 | OPAL_ASSERT_RESET); | ||
| 1050 | } | ||
| 1051 | |||
| 1051 | void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) | 1052 | void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) |
| 1052 | { | 1053 | { |
| 1053 | struct pci_controller *hose; | 1054 | struct pci_controller *hose; |
| @@ -1178,6 +1179,9 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) | |||
| 1178 | /* Setup TCEs */ | 1179 | /* Setup TCEs */ |
| 1179 | phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; | 1180 | phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; |
| 1180 | 1181 | ||
| 1182 | /* Setup shutdown function for kexec */ | ||
| 1183 | phb->shutdown = pnv_pci_ioda_shutdown; | ||
| 1184 | |||
| 1181 | /* Setup MSI support */ | 1185 | /* Setup MSI support */ |
| 1182 | pnv_pci_init_ioda_msis(phb); | 1186 | pnv_pci_init_ioda_msis(phb); |
| 1183 | 1187 | ||
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 55dfca844ddf..277343cc6a3d 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
| @@ -47,6 +47,10 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type) | |||
| 47 | { | 47 | { |
| 48 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | 48 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
| 49 | struct pnv_phb *phb = hose->private_data; | 49 | struct pnv_phb *phb = hose->private_data; |
| 50 | struct pci_dn *pdn = pci_get_pdn(pdev); | ||
| 51 | |||
| 52 | if (pdn && pdn->force_32bit_msi && !phb->msi32_support) | ||
| 53 | return -ENODEV; | ||
| 50 | 54 | ||
| 51 | return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV; | 55 | return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV; |
| 52 | } | 56 | } |
| @@ -367,7 +371,7 @@ static void pnv_tce_free(struct iommu_table *tbl, long index, long npages) | |||
| 367 | while (npages--) | 371 | while (npages--) |
| 368 | *(tcep++) = 0; | 372 | *(tcep++) = 0; |
| 369 | 373 | ||
| 370 | if (tbl->it_type & TCE_PCI_SWINV_CREATE) | 374 | if (tbl->it_type & TCE_PCI_SWINV_FREE) |
| 371 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1); | 375 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1); |
| 372 | } | 376 | } |
| 373 | 377 | ||
| @@ -450,6 +454,18 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev) | |||
| 450 | pnv_pci_dma_fallback_setup(hose, pdev); | 454 | pnv_pci_dma_fallback_setup(hose, pdev); |
| 451 | } | 455 | } |
| 452 | 456 | ||
| 457 | void pnv_pci_shutdown(void) | ||
| 458 | { | ||
| 459 | struct pci_controller *hose; | ||
| 460 | |||
| 461 | list_for_each_entry(hose, &hose_list, list_node) { | ||
| 462 | struct pnv_phb *phb = hose->private_data; | ||
| 463 | |||
| 464 | if (phb && phb->shutdown) | ||
| 465 | phb->shutdown(phb); | ||
| 466 | } | ||
| 467 | } | ||
| 468 | |||
| 453 | /* Fixup wrong class code in p7ioc and p8 root complex */ | 469 | /* Fixup wrong class code in p7ioc and p8 root complex */ |
| 454 | static void pnv_p7ioc_rc_quirk(struct pci_dev *dev) | 470 | static void pnv_p7ioc_rc_quirk(struct pci_dev *dev) |
| 455 | { | 471 | { |
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); | |||
| 158 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); | 159 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); |
| 159 | extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, | 160 | extern 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 |
| 11 | extern void pnv_pci_init(void); | 11 | extern void pnv_pci_init(void); |
| 12 | extern void pnv_pci_shutdown(void); | ||
| 12 | #else | 13 | #else |
| 13 | static inline void pnv_pci_init(void) { } | 14 | static inline void pnv_pci_init(void) { } |
| 15 | static 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..d4459bfc92f7 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
| @@ -78,7 +78,9 @@ static void pnv_show_cpuinfo(struct seq_file *m) | |||
| 78 | if (root) | 78 | if (root) |
| 79 | model = of_get_property(root, "model", NULL); | 79 | model = of_get_property(root, "model", NULL); |
| 80 | seq_printf(m, "machine\t\t: PowerNV %s\n", model); | 80 | seq_printf(m, "machine\t\t: PowerNV %s\n", model); |
| 81 | if (firmware_has_feature(FW_FEATURE_OPALv2)) | 81 | if (firmware_has_feature(FW_FEATURE_OPALv3)) |
| 82 | seq_printf(m, "firmware\t: OPAL v3\n"); | ||
| 83 | else if (firmware_has_feature(FW_FEATURE_OPALv2)) | ||
| 82 | seq_printf(m, "firmware\t: OPAL v2\n"); | 84 | seq_printf(m, "firmware\t: OPAL v2\n"); |
| 83 | else if (firmware_has_feature(FW_FEATURE_OPAL)) | 85 | else if (firmware_has_feature(FW_FEATURE_OPAL)) |
| 84 | seq_printf(m, "firmware\t: OPAL v1\n"); | 86 | seq_printf(m, "firmware\t: OPAL v1\n"); |
| @@ -126,6 +128,17 @@ static void pnv_progress(char *s, unsigned short hex) | |||
| 126 | { | 128 | { |
| 127 | } | 129 | } |
| 128 | 130 | ||
| 131 | static void pnv_shutdown(void) | ||
| 132 | { | ||
| 133 | /* Let the PCI code clear up IODA tables */ | ||
| 134 | pnv_pci_shutdown(); | ||
| 135 | |||
| 136 | /* And unregister all OPAL interrupts so they don't fire | ||
| 137 | * up while we kexec | ||
| 138 | */ | ||
| 139 | opal_shutdown(); | ||
| 140 | } | ||
| 141 | |||
| 129 | #ifdef CONFIG_KEXEC | 142 | #ifdef CONFIG_KEXEC |
| 130 | static void pnv_kexec_cpu_down(int crash_shutdown, int secondary) | 143 | static void pnv_kexec_cpu_down(int crash_shutdown, int secondary) |
| 131 | { | 144 | { |
| @@ -187,6 +200,7 @@ define_machine(powernv) { | |||
| 187 | .init_IRQ = pnv_init_IRQ, | 200 | .init_IRQ = pnv_init_IRQ, |
| 188 | .show_cpuinfo = pnv_show_cpuinfo, | 201 | .show_cpuinfo = pnv_show_cpuinfo, |
| 189 | .progress = pnv_progress, | 202 | .progress = pnv_progress, |
| 203 | .machine_shutdown = pnv_shutdown, | ||
| 190 | .power_save = power7_idle, | 204 | .power_save = power7_idle, |
| 191 | .calibrate_decr = generic_calibrate_decr, | 205 | .calibrate_decr = generic_calibrate_decr, |
| 192 | #ifdef CONFIG_KEXEC | 206 | #ifdef CONFIG_KEXEC |
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index 6a3ecca5b725..88c9459c3e07 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c | |||
| @@ -71,18 +71,68 @@ int pnv_smp_kick_cpu(int nr) | |||
| 71 | 71 | ||
| 72 | BUG_ON(nr < 0 || nr >= NR_CPUS); | 72 | BUG_ON(nr < 0 || nr >= NR_CPUS); |
| 73 | 73 | ||
| 74 | /* On OPAL v2 the CPU are still spinning inside OPAL itself, | 74 | /* |
| 75 | * get them back now | 75 | * If we already started or OPALv2 is not supported, we just |
| 76 | * kick the CPU via the PACA | ||
| 76 | */ | 77 | */ |
| 77 | if (!paca[nr].cpu_start && firmware_has_feature(FW_FEATURE_OPALv2)) { | 78 | if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPALv2)) |
| 78 | pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu); | 79 | goto kick; |
| 79 | rc = opal_start_cpu(pcpu, start_here); | 80 | |
| 81 | /* | ||
| 82 | * At this point, the CPU can either be spinning on the way in | ||
| 83 | * from kexec or be inside OPAL waiting to be started for the | ||
| 84 | * first time. OPAL v3 allows us to query OPAL to know if it | ||
| 85 | * has the CPUs, so we do that | ||
| 86 | */ | ||
| 87 | if (firmware_has_feature(FW_FEATURE_OPALv3)) { | ||
| 88 | uint8_t status; | ||
| 89 | |||
| 90 | rc = opal_query_cpu_status(pcpu, &status); | ||
| 80 | if (rc != OPAL_SUCCESS) { | 91 | if (rc != OPAL_SUCCESS) { |
| 81 | pr_warn("OPAL Error %ld starting CPU %d\n", | 92 | pr_warn("OPAL Error %ld querying CPU %d state\n", |
| 82 | rc, nr); | 93 | rc, nr); |
| 83 | return -ENODEV; | 94 | return -ENODEV; |
| 84 | } | 95 | } |
| 96 | |||
| 97 | /* | ||
| 98 | * Already started, just kick it, probably coming from | ||
| 99 | * kexec and spinning | ||
| 100 | */ | ||
| 101 | if (status == OPAL_THREAD_STARTED) | ||
| 102 | goto kick; | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Available/inactive, let's kick it | ||
| 106 | */ | ||
| 107 | if (status == OPAL_THREAD_INACTIVE) { | ||
| 108 | pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", | ||
| 109 | nr, pcpu); | ||
| 110 | rc = opal_start_cpu(pcpu, start_here); | ||
| 111 | if (rc != OPAL_SUCCESS) { | ||
| 112 | pr_warn("OPAL Error %ld starting CPU %d\n", | ||
| 113 | rc, nr); | ||
| 114 | return -ENODEV; | ||
| 115 | } | ||
| 116 | } else { | ||
| 117 | /* | ||
| 118 | * An unavailable CPU (or any other unknown status) | ||
| 119 | * shouldn't be started. It should also | ||
| 120 | * not be in the possible map but currently it can | ||
| 121 | * happen | ||
| 122 | */ | ||
| 123 | pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable" | ||
| 124 | " (status %d)...\n", nr, pcpu, status); | ||
| 125 | return -ENODEV; | ||
| 126 | } | ||
| 127 | } else { | ||
| 128 | /* | ||
| 129 | * On OPAL v2, we just kick it and hope for the best, | ||
| 130 | * we must not test the error from opal_start_cpu() or | ||
| 131 | * we would fail to get CPUs from kexec. | ||
| 132 | */ | ||
| 133 | opal_start_cpu(pcpu, start_here); | ||
| 85 | } | 134 | } |
| 135 | kick: | ||
| 86 | return smp_generic_kick_cpu(nr); | 136 | return smp_generic_kick_cpu(nr); |
| 87 | } | 137 | } |
| 88 | 138 | ||
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 9a0941bc4d31..023b288f895b 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
| @@ -18,6 +18,7 @@ config PPC_PSERIES | |||
| 18 | select PPC_PCI_CHOICE if EXPERT | 18 | select PPC_PCI_CHOICE if EXPERT |
| 19 | select ZLIB_DEFLATE | 19 | select ZLIB_DEFLATE |
| 20 | select PPC_DOORBELL | 20 | select PPC_DOORBELL |
| 21 | select HAVE_CONTEXT_TRACKING | ||
| 21 | default y | 22 | default y |
| 22 | 23 | ||
| 23 | config PPC_SPLPAR | 24 | config PPC_SPLPAR |
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index 420524e6f8c9..6d2f0abce6fa 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c | |||
| @@ -26,26 +26,6 @@ static int query_token, change_token; | |||
| 26 | #define RTAS_CHANGE_MSIX_FN 4 | 26 | #define RTAS_CHANGE_MSIX_FN 4 |
| 27 | #define RTAS_CHANGE_32MSI_FN 5 | 27 | #define RTAS_CHANGE_32MSI_FN 5 |
| 28 | 28 | ||
| 29 | static struct pci_dn *get_pdn(struct pci_dev *pdev) | ||
| 30 | { | ||
| 31 | struct device_node *dn; | ||
| 32 | struct pci_dn *pdn; | ||
| 33 | |||
| 34 | dn = pci_device_to_OF_node(pdev); | ||
| 35 | if (!dn) { | ||
| 36 | dev_dbg(&pdev->dev, "rtas_msi: No OF device node\n"); | ||
| 37 | return NULL; | ||
| 38 | } | ||
| 39 | |||
| 40 | pdn = PCI_DN(dn); | ||
| 41 | if (!pdn) { | ||
| 42 | dev_dbg(&pdev->dev, "rtas_msi: No PCI DN\n"); | ||
| 43 | return NULL; | ||
| 44 | } | ||
| 45 | |||
| 46 | return pdn; | ||
| 47 | } | ||
| 48 | |||
| 49 | /* RTAS Helpers */ | 29 | /* RTAS Helpers */ |
| 50 | 30 | ||
| 51 | static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) | 31 | static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) |
| @@ -91,7 +71,7 @@ static void rtas_disable_msi(struct pci_dev *pdev) | |||
| 91 | { | 71 | { |
| 92 | struct pci_dn *pdn; | 72 | struct pci_dn *pdn; |
| 93 | 73 | ||
| 94 | pdn = get_pdn(pdev); | 74 | pdn = pci_get_pdn(pdev); |
| 95 | if (!pdn) | 75 | if (!pdn) |
| 96 | return; | 76 | return; |
| 97 | 77 | ||
| @@ -152,7 +132,7 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name) | |||
| 152 | struct pci_dn *pdn; | 132 | struct pci_dn *pdn; |
| 153 | const u32 *req_msi; | 133 | const u32 *req_msi; |
| 154 | 134 | ||
| 155 | pdn = get_pdn(pdev); | 135 | pdn = pci_get_pdn(pdev); |
| 156 | if (!pdn) | 136 | if (!pdn) |
| 157 | return -ENODEV; | 137 | return -ENODEV; |
| 158 | 138 | ||
| @@ -394,6 +374,23 @@ static int check_msix_entries(struct pci_dev *pdev) | |||
| 394 | return 0; | 374 | return 0; |
| 395 | } | 375 | } |
| 396 | 376 | ||
| 377 | static void rtas_hack_32bit_msi_gen2(struct pci_dev *pdev) | ||
| 378 | { | ||
| 379 | u32 addr_hi, addr_lo; | ||
| 380 | |||
| 381 | /* | ||
| 382 | * We should only get in here for IODA1 configs. This is based on the | ||
| 383 | * fact that we using RTAS for MSIs, we don't have the 32 bit MSI RTAS | ||
| 384 | * support, and we are in a PCIe Gen2 slot. | ||
| 385 | */ | ||
| 386 | dev_info(&pdev->dev, | ||
| 387 | "rtas_msi: No 32 bit MSI firmware support, forcing 32 bit MSI\n"); | ||
| 388 | pci_read_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI, &addr_hi); | ||
| 389 | addr_lo = 0xffff0000 | ((addr_hi >> (48 - 32)) << 4); | ||
| 390 | pci_write_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_LO, addr_lo); | ||
| 391 | pci_write_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI, 0); | ||
| 392 | } | ||
| 393 | |||
| 397 | static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) | 394 | static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) |
| 398 | { | 395 | { |
| 399 | struct pci_dn *pdn; | 396 | struct pci_dn *pdn; |
| @@ -401,8 +398,9 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) | |||
| 401 | struct msi_desc *entry; | 398 | struct msi_desc *entry; |
| 402 | struct msi_msg msg; | 399 | struct msi_msg msg; |
| 403 | int nvec = nvec_in; | 400 | int nvec = nvec_in; |
| 401 | int use_32bit_msi_hack = 0; | ||
| 404 | 402 | ||
| 405 | pdn = get_pdn(pdev); | 403 | pdn = pci_get_pdn(pdev); |
| 406 | if (!pdn) | 404 | if (!pdn) |
| 407 | return -ENODEV; | 405 | return -ENODEV; |
| 408 | 406 | ||
| @@ -428,15 +426,31 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) | |||
| 428 | */ | 426 | */ |
| 429 | again: | 427 | again: |
| 430 | if (type == PCI_CAP_ID_MSI) { | 428 | if (type == PCI_CAP_ID_MSI) { |
| 431 | if (pdn->force_32bit_msi) | 429 | if (pdn->force_32bit_msi) { |
| 432 | rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec); | 430 | rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec); |
| 433 | else | 431 | if (rc < 0) { |
| 432 | /* | ||
| 433 | * We only want to run the 32 bit MSI hack below if | ||
| 434 | * the max bus speed is Gen2 speed | ||
| 435 | */ | ||
| 436 | if (pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) | ||
| 437 | return rc; | ||
| 438 | |||
| 439 | use_32bit_msi_hack = 1; | ||
| 440 | } | ||
| 441 | } else | ||
| 442 | rc = -1; | ||
| 443 | |||
| 444 | if (rc < 0) | ||
| 434 | rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); | 445 | rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); |
| 435 | 446 | ||
| 436 | if (rc < 0 && !pdn->force_32bit_msi) { | 447 | if (rc < 0) { |
| 437 | pr_debug("rtas_msi: trying the old firmware call.\n"); | 448 | pr_debug("rtas_msi: trying the old firmware call.\n"); |
| 438 | rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); | 449 | rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); |
| 439 | } | 450 | } |
| 451 | |||
| 452 | if (use_32bit_msi_hack && rc > 0) | ||
| 453 | rtas_hack_32bit_msi_gen2(pdev); | ||
| 440 | } else | 454 | } else |
| 441 | rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec); | 455 | rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec); |
| 442 | 456 | ||
| @@ -518,12 +532,3 @@ static int rtas_msi_init(void) | |||
| 518 | } | 532 | } |
| 519 | arch_initcall(rtas_msi_init); | 533 | arch_initcall(rtas_msi_init); |
| 520 | 534 | ||
| 521 | static void quirk_radeon(struct pci_dev *dev) | ||
| 522 | { | ||
| 523 | struct pci_dn *pdn = get_pdn(dev); | ||
| 524 | |||
| 525 | if (pdn) | ||
| 526 | pdn->force_32bit_msi = 1; | ||
| 527 | } | ||
| 528 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon); | ||
| 529 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon); | ||
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c index 47226e04126d..5f997e79d570 100644 --- a/arch/powerpc/platforms/pseries/suspend.c +++ b/arch/powerpc/platforms/pseries/suspend.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/cpu.h> | ||
| 19 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
| 20 | #include <linux/suspend.h> | 21 | #include <linux/suspend.h> |
| 21 | #include <linux/stat.h> | 22 | #include <linux/stat.h> |
| @@ -126,11 +127,15 @@ static ssize_t store_hibernate(struct device *dev, | |||
| 126 | struct device_attribute *attr, | 127 | struct device_attribute *attr, |
| 127 | const char *buf, size_t count) | 128 | const char *buf, size_t count) |
| 128 | { | 129 | { |
| 130 | cpumask_var_t offline_mask; | ||
| 129 | int rc; | 131 | int rc; |
| 130 | 132 | ||
| 131 | if (!capable(CAP_SYS_ADMIN)) | 133 | if (!capable(CAP_SYS_ADMIN)) |
| 132 | return -EPERM; | 134 | return -EPERM; |
| 133 | 135 | ||
| 136 | if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY)) | ||
| 137 | return -ENOMEM; | ||
| 138 | |||
| 134 | stream_id = simple_strtoul(buf, NULL, 16); | 139 | stream_id = simple_strtoul(buf, NULL, 16); |
| 135 | 140 | ||
| 136 | do { | 141 | do { |
| @@ -140,15 +145,32 @@ static ssize_t store_hibernate(struct device *dev, | |||
| 140 | } while (rc == -EAGAIN); | 145 | } while (rc == -EAGAIN); |
| 141 | 146 | ||
| 142 | if (!rc) { | 147 | if (!rc) { |
| 148 | /* All present CPUs must be online */ | ||
| 149 | cpumask_andnot(offline_mask, cpu_present_mask, | ||
| 150 | cpu_online_mask); | ||
| 151 | rc = rtas_online_cpus_mask(offline_mask); | ||
| 152 | if (rc) { | ||
| 153 | pr_err("%s: Could not bring present CPUs online.\n", | ||
| 154 | __func__); | ||
| 155 | goto out; | ||
| 156 | } | ||
| 157 | |||
| 143 | stop_topology_update(); | 158 | stop_topology_update(); |
| 144 | rc = pm_suspend(PM_SUSPEND_MEM); | 159 | rc = pm_suspend(PM_SUSPEND_MEM); |
| 145 | start_topology_update(); | 160 | start_topology_update(); |
| 161 | |||
| 162 | /* Take down CPUs not online prior to suspend */ | ||
| 163 | if (!rtas_offline_cpus_mask(offline_mask)) | ||
| 164 | pr_warn("%s: Could not restore CPUs to offline " | ||
| 165 | "state.\n", __func__); | ||
| 146 | } | 166 | } |
| 147 | 167 | ||
| 148 | stream_id = 0; | 168 | stream_id = 0; |
| 149 | 169 | ||
| 150 | if (!rc) | 170 | if (!rc) |
| 151 | rc = count; | 171 | rc = count; |
| 172 | out: | ||
| 173 | free_cpumask_var(offline_mask); | ||
| 152 | return rc; | 174 | return rc; |
| 153 | } | 175 | } |
| 154 | 176 | ||
diff --git a/arch/powerpc/platforms/wsp/ics.c b/arch/powerpc/platforms/wsp/ics.c index 97fe82ee8633..2d3b1dd9571d 100644 --- a/arch/powerpc/platforms/wsp/ics.c +++ b/arch/powerpc/platforms/wsp/ics.c | |||
| @@ -361,7 +361,7 @@ static int wsp_chip_set_affinity(struct irq_data *d, | |||
| 361 | xive = xive_set_server(xive, get_irq_server(ics, hw_irq)); | 361 | xive = xive_set_server(xive, get_irq_server(ics, hw_irq)); |
| 362 | wsp_ics_set_xive(ics, hw_irq, xive); | 362 | wsp_ics_set_xive(ics, hw_irq, xive); |
| 363 | 363 | ||
| 364 | return 0; | 364 | return IRQ_SET_MASK_OK; |
| 365 | } | 365 | } |
| 366 | 366 | ||
| 367 | static struct irq_chip wsp_irq_chip = { | 367 | static struct irq_chip wsp_irq_chip = { |
