Subject:[PATCH v2] PCI, pciechp: power on/off slots after change to D0 Found power on via /sys has problem. sca05-0a81fd7f:~ # echo 1 > /sys/bus/pci/slots/7/power [ 300.949937] pci_hotplug: power_write_file: power = 1 [ 300.955502] pciehp 0000:73:00.0:pcie004: pciehp_get_power_status: SLOTCTRL a8 value read 17f1 [ 300.982557] pciehp 0000:73:00.0:pcie004: pending interrupts 0x0010 from Slot Status [ 300.991171] pciehp 0000:73:00.0:pcie004: pciehp_power_on_slot: SLOTCTRL a8 write cmd 0 [ 301.000033] pciehp 0000:73:00.0:pcie004: pciehp_green_led_blink: SLOTCTRL a8 write cmd 200 [ 301.009274] pciehp 0000:73:00.0:pcie004: pending interrupts 0x0010 from Slot Status [ 301.662172] pciehp 0000:73:00.0:pcie004: pciehp_check_link_active: lnk_status = f083 [ 301.670827] pciehp 0000:73:00.0:pcie004: pending interrupts 0x0108 from Slot Status [ 301.679376] pciehp 0000:73:00.0:pcie004: Slot(7): Link Up [ 301.685463] pciehp 0000:73:00.0:pcie004: Slot(7): Link Up event ignored; already powering on [ 301.685508] pciehp 0000:73:00.0:pcie004: pciehp_check_link_active: lnk_status = f083 [ 302.005967] pciehp 0000:73:00.0:pcie004: pciehp_check_link_status: lnk_status = f083 [ 302.014859] pci 0000:74:00.0: [15b3:1003] type 00 class 0x0c0600 also find other slot with other card still have extra link up problem on power off. That mean commit 68db9bc assumpation about power on/off on D3 is not right. > >- The configuration space of the port remains accessible in D3hot, so all > the functions to read or modify the Slot Status and Slot Control > registers need not be modified. Even turning on slot power doesn't seem > to require the port to be in D0, at least the PCIe spec doesn't say so > and I confirmed that by testing with a Thunderbolt controller. This patch put back D0 when trying to power on/off the slots. Signed-off-by: Yinghai Lu --- drivers/pci/hotplug/pciehp_ctrl.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) Index: linux-2.6/drivers/pci/hotplug/pciehp_ctrl.c =================================================================== --- linux-2.6.orig/drivers/pci/hotplug/pciehp_ctrl.c +++ linux-2.6/drivers/pci/hotplug/pciehp_ctrl.c @@ -86,17 +86,17 @@ static int board_added(struct slot *p_sl struct controller *ctrl = p_slot->ctrl; struct pci_bus *parent = ctrl->pcie->port->subordinate; + pm_runtime_get_sync(&ctrl->pcie->port->dev); if (POWER_CTRL(ctrl)) { /* Power on slot */ retval = pciehp_power_on_slot(p_slot); if (retval) - return retval; + goto err_exit; } pciehp_green_led_blink(p_slot); /* Check link training status */ - pm_runtime_get_sync(&ctrl->pcie->port->dev); retval = pciehp_check_link_status(ctrl); if (retval) { ctrl_err(ctrl, "Failed to check link status\n"); @@ -124,8 +124,9 @@ static int board_added(struct slot *p_sl return 0; err_exit: - pm_runtime_put(&ctrl->pcie->port->dev); set_slot_off(ctrl, p_slot); + pm_runtime_put(&ctrl->pcie->port->dev); + /* turn on Amber LED, turn off Green LED */ pciehp_green_led_off(p_slot); pciehp_set_attention_status(p_slot, 1); @@ -143,11 +144,13 @@ static int remove_board(struct slot *p_s pm_runtime_get_sync(&ctrl->pcie->port->dev); retval = pciehp_unconfigure_device(p_slot); - pm_runtime_put(&ctrl->pcie->port->dev); - if (retval) + if (retval) { + pm_runtime_put(&ctrl->pcie->port->dev); return retval; + } set_slot_off(ctrl, p_slot); + pm_runtime_put(&ctrl->pcie->port->dev); /* turn off Green LED */ pciehp_green_led_off(p_slot);