Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/831131/?format=api
{ "id": 831131, "url": "http://patchwork.ozlabs.org/api/1.2/patches/831131/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/patch/20171027072612.26565-7-jeffy.chen@rock-chips.com/", "project": { "id": 28, "url": "http://patchwork.ozlabs.org/api/1.2/projects/28/?format=api", "name": "Linux PCI development", "link_name": "linux-pci", "list_id": "linux-pci.vger.kernel.org", "list_email": "linux-pci@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20171027072612.26565-7-jeffy.chen@rock-chips.com>", "list_archive_url": null, "date": "2017-10-27T07:26:11", "name": "[RFC,v10,6/7] PCI / PM: Move acpi wakeup code to pci core", "commit_ref": null, "pull_url": null, "state": "not-applicable", "archived": false, "hash": "98ad1fefbd9d824a288bb30854647e07e782972b", "submitter": { "id": 67754, "url": "http://patchwork.ozlabs.org/api/1.2/people/67754/?format=api", "name": "Jeffy Chen", "email": "jeffy.chen@rock-chips.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-pci/patch/20171027072612.26565-7-jeffy.chen@rock-chips.com/mbox/", "series": [ { "id": 10523, "url": "http://patchwork.ozlabs.org/api/1.2/series/10523/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/list/?series=10523", "date": "2017-10-27T07:26:06", "name": "PCI: rockchip: Move PCIe WAKE# handling into pci core", "version": 10, "mbox": "http://patchwork.ozlabs.org/series/10523/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/831131/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/831131/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<linux-pci-owner@vger.kernel.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=linux-pci-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3yNb7t2KDXz9t2x\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 27 Oct 2017 18:28:10 +1100 (AEDT)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1752218AbdJ0H1b (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tFri, 27 Oct 2017 03:27:31 -0400", "from regular1.263xmail.com ([211.150.99.141]:48907 \"EHLO\n\tregular1.263xmail.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751072AbdJ0H10 (ORCPT\n\t<rfc822; linux-pci@vger.kernel.org>); Fri, 27 Oct 2017 03:27:26 -0400", "from jeffy.chen?rock-chips.com (unknown [192.168.167.161])\n\tby regular1.263xmail.com (Postfix) with ESMTP id B62D46C;\n\tFri, 27 Oct 2017 15:27:22 +0800 (CST)", "from localhost (localhost [127.0.0.1])\n\tby smtp.263.net (Postfix) with ESMTPA id E45ED393;\n\tFri, 27 Oct 2017 15:27:15 +0800 (CST)", "from localhost (unknown [103.29.142.67])\n\tby smtp.263.net (Postfix) whith ESMTP id 14555HINT57;\n\tFri, 27 Oct 2017 15:27:21 +0800 (CST)" ], "X-263anti-spam": "KSV:0;", "X-MAIL-GRAY": "0", "X-MAIL-DELIVERY": "1", "X-KSVirus-check": "0", "X-ABS-CHECKED": "4", "X-RL-SENDER": "jeffy.chen@rock-chips.com", "X-FST-TO": "linux-kernel@vger.kernel.org", "X-SENDER-IP": "103.29.142.67", "X-LOGIN-NAME": "jeffy.chen@rock-chips.com", "X-UNIQUE-TAG": "<acf560d6ca7ad6cdccba6507e7696065>", "X-ATTACHMENT-NUM": "0", "X-SENDER": "cjf@rock-chips.com", "X-DNS-TYPE": "0", "From": "Jeffy Chen <jeffy.chen@rock-chips.com>", "To": "linux-kernel@vger.kernel.org, bhelgaas@google.com", "Cc": "linux-pm@vger.kernel.org, tony@atomide.com,\n\tshawn.lin@rock-chips.com, briannorris@chromium.org,\n\trjw@rjwysocki.net, dianders@chromium.org,\n\tJeffy Chen <jeffy.chen@rock-chips.com>,\n\tlinux-pci@vger.kernel.org, linux-acpi@vger.kernel.org,\n\tLen Brown <lenb@kernel.org>", "Subject": "[RFC PATCH v10 6/7] PCI / PM: Move acpi wakeup code to pci core", "Date": "Fri, 27 Oct 2017 15:26:11 +0800", "Message-Id": "<20171027072612.26565-7-jeffy.chen@rock-chips.com>", "X-Mailer": "git-send-email 2.11.0", "In-Reply-To": "<20171027072612.26565-1-jeffy.chen@rock-chips.com>", "References": "<20171027072612.26565-1-jeffy.chen@rock-chips.com>", "Sender": "linux-pci-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<linux-pci.vger.kernel.org>", "X-Mailing-List": "linux-pci@vger.kernel.org" }, "content": "Move acpi wakeup code to pci core as pci_set_wakeup(), so that other\nplatforms could reuse it.\n\nAlso add .setup_dev() / .setup_host_bridge() / .cleanup() platform pm\nops's callbacks to setup and cleanup pci devices and host bridge for\nwakeup.\n\nSigned-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>\n---\n\nChanges in v10: None\nChanges in v9: None\nChanges in v8: None\nChanges in v7: None\nChanges in v6: None\nChanges in v5: None\nChanges in v3: None\nChanges in v2: None\n\n drivers/pci/pci-acpi.c | 121 +++++++++++++++++++++++------------------------\n drivers/pci/pci-driver.c | 9 ++++\n drivers/pci/pci.c | 84 ++++++++++++++++++++++++++++----\n drivers/pci/pci.h | 28 +++++++++--\n drivers/pci/probe.c | 12 ++++-\n drivers/pci/remove.c | 2 +\n include/linux/pci.h | 2 +\n 7 files changed, 180 insertions(+), 78 deletions(-)", "diff": "diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c\nindex 4708eb9df71b..ee96e7afe1ac 100644\n--- a/drivers/pci/pci-acpi.c\n+++ b/drivers/pci/pci-acpi.c\n@@ -569,31 +569,6 @@ static pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)\n \treturn state_conv[state];\n }\n \n-static int acpi_pci_propagate_wakeup(struct pci_bus *bus, bool enable)\n-{\n-\twhile (bus->parent) {\n-\t\tif (acpi_pm_device_can_wakeup(&bus->self->dev))\n-\t\t\treturn acpi_pm_set_bridge_wakeup(&bus->self->dev, enable);\n-\n-\t\tbus = bus->parent;\n-\t}\n-\n-\t/* We have reached the root bus. */\n-\tif (bus->bridge) {\n-\t\tif (acpi_pm_device_can_wakeup(bus->bridge))\n-\t\t\treturn acpi_pm_set_bridge_wakeup(bus->bridge, enable);\n-\t}\n-\treturn 0;\n-}\n-\n-static int acpi_pci_wakeup(struct pci_dev *dev, bool enable)\n-{\n-\tif (acpi_pm_device_can_wakeup(&dev->dev))\n-\t\treturn acpi_pm_set_device_wakeup(&dev->dev, enable);\n-\n-\treturn acpi_pci_propagate_wakeup(dev->bus, enable);\n-}\n-\n static bool acpi_pci_need_resume(struct pci_dev *dev)\n {\n \tstruct acpi_device *adev = ACPI_COMPANION(&dev->dev);\n@@ -610,14 +585,29 @@ static bool acpi_pci_need_resume(struct pci_dev *dev)\n \treturn !!adev->power.flags.dsw_present;\n }\n \n-static const struct pci_platform_pm_ops acpi_pci_platform_pm = {\n-\t.is_manageable = acpi_pci_power_manageable,\n-\t.set_state = acpi_pci_set_power_state,\n-\t.get_state = acpi_pci_get_power_state,\n-\t.choose_state = acpi_pci_choose_state,\n-\t.set_wakeup = acpi_pci_wakeup,\n-\t.need_resume = acpi_pci_need_resume,\n-};\n+static bool acpi_pci_can_wakeup(void *pmdata)\n+{\n+\tstruct device *dev = pmdata;\n+\n+\tif (!dev)\n+\t\treturn false;\n+\n+\treturn acpi_pm_device_can_wakeup(dev);\n+}\n+\n+static int acpi_pci_dev_wakeup(void *pmdata, bool enable)\n+{\n+\tstruct device *dev = pmdata;\n+\n+\treturn acpi_pm_set_device_wakeup(dev, enable);\n+}\n+\n+static int acpi_pci_bridge_wakeup(void *pmdata, bool enable)\n+{\n+\tstruct device *dev = pmdata;\n+\n+\treturn acpi_pm_set_bridge_wakeup(dev, enable);\n+}\n \n void acpi_pci_add_bus(struct pci_bus *bus)\n {\n@@ -658,20 +648,6 @@ void acpi_pci_remove_bus(struct pci_bus *bus)\n \tacpi_pci_slot_remove(bus);\n }\n \n-/* ACPI bus type */\n-static struct acpi_device *acpi_pci_find_companion(struct device *dev)\n-{\n-\tstruct pci_dev *pci_dev = to_pci_dev(dev);\n-\tbool check_children;\n-\tu64 addr;\n-\n-\tcheck_children = pci_is_bridge(pci_dev);\n-\t/* Please ref to ACPI spec for the syntax of _ADR */\n-\taddr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);\n-\treturn acpi_find_child_device(ACPI_COMPANION(dev->parent), addr,\n-\t\t\t\t check_children);\n-}\n-\n /**\n * pci_acpi_optimize_delay - optimize PCI D3 and D3cold delay from ACPI\n * @pdev: the PCI device whose delay is to be updated\n@@ -723,34 +699,55 @@ static void pci_acpi_optimize_delay(struct pci_dev *pdev,\n \tACPI_FREE(obj);\n }\n \n-static void pci_acpi_setup(struct device *dev)\n+static void *acpi_pci_setup_dev(struct pci_dev *pci_dev)\n {\n-\tstruct pci_dev *pci_dev = to_pci_dev(dev);\n-\tstruct acpi_device *adev = ACPI_COMPANION(dev);\n+\tstruct acpi_device *adev = ACPI_COMPANION(&pci_dev->dev);\n \n \tif (!adev)\n-\t\treturn;\n+\t\treturn NULL;\n \n \tpci_acpi_optimize_delay(pci_dev, adev->handle);\n \n \tpci_acpi_add_pm_notifier(adev, pci_dev);\n \tif (!adev->wakeup.flags.valid)\n-\t\treturn;\n+\t\treturn NULL;\n+\n+\tdevice_set_wakeup_capable(&pci_dev->dev, true);\n+\tacpi_pm_set_device_wakeup(&pci_dev->dev, false);\n \n-\tdevice_set_wakeup_capable(dev, true);\n-\tacpi_pci_wakeup(pci_dev, false);\n+\treturn &pci_dev->dev;\n }\n \n-static void pci_acpi_cleanup(struct device *dev)\n+static void *acpi_pci_setup_host_bridge(struct pci_host_bridge *bridge)\n {\n-\tstruct acpi_device *adev = ACPI_COMPANION(dev);\n+\treturn &bridge->dev;\n+}\n \n-\tif (!adev)\n-\t\treturn;\n+static const struct pci_platform_pm_ops acpi_pci_platform_pm = {\n+\t.is_manageable = acpi_pci_power_manageable,\n+\t.set_state = acpi_pci_set_power_state,\n+\t.get_state = acpi_pci_get_power_state,\n+\t.choose_state = acpi_pci_choose_state,\n+\t.need_resume = acpi_pci_need_resume,\n+\t.setup_dev = acpi_pci_setup_dev,\n+\t.setup_host_bridge = acpi_pci_setup_host_bridge,\n+\t.can_wakeup = acpi_pci_can_wakeup,\n+\t.dev_wakeup = acpi_pci_dev_wakeup,\n+\t.bridge_wakeup = acpi_pci_bridge_wakeup,\n+};\n+\n+/* ACPI bus type */\n+static struct acpi_device *acpi_pci_find_companion(struct device *dev)\n+{\n+\tstruct pci_dev *pci_dev = to_pci_dev(dev);\n+\tbool check_children;\n+\tu64 addr;\n \n-\tpci_acpi_remove_pm_notifier(adev);\n-\tif (adev->wakeup.flags.valid)\n-\t\tdevice_set_wakeup_capable(dev, false);\n+\tcheck_children = pci_is_bridge(pci_dev);\n+\t/* Please ref to ACPI spec for the syntax of _ADR */\n+\taddr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);\n+\treturn acpi_find_child_device(ACPI_COMPANION(dev->parent), addr,\n+\t\t\t\t check_children);\n }\n \n static bool pci_acpi_bus_match(struct device *dev)\n@@ -762,8 +759,6 @@ static struct acpi_bus_type acpi_pci_bus = {\n \t.name = \"PCI\",\n \t.match = pci_acpi_bus_match,\n \t.find_companion = acpi_pci_find_companion,\n-\t.setup = pci_acpi_setup,\n-\t.cleanup = pci_acpi_cleanup,\n };\n \n \ndiff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c\nindex 9be563067c0c..abb7caa8a6e5 100644\n--- a/drivers/pci/pci-driver.c\n+++ b/drivers/pci/pci-driver.c\n@@ -421,10 +421,17 @@ static int pci_device_probe(struct device *dev)\n \tif (error < 0)\n \t\treturn error;\n \n+\tpci_dev->pmdata = platform_pci_setup_dev(pci_dev);\n+\tif (IS_ERR(pci_dev->pmdata)) {\n+\t\tpcibios_free_irq(pci_dev);\n+\t\treturn PTR_ERR(pci_dev->pmdata);\n+\t}\n+\n \tpci_dev_get(pci_dev);\n \tif (pci_device_can_probe(pci_dev)) {\n \t\terror = __pci_device_probe(drv, pci_dev);\n \t\tif (error) {\n+\t\t\tplatform_pci_cleanup(pci_dev->pmdata);\n \t\t\tpcibios_free_irq(pci_dev);\n \t\t\tpci_dev_put(pci_dev);\n \t\t}\n@@ -438,6 +445,8 @@ static int pci_device_remove(struct device *dev)\n \tstruct pci_dev *pci_dev = to_pci_dev(dev);\n \tstruct pci_driver *drv = pci_dev->driver;\n \n+\tplatform_pci_cleanup(pci_dev->pmdata);\n+\n \tif (drv) {\n \t\tif (drv->remove) {\n \t\t\tpm_runtime_get_sync(dev);\ndiff --git a/drivers/pci/pci.c b/drivers/pci/pci.c\nindex e120b00a9017..6add5d3209bf 100644\n--- a/drivers/pci/pci.c\n+++ b/drivers/pci/pci.c\n@@ -585,6 +585,52 @@ static inline bool platform_pci_power_manageable(struct pci_dev *dev)\n \treturn false;\n }\n \n+void *platform_pci_setup_dev(struct pci_dev *dev)\n+{\n+\tif (pci_platform_pm && pci_platform_pm->setup_dev)\n+\t\treturn pci_platform_pm->setup_dev(dev);\n+\n+\treturn NULL;\n+}\n+\n+void *platform_pci_setup_host_bridge(struct pci_host_bridge *bridge)\n+{\n+\tif (pci_platform_pm && pci_platform_pm->setup_host_bridge)\n+\t\treturn pci_platform_pm->setup_host_bridge(bridge);\n+\n+\treturn NULL;\n+}\n+\n+void platform_pci_cleanup(void *pmdata)\n+{\n+\tif (pci_platform_pm && pci_platform_pm->cleanup)\n+\t\tpci_platform_pm->cleanup(pmdata);\n+}\n+\n+static inline bool platform_pci_can_wakeup(void *pmdata)\n+{\n+\tif (pci_platform_pm && pci_platform_pm->can_wakeup)\n+\t\treturn pci_platform_pm->can_wakeup(pmdata);\n+\n+\treturn false;\n+}\n+\n+static inline int platform_pci_dev_wakeup(void *pmdata, bool enable)\n+{\n+\tif (pci_platform_pm && pci_platform_pm->dev_wakeup)\n+\t\treturn pci_platform_pm->dev_wakeup(pmdata, enable);\n+\n+\treturn -ENODEV;\n+}\n+\n+static inline int platform_pci_bridge_wakeup(void *pmdata, bool enable)\n+{\n+\tif (pci_platform_pm && pci_platform_pm->bridge_wakeup)\n+\t\treturn pci_platform_pm->bridge_wakeup(pmdata, enable);\n+\n+\treturn -ENODEV;\n+}\n+\n static inline int platform_pci_set_power_state(struct pci_dev *dev,\n \t\t\t\t\t pci_power_t t)\n {\n@@ -610,14 +656,6 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev)\n \treturn PCI_POWER_ERROR;\n }\n \n-static inline int platform_pci_set_wakeup(struct pci_dev *dev, bool enable)\n-{\n-\tif (pci_platform_pm && pci_platform_pm->set_wakeup)\n-\t\treturn pci_platform_pm->set_wakeup(dev, enable);\n-\n-\treturn -ENODEV;\n-}\n-\n static inline bool platform_pci_need_resume(struct pci_dev *dev)\n {\n \tif (pci_platform_pm && pci_platform_pm->need_resume)\n@@ -1903,6 +1941,32 @@ void pci_pme_active(struct pci_dev *dev, bool enable)\n }\n EXPORT_SYMBOL(pci_pme_active);\n \n+static int pci_set_wakeup(struct pci_dev *dev, bool enable)\n+{\n+\tstruct pci_bus *bus = dev->bus;\n+\tstruct pci_host_bridge *bridge;\n+\n+\t/* Handle per device wakeup */\n+\tif (platform_pci_can_wakeup(dev->pmdata))\n+\t\treturn platform_pci_dev_wakeup(dev->pmdata, enable);\n+\n+\t/* Find a parent which can handle wakeup */\n+\twhile (bus->parent) {\n+\t\tif (platform_pci_can_wakeup(bus->self->pmdata))\n+\t\t\treturn platform_pci_bridge_wakeup(bus->self->pmdata,\n+\t\t\t\t\t\t\t enable);\n+\n+\t\tbus = bus->parent;\n+\t}\n+\n+\t/* We have reached the root bus. */\n+\tbridge = to_pci_host_bridge(bus->bridge);\n+\tif (platform_pci_can_wakeup(bridge->pmdata))\n+\t\treturn platform_pci_bridge_wakeup(bridge->pmdata, enable);\n+\n+\treturn 0;\n+}\n+\n /**\n * pci_enable_wake - enable PCI device as wakeup event source\n * @dev: PCI device affected\n@@ -1950,13 +2014,13 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)\n \t\t\tpci_pme_active(dev, true);\n \t\telse\n \t\t\tret = 1;\n-\t\terror = platform_pci_set_wakeup(dev, true);\n+\t\terror = pci_set_wakeup(dev, true);\n \t\tif (ret)\n \t\t\tret = error;\n \t\tif (!ret)\n \t\t\tdev->wakeup_prepared = true;\n \t} else {\n-\t\tplatform_pci_set_wakeup(dev, false);\n+\t\tpci_set_wakeup(dev, false);\n \t\tpci_pme_active(dev, false);\n \t\tdev->wakeup_prepared = false;\n \t}\ndiff --git a/drivers/pci/pci.h b/drivers/pci/pci.h\nindex 048668271014..dcefb9e759d7 100644\n--- a/drivers/pci/pci.h\n+++ b/drivers/pci/pci.h\n@@ -47,21 +47,43 @@ int pci_probe_reset_function(struct pci_dev *dev);\n * platform; to be used during system-wide transitions from a\n * sleeping state to the working state and vice versa\n *\n- * @set_wakeup: enables/disables wakeup capability for the device\n- *\n * @need_resume: returns 'true' if the given device (which is currently\n *\t\tsuspended) needs to be resumed to be configured for system\n *\t\twakeup.\n+ *\n+ * @setup_dev: setup device's wakeup ability, alloc and return device's private\n+ * \t\tpm data.\n+ *\n+ * @setup_host_bridge: setup host bridge's wakeup ability, alloc and return host\n+ * \t\tbridge's private pm data.\n+ *\n+ * @cleanup: cleanup the private pm data and deinit wakeup ability.\n+ *\n+ * @can_wakeup: returns 'true' if given device is capable of waking up the\n+ *\t\tsystem from a sleeping state.\n+ *\n+ * @dev_wakeup: enables/disables wakeup capability for the device.\n+ *\n+ * @bridge_wakeup: enables/disables wakeup capability for the bridge.\n */\n struct pci_platform_pm_ops {\n \tbool (*is_manageable)(struct pci_dev *dev);\n \tint (*set_state)(struct pci_dev *dev, pci_power_t state);\n \tpci_power_t (*get_state)(struct pci_dev *dev);\n \tpci_power_t (*choose_state)(struct pci_dev *dev);\n-\tint (*set_wakeup)(struct pci_dev *dev, bool enable);\n \tbool (*need_resume)(struct pci_dev *dev);\n+\tvoid *(*setup_dev)(struct pci_dev *dev);\n+\tvoid *(*setup_host_bridge)(struct pci_host_bridge *bridge);\n+\tvoid (*cleanup)(void *pmdata);\n+\tbool (*can_wakeup)(void *pmdata);\n+\tint (*dev_wakeup)(void *pmdata, bool enable);\n+\tint (*bridge_wakeup)(void *pmdata, bool enable);\n };\n \n+void *platform_pci_setup_dev(struct pci_dev *dev);\n+void *platform_pci_setup_host_bridge(struct pci_host_bridge *bridge);\n+void platform_pci_cleanup(void *pmdata);\n+\n void pci_set_platform_pm(const struct pci_platform_pm_ops *ops);\n void pci_update_current_state(struct pci_dev *dev, pci_power_t state);\n void pci_power_up(struct pci_dev *dev);\ndiff --git a/drivers/pci/probe.c b/drivers/pci/probe.c\nindex cdc2f83c11c5..b12c552a5522 100644\n--- a/drivers/pci/probe.c\n+++ b/drivers/pci/probe.c\n@@ -809,7 +809,13 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)\n \n \terr = device_register(&bus->dev);\n \tif (err)\n-\t\tgoto unregister;\n+\t\tgoto unregister_bridge;\n+\n+\tbridge->pmdata = platform_pci_setup_host_bridge(bridge);\n+\tif (IS_ERR(bridge->pmdata)) {\n+\t\terr = PTR_ERR(bridge->pmdata);\n+\t\tgoto unregister_bus;\n+\t}\n \n \tpcibios_add_bus(bus);\n \n@@ -853,7 +859,9 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)\n \n \treturn 0;\n \n-unregister:\n+unregister_bus:\n+\tdevice_unregister(&bus->dev);\n+unregister_bridge:\n \tput_device(&bridge->dev);\n \tdevice_unregister(&bridge->dev);\n \ndiff --git a/drivers/pci/remove.c b/drivers/pci/remove.c\nindex 73a03d382590..d7a8cf1dc69f 100644\n--- a/drivers/pci/remove.c\n+++ b/drivers/pci/remove.c\n@@ -153,6 +153,8 @@ void pci_remove_root_bus(struct pci_bus *bus)\n \tif (!pci_is_root_bus(bus))\n \t\treturn;\n \n+\tplatform_pci_cleanup(host_bridge->pmdata);\n+\n \thost_bridge = to_pci_host_bridge(bus->bridge);\n \tlist_for_each_entry_safe(child, tmp,\n \t\t\t\t &bus->devices, bus_list)\ndiff --git a/include/linux/pci.h b/include/linux/pci.h\nindex 80eaa2dbe3e9..628faa58c790 100644\n--- a/include/linux/pci.h\n+++ b/include/linux/pci.h\n@@ -293,6 +293,7 @@ struct pci_dev {\n \tstruct pci_bus\t*subordinate;\t/* bus this device bridges to */\n \n \tvoid\t\t*sysdata;\t/* hook for sys-specific extension */\n+\tvoid\t\t*pmdata;\t/* data for platform pm */\n \tstruct proc_dir_entry *procent;\t/* device entry in /proc/bus/pci */\n \tstruct pci_slot\t*slot;\t\t/* Physical slot this device is in */\n \n@@ -467,6 +468,7 @@ struct pci_host_bridge {\n \tstruct pci_bus *bus;\t\t/* root bus */\n \tstruct pci_ops *ops;\n \tvoid *sysdata;\n+\tvoid *pmdata;\t\t\t/* data for platform pm */\n \tint busnr;\n \tstruct list_head windows;\t/* resource_entry */\n \tu8 (*swizzle_irq)(struct pci_dev *, u8 *); /* platform IRQ swizzler */\n", "prefixes": [ "RFC", "v10", "6/7" ] }