diff options
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 3 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 6 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 10 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 25 |
4 files changed, 26 insertions, 18 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 8131c08b21e5..b9204ef3ecd7 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -190,11 +190,12 @@ void pciehp_get_power_status(struct slot *slot, u8 *status); void pciehp_set_attention_status(struct slot *slot, u8 status); void pciehp_get_latch_status(struct slot *slot, u8 *status); -void pciehp_get_adapter_status(struct slot *slot, u8 *status); int pciehp_query_power_fault(struct slot *slot); void pciehp_green_led_on(struct slot *slot); void pciehp_green_led_off(struct slot *slot); void pciehp_green_led_blink(struct slot *slot); +bool pciehp_card_present(struct controller *ctrl); +bool pciehp_card_present_or_link_active(struct controller *ctrl); int pciehp_check_link_status(struct controller *ctrl); bool pciehp_check_link_active(struct controller *ctrl); void pciehp_release_ctrl(struct controller *ctrl); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index ccaf01e6eced..d24875102b1f 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -158,7 +158,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) struct pci_dev *pdev = slot->ctrl->pcie->port; pci_config_pm_runtime_get(pdev); - pciehp_get_adapter_status(slot, value); + *value = pciehp_card_present_or_link_active(slot->ctrl); pci_config_pm_runtime_put(pdev); return 0; } @@ -176,12 +176,12 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) static void pciehp_check_presence(struct controller *ctrl) { struct slot *slot = ctrl->slot; - u8 occupied; + bool occupied; down_read(&ctrl->reset_lock); mutex_lock(&slot->lock); - pciehp_get_adapter_status(slot, &occupied); + occupied = pciehp_card_present_or_link_active(ctrl); if ((occupied && (slot->state == OFF_STATE || slot->state == BLINKINGON_STATE)) || (!occupied && (slot->state == ON_STATE || diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index c4d0f902f1d2..1fda6ea96fdc 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -223,8 +223,7 @@ void pciehp_handle_disable_request(struct slot *slot) void pciehp_handle_presence_or_link_change(struct slot *slot, u32 events) { struct controller *ctrl = slot->ctrl; - bool link_active; - u8 present; + bool present, link_active; /* * If the slot is on and presence or link has changed, turn it off. @@ -253,7 +252,7 @@ void pciehp_handle_presence_or_link_change(struct slot *slot, u32 events) /* Turn the slot on if it's occupied or link is up */ mutex_lock(&slot->lock); - pciehp_get_adapter_status(slot, &present); + present = pciehp_card_present(ctrl); link_active = pciehp_check_link_active(ctrl); if (!present && !link_active) { mutex_unlock(&slot->lock); @@ -286,11 +285,6 @@ static int __pciehp_enable_slot(struct slot *p_slot) u8 getstatus = 0; struct controller *ctrl = p_slot->ctrl; - pciehp_get_adapter_status(p_slot, &getstatus); - if (!getstatus) { - ctrl_info(ctrl, "Slot(%s): No adapter\n", slot_name(p_slot)); - return -ENODEV; - } if (MRL_SENS(p_slot->ctrl)) { pciehp_get_latch_status(p_slot, &getstatus); if (getstatus) { diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 93003ff81166..d6cd4fbc72da 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -389,13 +389,27 @@ void pciehp_get_latch_status(struct slot *slot, u8 *status) *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS); } -void pciehp_get_adapter_status(struct slot *slot, u8 *status) +bool pciehp_card_present(struct controller *ctrl) { - struct pci_dev *pdev = ctrl_dev(slot->ctrl); + struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - *status = !!(slot_status & PCI_EXP_SLTSTA_PDS); + return slot_status & PCI_EXP_SLTSTA_PDS; +} + +/** + * pciehp_card_present_or_link_active() - whether given slot is occupied + * @ctrl: PCIe hotplug controller + * + * Unlike pciehp_card_present(), which determines presence solely from the + * Presence Detect State bit, this helper also returns true if the Link Active + * bit is set. This is a concession to broken hotplug ports which hardwire + * Presence Detect State to zero, such as Wilocity's [1ae9:0200]. + */ +bool pciehp_card_present_or_link_active(struct controller *ctrl) +{ + return pciehp_card_present(ctrl) || pciehp_check_link_active(ctrl); } int pciehp_query_power_fault(struct slot *slot) @@ -858,7 +872,7 @@ struct controller *pcie_init(struct pcie_device *dev) { struct controller *ctrl; u32 slot_cap, link_cap; - u8 occupied, poweron; + u8 poweron; struct pci_dev *pdev = dev->port; ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); @@ -918,9 +932,8 @@ struct controller *pcie_init(struct pcie_device *dev) * requested yet, so avoid triggering a notification with this command. */ if (POWER_CTRL(ctrl)) { - pciehp_get_adapter_status(ctrl->slot, &occupied); pciehp_get_power_status(ctrl->slot, &poweron); - if (!occupied && poweron) { + if (!pciehp_card_present_or_link_active(ctrl) && poweron) { pcie_disable_notification(ctrl); pciehp_power_off_slot(ctrl->slot); } |