aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@huawei.com>2012-08-22 11:16:45 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-09-24 17:48:37 -0400
commit5ba113f7c4fb06cfdd6cba92353ac55ad5b81b75 (patch)
treedb348ed48ef708f2abc7ba4daa9ac116f18974f0
parent479e0d485eaab452cf248cd1a9520015023b35b2 (diff)
PCI: acpiphp: Handle PCIe ports without native hotplug capability
Commit 0d52f54e2ef64c189dedc332e680b2eb4a34590a (PCI / ACPI: Make acpiphp ignore root bridges using PCIe native hotplug) added code that made the acpiphp driver completely ignore PCIe root complexes for which the kernel had been granted control of the native PCIe hotplug feature by the BIOS through _OSC. Later commit 619a5182d1f38a3d629ee48e04fa182ef9170052 "PCI hotplug: Always allow acpiphp to handle non-PCIe bridges" relaxed the constraints to allow acpiphp driver handle non-PCIe bridges under such a complex. The constraint needs to be relaxed further to allow acpiphp driver to handle PCIe ports without native PCIe hotplug capability. Some MR-IOV switch chipsets, such PLX8696, support multiple virtual PCIe switches and may migrate downstream ports among virtual switches. To migrate a downstream port from the source virtual switch to the target, the port needs to be hot-removed from the source and hot-added into the target. The pciehp driver can't be used here because there are no slots within the virtual PCIe switch. So acpiphp driver is used to support downstream port migration. A typical configuration is as below: [Root without native PCIe HP] [Upstream port of vswitch without native PCIe HP] [Downstream port of vswitch with native PCIe HP] [PCIe endpoint] Here acpiphp driver will be used to handle root ports and upstream port in the virtual switch, and pciehp driver will be used to handle downstream ports in the virtual switch. Signed-off-by: Jiang Liu <liuj97@gmail.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index ad6fd669549..e6da3927c49 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -115,6 +115,35 @@ static const struct acpi_dock_ops acpiphp_dock_ops = {
115 .handler = handle_hotplug_event_func, 115 .handler = handle_hotplug_event_func,
116}; 116};
117 117
118/* Check whether the PCI device is managed by native PCIe hotplug driver */
119static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)
120{
121 u32 reg32;
122 acpi_handle tmp;
123 struct acpi_pci_root *root;
124
125 /* Check whether the PCIe port supports native PCIe hotplug */
126 if (pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &reg32))
127 return false;
128 if (!(reg32 & PCI_EXP_SLTCAP_HPC))
129 return false;
130
131 /*
132 * Check whether native PCIe hotplug has been enabled for
133 * this PCIe hierarchy.
134 */
135 tmp = acpi_find_root_bridge_handle(pdev);
136 if (!tmp)
137 return false;
138 root = acpi_pci_find_root(tmp);
139 if (!root)
140 return false;
141 if (!(root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
142 return false;
143
144 return true;
145}
146
118/* callback routine to register each ACPI PCI slot object */ 147/* callback routine to register each ACPI PCI slot object */
119static acpi_status 148static acpi_status
120register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) 149register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
@@ -142,16 +171,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
142 function = adr & 0xffff; 171 function = adr & 0xffff;
143 172
144 pdev = pbus->self; 173 pdev = pbus->self;
145 if (pdev && pci_is_pcie(pdev)) { 174 if (pdev && device_is_managed_by_native_pciehp(pdev))
146 tmp = acpi_find_root_bridge_handle(pdev); 175 return AE_OK;
147 if (tmp) {
148 struct acpi_pci_root *root = acpi_pci_find_root(tmp);
149
150 if (root && (root->osc_control_set &
151 OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
152 return AE_OK;
153 }
154 }
155 176
156 newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); 177 newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
157 if (!newfunc) 178 if (!newfunc)