diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e3a1e7e..6ab29d8 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -136,6 +136,7 @@ struct controller { #define ATTN_LED_PRSN 0x00000008 #define PWR_LED_PRSN 0x00000010 #define HP_SUPR_RM_SUP 0x00000020 +#define HP_CAP_SUP 0x00000040 #define EMI_PRSN 0x00020000 #define NO_CMD_CMPL_SUP 0x00040000 @@ -145,6 +146,7 @@ struct controller { #define ATTN_LED(ctrl) ((ctrl)->slot_cap & ATTN_LED_PRSN) #define PWR_LED(ctrl) ((ctrl)->slot_cap & PWR_LED_PRSN) #define HP_SUPR_RM(ctrl) ((ctrl)->slot_cap & HP_SUPR_RM_SUP) +#define HP_CAP(ctrl) ((ctrl)->slot_cap & HP_CAP_SUP) #define EMI(ctrl) ((ctrl)->slot_cap & EMI_PRSN) #define NO_CMD_CMPL(ctrl) ((ctrl)->slot_cap & NO_CMD_CMPL_SUP) diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 3677495..896ca5f 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -386,6 +386,17 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe return 0; } +static bool acpi_rmv_present(struct pci_dev *pdev) +{ + struct acpi_device *acpi_dev = to_acpi_device(&pdev->dev); + + if (acpi_dev && acpi_dev->flags.removable) + return true; + + dbg("%s: no ACPI device (%p) or not removable\n", pci_name(pdev), acpi_dev); + return false; +} + static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_id *id) { int rc; @@ -397,8 +408,15 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ if (pciehp_force) dbg("Bypassing BIOS check for pciehp use on %s\n", pci_name(pdev)); - else if (pciehp_get_hp_hw_control_from_firmware(pdev)) - goto err_out_none; + else { + if (!acpi_rmv_present(pdev)) + goto err_out_none; + if (pciehp_get_hp_hw_control_from_firmware(pdev)) { + dbg("Failed to get control from firmware for %s\n", + pci_name(pdev)); + goto err_out_none; + } + } ctrl = pcie_init(dev); if (!ctrl) { diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 1323a43..445b0b1 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -149,7 +149,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) #define ATTN_LED_PRSN 0x00000008 #define PWR_LED_PRSN 0x00000010 #define HP_SUPR_RM_SUP 0x00000020 -#define HP_CAP 0x00000040 +#define HP_CAP_SUP 0x00000040 #define SLOT_PWR_VALUE 0x000003F8 #define SLOT_PWR_LIMIT 0x00000C00 #define PSN 0xFFF80000 /* PSN: Physical Slot Number */ @@ -1102,6 +1102,7 @@ static inline void dbg_ctrl(struct controller *ctrl) dbg(" Attention Indicator : %3s\n", ATTN_LED(ctrl) ? "yes" : "no"); dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no"); dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no"); + dbg(" Hot-Plug Capable : %3s\n", HP_CAP(ctrl) ? "yes" : "no"); dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no"); dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes"); pciehp_readw(ctrl, SLOTSTATUS, ®16); @@ -1127,18 +1128,25 @@ struct controller *pcie_init(struct pcie_device *dev) ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (!ctrl->cap_base) { err("%s: Cannot find PCI Express capability\n", __func__); - goto abort; + goto abort_ctrl; } if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) { err("%s: Cannot read SLOTCAP register\n", __func__); - goto abort; + goto abort_ctrl; } + ctrl->slot_cap = slot_cap; ctrl->first_slot = slot_cap >> 19; ctrl->slot_device_offset = 0; ctrl->num_slots = 1; ctrl->hpc_ops = &pciehp_hpc_ops; + + if (!HP_CAP(ctrl)) { + dbg("%s: not hotplug capable, skipping\n", pci_name(pdev)); + goto abort_ctrl; + } + mutex_init(&ctrl->crit_sect); mutex_init(&ctrl->ctrl_lock); init_waitqueue_head(&ctrl->queue);