aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-04-24 04:00:24 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-04-28 03:34:53 -0400
commitd92a208d086063ecc785b4588f74ab42268cbc4b (patch)
tree07189bb010c1d9443a0fee736268cfcbf965dfd3
parent26833a5029b710b12f00607fa255ce86909836ad (diff)
powerpc/pci: Mask linkDown on resetting PCI bus
The problem was initially reported by Wendy who tried pass through IPR adapter, which was connected to PHB root port directly, to KVM based guest. When doing that, pci_reset_bridge_secondary_bus() was called by VFIO driver and linkDown was detected by the root port. That caused all PEs to be frozen. The patch fixes the issue by routing the reset for the secondary bus of root port to underly firmware. For that, one more weak function pci_reset_secondary_bus() is introduced so that the individual platforms can override that and do specific reset for bridge's secondary bus. Reported-by: Wendy Xiong <wenxiong@linux.vnet.ibm.com> Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/machdep.h3
-rw-r--r--arch/powerpc/kernel/pci-common.c20
-rw-r--r--arch/powerpc/platforms/powernv/eeh-ioda.c38
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c1
-rw-r--r--arch/powerpc/platforms/powernv/pci.h1
-rw-r--r--drivers/pci/pci.c21
6 files changed, 74 insertions, 10 deletions
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 5b6c03f1058f..240b137ce0cf 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -241,6 +241,9 @@ struct machdep_calls {
241 /* Called during PCI resource reassignment */ 241 /* Called during PCI resource reassignment */
242 resource_size_t (*pcibios_window_alignment)(struct pci_bus *, unsigned long type); 242 resource_size_t (*pcibios_window_alignment)(struct pci_bus *, unsigned long type);
243 243
244 /* Reset the secondary bus of bridge */
245 void (*pcibios_reset_secondary_bus)(struct pci_dev *dev);
246
244 /* Called to shutdown machine specific hardware not already controlled 247 /* Called to shutdown machine specific hardware not already controlled
245 * by other drivers. 248 * by other drivers.
246 */ 249 */
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index d9476c1fc959..f9ca5091840c 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -21,6 +21,7 @@
21#include <linux/string.h> 21#include <linux/string.h>
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/bootmem.h> 23#include <linux/bootmem.h>
24#include <linux/delay.h>
24#include <linux/export.h> 25#include <linux/export.h>
25#include <linux/of_address.h> 26#include <linux/of_address.h>
26#include <linux/of_pci.h> 27#include <linux/of_pci.h>
@@ -120,6 +121,25 @@ resource_size_t pcibios_window_alignment(struct pci_bus *bus,
120 return 1; 121 return 1;
121} 122}
122 123
124void pcibios_reset_secondary_bus(struct pci_dev *dev)
125{
126 u16 ctrl;
127
128 if (ppc_md.pcibios_reset_secondary_bus) {
129 ppc_md.pcibios_reset_secondary_bus(dev);
130 return;
131 }
132
133 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl);
134 ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
135 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
136 msleep(2);
137
138 ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
139 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
140 ssleep(1);
141}
142
123static resource_size_t pcibios_io_size(const struct pci_controller *hose) 143static resource_size_t pcibios_io_size(const struct pci_controller *hose)
124{ 144{
125#ifdef CONFIG_PPC64 145#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 268cd46af8f1..58ef80987eed 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -474,6 +474,8 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option)
474 474
475{ 475{
476 struct device_node *dn = pci_device_to_OF_node(dev); 476 struct device_node *dn = pci_device_to_OF_node(dev);
477 struct eeh_dev *edev = of_node_to_eeh_dev(dn);
478 int aer = edev ? edev->aer_cap : 0;
477 u32 ctrl; 479 u32 ctrl;
478 480
479 pr_debug("%s: Reset PCI bus %04x:%02x with option %d\n", 481 pr_debug("%s: Reset PCI bus %04x:%02x with option %d\n",
@@ -483,24 +485,56 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option)
483 switch (option) { 485 switch (option) {
484 case EEH_RESET_FUNDAMENTAL: 486 case EEH_RESET_FUNDAMENTAL:
485 case EEH_RESET_HOT: 487 case EEH_RESET_HOT:
488 /* Don't report linkDown event */
489 if (aer) {
490 eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
491 4, &ctrl);
492 ctrl |= PCI_ERR_UNC_SURPDN;
493 eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
494 4, ctrl);
495 }
496
486 eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); 497 eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
487 ctrl |= PCI_BRIDGE_CTL_BUS_RESET; 498 ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
488 eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); 499 eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
489
490 msleep(EEH_PE_RST_HOLD_TIME); 500 msleep(EEH_PE_RST_HOLD_TIME);
501
491 break; 502 break;
492 case EEH_RESET_DEACTIVATE: 503 case EEH_RESET_DEACTIVATE:
493 eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); 504 eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
494 ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; 505 ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
495 eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); 506 eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
496
497 msleep(EEH_PE_RST_SETTLE_TIME); 507 msleep(EEH_PE_RST_SETTLE_TIME);
508
509 /* Continue reporting linkDown event */
510 if (aer) {
511 eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
512 4, &ctrl);
513 ctrl &= ~PCI_ERR_UNC_SURPDN;
514 eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
515 4, ctrl);
516 }
517
498 break; 518 break;
499 } 519 }
500 520
501 return 0; 521 return 0;
502} 522}
503 523
524void pnv_pci_reset_secondary_bus(struct pci_dev *dev)
525{
526 struct pci_controller *hose;
527
528 if (pci_is_root_bus(dev->bus)) {
529 hose = pci_bus_to_host(dev->bus);
530 ioda_eeh_root_reset(hose, EEH_RESET_HOT);
531 ioda_eeh_root_reset(hose, EEH_RESET_DEACTIVATE);
532 } else {
533 ioda_eeh_bridge_reset(dev, EEH_RESET_HOT);
534 ioda_eeh_bridge_reset(dev, EEH_RESET_DEACTIVATE);
535 }
536}
537
504/** 538/**
505 * ioda_eeh_reset - Reset the indicated PE 539 * ioda_eeh_reset - Reset the indicated PE
506 * @pe: EEH PE 540 * @pe: EEH PE
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 98824aa99173..a179ff00be3e 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1386,6 +1386,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
1386 ppc_md.pcibios_fixup = pnv_pci_ioda_fixup; 1386 ppc_md.pcibios_fixup = pnv_pci_ioda_fixup;
1387 ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook; 1387 ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook;
1388 ppc_md.pcibios_window_alignment = pnv_pci_window_alignment; 1388 ppc_md.pcibios_window_alignment = pnv_pci_window_alignment;
1389 ppc_md.pcibios_reset_secondary_bus = pnv_pci_reset_secondary_bus;
1389 pci_add_flags(PCI_REASSIGN_ALL_RSRC); 1390 pci_add_flags(PCI_REASSIGN_ALL_RSRC);
1390 1391
1391 /* Reset IODA tables to a clean state */ 1392 /* Reset IODA tables to a clean state */
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 39ec6978e809..34a09740aad3 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -204,5 +204,6 @@ extern void pnv_pci_init_ioda_hub(struct device_node *np);
204extern void pnv_pci_init_ioda2_phb(struct device_node *np); 204extern void pnv_pci_init_ioda2_phb(struct device_node *np);
205extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, 205extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
206 __be64 *startp, __be64 *endp, bool rm); 206 __be64 *startp, __be64 *endp, bool rm);
207extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev);
207 208
208#endif /* __POWERNV_PCI_H */ 209#endif /* __POWERNV_PCI_H */
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 7325d43bf030..633382d227f4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3167,14 +3167,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
3167 return 0; 3167 return 0;
3168} 3168}
3169 3169
3170/** 3170void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
3171 * pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge.
3172 * @dev: Bridge device
3173 *
3174 * Use the bridge control register to assert reset on the secondary bus.
3175 * Devices on the secondary bus are left in power-on state.
3176 */
3177void pci_reset_bridge_secondary_bus(struct pci_dev *dev)
3178{ 3171{
3179 u16 ctrl; 3172 u16 ctrl;
3180 3173
@@ -3199,6 +3192,18 @@ void pci_reset_bridge_secondary_bus(struct pci_dev *dev)
3199 */ 3192 */
3200 ssleep(1); 3193 ssleep(1);
3201} 3194}
3195
3196/**
3197 * pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge.
3198 * @dev: Bridge device
3199 *
3200 * Use the bridge control register to assert reset on the secondary bus.
3201 * Devices on the secondary bus are left in power-on state.
3202 */
3203void pci_reset_bridge_secondary_bus(struct pci_dev *dev)
3204{
3205 pcibios_reset_secondary_bus(dev);
3206}
3202EXPORT_SYMBOL_GPL(pci_reset_bridge_secondary_bus); 3207EXPORT_SYMBOL_GPL(pci_reset_bridge_secondary_bus);
3203 3208
3204static int pci_parent_bus_reset(struct pci_dev *dev, int probe) 3209static int pci_parent_bus_reset(struct pci_dev *dev, int probe)