From 774d446b0f9222f46772dde8770d7c1c169c0284 Mon Sep 17 00:00:00 2001
From: Lukas Wunner <lukas@wunner.de>
Date: Thu, 19 Jul 2018 17:27:43 -0500
Subject: [PATCH] PCI: pciehp: Publish to user space last on probe
Git-commit: 774d446b0f9222f46772dde8770d7c1c169c0284
Patch-mainline: v4.19
References: FATE#326303
The PCI hotplug core has just been refactored to separate slot
initialization for in-kernel use from publication to user space.
Take advantage of it in pciehp by publishing to user space last on
probe. This will allow enable/disablement of the slot exclusively from
the IRQ thread because the IRQ is requested after initialization for
in-kernel use (thereby getting its unique name needed by the IRQ thread)
but before user space is able to submit enable/disable requests.
On teardown, the order is the same in reverse: The user space interface
is removed prior to freeing the IRQ and destroying the slot.
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
drivers/pci/hotplug/pciehp_core.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -114,10 +114,10 @@ static int init_slot(struct controller *
slot->hotplug_slot = hotplug;
snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl));
- retval = pci_hp_register(hotplug,
- ctrl->pcie->port->subordinate, 0, name);
+ retval = pci_hp_initialize(hotplug,
+ ctrl->pcie->port->subordinate, 0, name);
if (retval)
- ctrl_err(ctrl, "pci_hp_register failed: error %d\n", retval);
+ ctrl_err(ctrl, "pci_hp_initialize failed: error %d\n", retval);
out:
if (retval) {
kfree(ops);
@@ -131,7 +131,7 @@ static void cleanup_slot(struct controll
{
struct hotplug_slot *hotplug_slot = ctrl->slot->hotplug_slot;
- pci_hp_deregister(hotplug_slot);
+ pci_hp_destroy(hotplug_slot);
kfree(hotplug_slot->ops);
kfree(hotplug_slot->info);
kfree(hotplug_slot);
@@ -245,8 +245,15 @@ static int pciehp_probe(struct pcie_devi
goto err_out_free_ctrl_slot;
}
- /* Check if slot is occupied */
+ /* Publish to user space */
slot = ctrl->slot;
+ rc = pci_hp_add(slot->hotplug_slot);
+ if (rc) {
+ ctrl_err(ctrl, "Publication to user space failed (%d)\n", rc);
+ goto err_out_shutdown_notification;
+ }
+
+ /* Check if slot is occupied */
pciehp_get_adapter_status(slot, &occupied);
pciehp_get_power_status(slot, &poweron);
if (occupied && pciehp_force)
@@ -257,6 +264,8 @@ static int pciehp_probe(struct pcie_devi
return 0;
+err_out_shutdown_notification:
+ pcie_shutdown_notification(ctrl);
err_out_free_ctrl_slot:
cleanup_slot(ctrl);
err_out_release_ctlr:
@@ -268,6 +277,7 @@ static void pciehp_remove(struct pcie_de
{
struct controller *ctrl = get_service_data(dev);
+ pci_hp_del(ctrl->slot->hotplug_slot);
pcie_shutdown_notification(ctrl);
cleanup_slot(ctrl);
pciehp_release_ctrl(ctrl);