aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2018-07-19 18:27:57 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-07-31 12:09:36 -0400
commit4417aa45c185376ece278430e33b6a1891a1dc36 (patch)
tree0e498444068e5ba5e4d8a280d972faabd2ff1e22
parent8350307454240abeebe52ff5a73810d9ba93dd60 (diff)
PCI: pciehp: Resume parent to D0 on config space access
Ensure accessibility of a hotplug port's config space when accessed via sysfs by resuming its parent to D0. Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Cc: Mika Westerberg <mika.westerberg@linux.intel.com> Cc: Ashok Raj <ashok.raj@intel.com> Cc: Keith Busch <keith.busch@intel.com> Cc: Yinghai Lu <yinghai@kernel.org>
-rw-r--r--drivers/pci/hotplug/pciehp_core.c14
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c7
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 3e73b12ed656..01fcf1fa0f66 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -26,6 +26,8 @@
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/time.h> 27#include <linux/time.h>
28 28
29#include "../pci.h"
30
29/* Global variables */ 31/* Global variables */
30bool pciehp_debug; 32bool pciehp_debug;
31bool pciehp_poll_mode; 33bool pciehp_poll_mode;
@@ -126,8 +128,11 @@ static void cleanup_slot(struct controller *ctrl)
126static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) 128static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
127{ 129{
128 struct slot *slot = hotplug_slot->private; 130 struct slot *slot = hotplug_slot->private;
131 struct pci_dev *pdev = slot->ctrl->pcie->port;
129 132
133 pci_config_pm_runtime_get(pdev);
130 pciehp_set_attention_status(slot, status); 134 pciehp_set_attention_status(slot, status);
135 pci_config_pm_runtime_put(pdev);
131 return 0; 136 return 0;
132} 137}
133 138
@@ -150,8 +155,11 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
150static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) 155static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
151{ 156{
152 struct slot *slot = hotplug_slot->private; 157 struct slot *slot = hotplug_slot->private;
158 struct pci_dev *pdev = slot->ctrl->pcie->port;
153 159
160 pci_config_pm_runtime_get(pdev);
154 pciehp_get_power_status(slot, value); 161 pciehp_get_power_status(slot, value);
162 pci_config_pm_runtime_put(pdev);
155 return 0; 163 return 0;
156} 164}
157 165
@@ -166,16 +174,22 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
166static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) 174static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
167{ 175{
168 struct slot *slot = hotplug_slot->private; 176 struct slot *slot = hotplug_slot->private;
177 struct pci_dev *pdev = slot->ctrl->pcie->port;
169 178
179 pci_config_pm_runtime_get(pdev);
170 pciehp_get_latch_status(slot, value); 180 pciehp_get_latch_status(slot, value);
181 pci_config_pm_runtime_put(pdev);
171 return 0; 182 return 0;
172} 183}
173 184
174static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) 185static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
175{ 186{
176 struct slot *slot = hotplug_slot->private; 187 struct slot *slot = hotplug_slot->private;
188 struct pci_dev *pdev = slot->ctrl->pcie->port;
177 189
190 pci_config_pm_runtime_get(pdev);
178 pciehp_get_adapter_status(slot, value); 191 pciehp_get_adapter_status(slot, value);
192 pci_config_pm_runtime_put(pdev);
179 return 0; 193 return 0;
180} 194}
181 195
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 6e9b4330ad82..6f7de0819c88 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -322,7 +322,9 @@ int pciehp_get_raw_indicator_status(struct hotplug_slot *hotplug_slot,
322 struct pci_dev *pdev = ctrl_dev(slot->ctrl); 322 struct pci_dev *pdev = ctrl_dev(slot->ctrl);
323 u16 slot_ctrl; 323 u16 slot_ctrl;
324 324
325 pci_config_pm_runtime_get(pdev);
325 pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); 326 pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
327 pci_config_pm_runtime_put(pdev);
326 *status = (slot_ctrl & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; 328 *status = (slot_ctrl & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6;
327 return 0; 329 return 0;
328} 330}
@@ -333,7 +335,9 @@ void pciehp_get_attention_status(struct slot *slot, u8 *status)
333 struct pci_dev *pdev = ctrl_dev(ctrl); 335 struct pci_dev *pdev = ctrl_dev(ctrl);
334 u16 slot_ctrl; 336 u16 slot_ctrl;
335 337
338 pci_config_pm_runtime_get(pdev);
336 pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); 339 pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
340 pci_config_pm_runtime_put(pdev);
337 ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__, 341 ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__,
338 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); 342 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl);
339 343
@@ -408,9 +412,12 @@ int pciehp_set_raw_indicator_status(struct hotplug_slot *hotplug_slot,
408{ 412{
409 struct slot *slot = hotplug_slot->private; 413 struct slot *slot = hotplug_slot->private;
410 struct controller *ctrl = slot->ctrl; 414 struct controller *ctrl = slot->ctrl;
415 struct pci_dev *pdev = ctrl_dev(ctrl);
411 416
417 pci_config_pm_runtime_get(pdev);
412 pcie_write_cmd_nowait(ctrl, status << 6, 418 pcie_write_cmd_nowait(ctrl, status << 6,
413 PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC); 419 PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC);
420 pci_config_pm_runtime_put(pdev);
414 return 0; 421 return 0;
415} 422}
416 423