aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/pci-common.c
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 /arch/powerpc/kernel/pci-common.c
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>
Diffstat (limited to 'arch/powerpc/kernel/pci-common.c')
-rw-r--r--arch/powerpc/kernel/pci-common.c20
1 files changed, 20 insertions, 0 deletions
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