#define PCIEHP_DETECT_PCIE     (0)
 #define PCIEHP_DETECT_ACPI     (1)
-#define PCIEHP_DETECT_DEFAULT  PCIEHP_DETECT_PCIE
+#define PCIEHP_DETECT_AUTO     (2)
+#define PCIEHP_DETECT_DEFAULT  PCIEHP_DETECT_AUTO
 
 static int slot_detection_mode;
 static char *pciehp_detect_mode;
 module_param(pciehp_detect_mode, charp, 0444);
 MODULE_PARM_DESC(pciehp_detect_mode,
-                "Slot detection mode: pcie, acpi\n"
-                "  pcie - Use PCIe based slot detection (default)\n"
-                "  acpi - Use ACPI for slot detection\n");
+        "Slot detection mode: pcie, acpi, auto\n"
+        "  pcie          - Use PCIe based slot detection\n"
+        "  acpi          - Use ACPI for slot detection\n"
+        "  auto(default) - Auto select mode. Use acpi option if duplicate\n"
+        "                  slot ids are found. Otherwise, use pcie option\n");
 
 static int is_ejectable(acpi_handle handle)
 {
                return PCIEHP_DETECT_PCIE;
        if (!strcmp(pciehp_detect_mode, "acpi"))
                return PCIEHP_DETECT_ACPI;
+       if (!strcmp(pciehp_detect_mode, "auto"))
+               return PCIEHP_DETECT_AUTO;
        warn("bad specifier '%s' for pciehp_detect_mode. Use default\n",
             pciehp_detect_mode);
        return PCIEHP_DETECT_DEFAULT;
 }
 
+static struct pcie_port_service_id __initdata port_pci_ids[] = {
+       {
+               .vendor = PCI_ANY_ID,
+               .device = PCI_ANY_ID,
+               .port_type = PCIE_ANY_PORT,
+               .service_type = PCIE_PORT_SERVICE_HP,
+               .driver_data =  0,
+        }, { /* end: all zeroes */ }
+};
+
+static int __initdata dup_slot_id;
+static int __initdata acpi_slot_detected;
+static struct list_head __initdata dummy_slots = LIST_HEAD_INIT(dummy_slots);
+
+/* Dummy driver for dumplicate name detection */
+static int __init dummy_probe(struct pcie_device *dev,
+                             const struct pcie_port_service_id *id)
+{
+       int pos;
+       u32 slot_cap;
+       struct slot *slot, *tmp;
+       struct pci_dev *pdev = dev->port;
+       if (!(slot = kzalloc(sizeof(*slot), GFP_KERNEL)))
+               return -ENOMEM;
+       /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
+       if (pciehp_get_hp_hw_control_from_firmware(pdev))
+               return -ENODEV;
+       if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP)))
+               return -ENODEV;
+       pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap);
+       slot->number = slot_cap >> 19;
+       list_for_each_entry(tmp, &dummy_slots, slot_list) {
+               if (tmp->number == slot->number)
+                       dup_slot_id++;
+       }
+       list_add_tail(&slot->slot_list, &dummy_slots);
+       if (!acpi_slot_detected && pciehp_detect_acpi_slot(pdev->subordinate))
+               acpi_slot_detected = 1;
+       return -ENODEV;         /* dummy driver always returns error */
+}
+
+static struct pcie_port_service_driver __initdata dummy_driver = {
+        .name           = "pciehp_dummy",
+        .id_table       = port_pci_ids,
+        .probe          = dummy_probe,
+};
+
+static int __init select_detection_mode(void)
+{
+       struct slot *slot, *tmp;
+       pcie_port_service_register(&dummy_driver);
+       pcie_port_service_unregister(&dummy_driver);
+       list_for_each_entry_safe(slot, tmp, &dummy_slots, slot_list) {
+               list_del(&slot->slot_list);
+               kfree(slot);
+       }
+       if (acpi_slot_detected && dup_slot_id)
+               return PCIEHP_DETECT_ACPI;
+       return PCIEHP_DETECT_PCIE;
+}
+
 void __init pciehp_acpi_slot_detection_init(void)
 {
        slot_detection_mode = parse_detect_mode();
+       if (slot_detection_mode != PCIEHP_DETECT_AUTO)
+               goto out;
+       slot_detection_mode = select_detection_mode();
+out:
+       if (slot_detection_mode == PCIEHP_DETECT_ACPI)
+               info("Using ACPI for slot detection.\n");
 }