Home Home > GIT Browse > SLE15-SP1
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKernel Build Daemon <kbuild@suse.de>2019-05-23 21:00:55 +0200
committerKernel Build Daemon <kbuild@suse.de>2019-05-23 21:00:55 +0200
commitd1796949cba2cbc9d86d18f582bf798152a25c4f (patch)
tree7946fcfa6a9b2ea80baf825681669e99c17f531e
parent00d8d869439fc2cc21c751441d99d945444c8f32 (diff)
parentcbef614bfef10ff3d624b3baf4caef2eb89ec91c (diff)
Merge branch 'users/oneukum/SLE15-SP1/for-next' into SLE15-SP1SLE15-SP1
-rw-r--r--patches.drivers/0001-PCI-pciehp-Unify-controller-and-slot-structs.patch110
-rw-r--r--patches.fixes/0001-PCI-pciehp-Tolerate-Presence-Detect-hardwired-to-zer.patch200
-rw-r--r--series.conf1
3 files changed, 244 insertions, 67 deletions
diff --git a/patches.drivers/0001-PCI-pciehp-Unify-controller-and-slot-structs.patch b/patches.drivers/0001-PCI-pciehp-Unify-controller-and-slot-structs.patch
index da3199c891..ab3d68d742 100644
--- a/patches.drivers/0001-PCI-pciehp-Unify-controller-and-slot-structs.patch
+++ b/patches.drivers/0001-PCI-pciehp-Unify-controller-and-slot-structs.patch
@@ -30,12 +30,12 @@ Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
- drivers/pci/hotplug/pciehp.h | 70 +++-------
- drivers/pci/hotplug/pciehp_core.c | 55 +++-----
- drivers/pci/hotplug/pciehp_ctrl.c | 254 ++++++++++++++++++--------------------
- drivers/pci/hotplug/pciehp_hpc.c | 128 +++++--------------
+ drivers/pci/hotplug/pciehp.h | 68 +++-------
+ drivers/pci/hotplug/pciehp_core.c | 53 +++-----
+ drivers/pci/hotplug/pciehp_ctrl.c | 248 ++++++++++++++++++--------------------
+ drivers/pci/hotplug/pciehp_hpc.c | 122 +++++-------------
drivers/pci/hotplug/pciehp_pci.c | 14 --
- 5 files changed, 215 insertions(+), 306 deletions(-)
+ 5 files changed, 207 insertions(+), 298 deletions(-)
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -96,7 +96,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
int request_result;
wait_queue_head_t requester;
};
-@@ -185,29 +163,29 @@ struct controller {
+@@ -185,28 +163,28 @@ struct controller {
#define PSN(ctrl) (((ctrl)->slot_cap & PCI_EXP_SLTCAP_PSN) >> 19)
void pciehp_request(struct controller *ctrl, int action);
@@ -125,7 +125,6 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
-
-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);
@@ -136,15 +135,14 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
+
+void pciehp_set_attention_status(struct controller *ctrl, u8 status);
+void pciehp_get_latch_status(struct controller *ctrl, u8 *status);
-+void pciehp_get_adapter_status(struct controller *ctrl, u8 *status);
+int pciehp_query_power_fault(struct controller *ctrl);
+void pciehp_green_led_on(struct controller *ctrl);
+void pciehp_green_led_off(struct controller *ctrl);
+void pciehp_green_led_blink(struct controller *ctrl);
+ 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);
-@@ -219,9 +197,9 @@ int pciehp_get_attention_status(struct h
+@@ -220,9 +198,9 @@ int pciehp_get_attention_status(struct h
int pciehp_set_raw_indicator_status(struct hotplug_slot *h_slot, u8 status);
int pciehp_get_raw_indicator_status(struct hotplug_slot *h_slot, u8 *status);
@@ -239,8 +237,8 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
+ struct pci_dev *pdev = ctrl->pcie->port;
pci_config_pm_runtime_get(pdev);
-- pciehp_get_adapter_status(slot, value);
-+ pciehp_get_adapter_status(ctrl, value);
+- *value = pciehp_card_present_or_link_active(slot->ctrl);
++ *value = pciehp_card_present_or_link_active(ctrl);
pci_config_pm_runtime_put(pdev);
return 0;
}
@@ -249,18 +247,17 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
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);
+ mutex_lock(&ctrl->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 ||
- slot->state == BLINKINGOFF_STATE)))
-+ pciehp_get_adapter_status(ctrl, &occupied);
+ if ((occupied && (ctrl->state == OFF_STATE ||
+ ctrl->state == BLINKINGON_STATE)) ||
+ (!occupied && (ctrl->state == ON_STATE ||
@@ -503,7 +500,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
break;
case BLINKINGOFF_STATE:
case BLINKINGON_STATE:
-@@ -201,46 +199,43 @@ void pciehp_handle_button_press(struct s
+@@ -201,143 +199,138 @@ void pciehp_handle_button_press(struct s
* press the attention again before the 5 sec. limit
* expires to cancel hot-add or hot-remove
*/
@@ -566,10 +563,9 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
+void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
{
- struct controller *ctrl = slot->ctrl;
- bool link_active;
- u8 present;
+ bool present, link_active;
-@@ -248,102 +243,100 @@ void pciehp_handle_presence_or_link_chan
+ /*
* If the slot is on and presence or link has changed, turn it off.
* Even if it's occupied again, we cannot assume the card is the same.
*/
@@ -603,9 +599,8 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
/* Turn the slot on if it's occupied or link is up */
- mutex_lock(&slot->lock);
-- pciehp_get_adapter_status(slot, &present);
+ mutex_lock(&ctrl->lock);
-+ pciehp_get_adapter_status(ctrl, &present);
+ present = pciehp_card_present(ctrl);
link_active = pciehp_check_link_active(ctrl);
if (!present && !link_active) {
- mutex_unlock(&slot->lock);
@@ -649,13 +644,6 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
u8 getstatus = 0;
- struct controller *ctrl = p_slot->ctrl;
-- pciehp_get_adapter_status(p_slot, &getstatus);
-+ pciehp_get_adapter_status(ctrl, &getstatus);
- if (!getstatus) {
-- ctrl_info(ctrl, "Slot(%s): No adapter\n", slot_name(p_slot));
-+ ctrl_info(ctrl, "Slot(%s): No adapter\n", slot_name(ctrl));
- return -ENODEV;
- }
- if (MRL_SENS(p_slot->ctrl)) {
- pciehp_get_latch_status(p_slot, &getstatus);
+ if (MRL_SENS(ctrl)) {
@@ -693,9 +681,9 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
- mutex_lock(&slot->hotplug_lock);
- ret = __pciehp_enable_slot(slot);
- mutex_unlock(&slot->hotplug_lock);
-+ pm_runtime_get_sync(&ctrl->pcie->port->dev);
++ mutex_lock(&ctrl->lock);
+ ret = __pciehp_enable_slot(ctrl);
-+ pm_runtime_put(&ctrl->pcie->port->dev);
++ mutex_unlock(&ctrl->lock);
if (ret && ATTN_BUTTN(ctrl))
- pciehp_green_led_off(slot); /* may be blinking */
@@ -705,12 +693,12 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
- slot->state = ON_STATE;
- mutex_unlock(&slot->lock);
+ mutex_lock(&ctrl->lock);
-+ ctrl->state = ret ? OFF_STATE : ON_STATE;
++ ctrl->state = ON_STATE;
+ mutex_unlock(&ctrl->lock);
return ret;
}
-@@ -351,48 +344,46 @@ int pciehp_enable_slot(struct slot *slot
+@@ -345,48 +338,46 @@ int pciehp_enable_slot(struct slot *slot
/*
* Note: This function must be called with slot->hotplug_lock held
*/
@@ -776,7 +764,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
/*
* The IRQ thread becomes a no-op if the user pulls out the
* card before the thread wakes up, so initialize to -ENODEV.
-@@ -404,33 +395,32 @@ int pciehp_sysfs_enable_slot(struct hotp
+@@ -398,33 +389,32 @@ int pciehp_sysfs_enable_slot(struct hotp
return ctrl->request_result;
case POWERON_STATE:
ctrl_info(ctrl, "Slot(%s): Already in powering on state\n",
@@ -818,7 +806,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
pciehp_request(ctrl, DISABLE_SLOT);
wait_event(ctrl->requester,
!atomic_read(&ctrl->pending_events));
-@@ -438,20 +428,20 @@ int pciehp_sysfs_disable_slot(struct hot
+@@ -432,20 +422,20 @@ int pciehp_sysfs_disable_slot(struct hot
break;
case POWEROFF_STATE:
ctrl_info(ctrl, "Slot(%s): Already in powering off state\n",
@@ -886,7 +874,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
struct pci_dev *pdev = ctrl_dev(ctrl);
u16 slot_ctrl;
-@@ -397,27 +395,27 @@ void pciehp_get_power_status(struct slot
+@@ -397,9 +395,9 @@ void pciehp_get_power_status(struct slot
}
}
@@ -898,18 +886,8 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
u16 slot_status;
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
- *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS);
- }
-
--void pciehp_get_adapter_status(struct slot *slot, u8 *status)
-+void pciehp_get_adapter_status(struct controller *ctrl, u8 *status)
- {
-- 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);
+@@ -429,9 +427,9 @@ bool pciehp_card_present_or_link_active(
+ return pciehp_card_present(ctrl) || pciehp_check_link_active(ctrl);
}
-int pciehp_query_power_fault(struct slot *slot)
@@ -920,7 +898,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
u16 slot_status;
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
-@@ -427,8 +425,7 @@ int pciehp_query_power_fault(struct slot
+@@ -441,8 +439,7 @@ int pciehp_query_power_fault(struct slot
int pciehp_set_raw_indicator_status(struct hotplug_slot *hotplug_slot,
u8 status)
{
@@ -930,7 +908,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
struct pci_dev *pdev = ctrl_dev(ctrl);
pci_config_pm_runtime_get(pdev);
-@@ -438,9 +435,8 @@ int pciehp_set_raw_indicator_status(stru
+@@ -452,9 +449,8 @@ int pciehp_set_raw_indicator_status(stru
return 0;
}
@@ -941,7 +919,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
u16 slot_cmd;
if (!ATTN_LED(ctrl))
-@@ -464,10 +460,8 @@ void pciehp_set_attention_status(struct
+@@ -478,10 +474,8 @@ void pciehp_set_attention_status(struct
pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
}
@@ -953,7 +931,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
if (!PWR_LED(ctrl))
return;
-@@ -478,10 +472,8 @@ void pciehp_green_led_on(struct slot *sl
+@@ -492,10 +486,8 @@ void pciehp_green_led_on(struct slot *sl
PCI_EXP_SLTCTL_PWR_IND_ON);
}
@@ -965,7 +943,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
if (!PWR_LED(ctrl))
return;
-@@ -492,10 +484,8 @@ void pciehp_green_led_off(struct slot *s
+@@ -506,10 +498,8 @@ void pciehp_green_led_off(struct slot *s
PCI_EXP_SLTCTL_PWR_IND_OFF);
}
@@ -977,7 +955,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
if (!PWR_LED(ctrl))
return;
-@@ -506,9 +496,8 @@ void pciehp_green_led_blink(struct slot
+@@ -520,9 +510,8 @@ void pciehp_green_led_blink(struct slot
PCI_EXP_SLTCTL_PWR_IND_BLINK);
}
@@ -988,7 +966,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
struct pci_dev *pdev = ctrl_dev(ctrl);
u16 slot_status;
int retval;
-@@ -532,10 +521,8 @@ int pciehp_power_on_slot(struct slot *sl
+@@ -546,10 +535,8 @@ int pciehp_power_on_slot(struct slot *sl
return retval;
}
@@ -1000,7 +978,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC);
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
-@@ -609,7 +596,6 @@ static irqreturn_t pciehp_isr(int irq, v
+@@ -623,7 +610,6 @@ static irqreturn_t pciehp_isr(int irq, v
static irqreturn_t pciehp_ist(int irq, void *dev_id)
{
struct controller *ctrl = (struct controller *)dev_id;
@@ -1008,7 +986,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
u32 events;
synchronize_hardirq(irq);
-@@ -620,16 +606,16 @@ static irqreturn_t pciehp_ist(int irq, v
+@@ -634,16 +620,16 @@ static irqreturn_t pciehp_ist(int irq, v
/* Check Attention Button Pressed */
if (events & PCI_EXP_SLTSTA_ABP) {
ctrl_info(ctrl, "Slot(%s): Attention button pressed\n",
@@ -1030,7 +1008,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
}
/*
-@@ -638,9 +624,9 @@ static irqreturn_t pciehp_ist(int irq, v
+@@ -652,9 +638,9 @@ static irqreturn_t pciehp_ist(int irq, v
*/
down_read(&ctrl->reset_lock);
if (events & DISABLE_SLOT)
@@ -1042,7 +1020,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
up_read(&ctrl->reset_lock);
wake_up(&ctrl->requester);
-@@ -735,8 +721,7 @@ void pcie_clear_hotplug_events(struct co
+@@ -749,8 +735,7 @@ void pcie_clear_hotplug_events(struct co
*/
int pciehp_reset_slot(struct hotplug_slot *hotplug_slot, int probe)
{
@@ -1052,7 +1030,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
struct pci_dev *pdev = ctrl_dev(ctrl);
u16 stat_mask = 0, ctrl_mask = 0;
int rc;
-@@ -786,42 +771,6 @@ void pcie_shutdown_notification(struct c
+@@ -800,42 +785,6 @@ void pcie_shutdown_notification(struct c
}
}
@@ -1095,9 +1073,9 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
static inline void dbg_ctrl(struct controller *ctrl)
{
struct pci_dev *pdev = ctrl->pcie->port;
-@@ -845,10 +794,11 @@ struct controller *pcie_init(struct pcie
+@@ -859,10 +808,11 @@ struct controller *pcie_init(struct pcie
u32 slot_cap, link_cap;
- u8 occupied, poweron;
+ u8 poweron;
struct pci_dev *pdev = dev->port;
+ struct pci_bus *subordinate = pdev->subordinate;
@@ -1108,7 +1086,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
ctrl->pcie = dev;
pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap);
-@@ -865,11 +815,17 @@ struct controller *pcie_init(struct pcie
+@@ -879,11 +829,17 @@ struct controller *pcie_init(struct pcie
ctrl->slot_cap = slot_cap;
mutex_init(&ctrl->ctrl_lock);
@@ -1126,7 +1104,7 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
/* Check if Data Link Layer Link Active Reporting is implemented */
pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap);
if (link_cap & PCI_EXP_LNKCAP_DLLLARC)
-@@ -895,33 +851,25 @@ struct controller *pcie_init(struct pcie
+@@ -909,32 +865,24 @@ struct controller *pcie_init(struct pcie
FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC),
pdev->broken_cmd_compl ? " (with Cmd Compl erratum)" : "");
@@ -1138,11 +1116,9 @@ Signed-off-by: Oliver Neukum <oneukum@suse.com>
* 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);
-+ pciehp_get_adapter_status(ctrl, &occupied);
+ pciehp_get_power_status(ctrl, &poweron);
- if (!occupied && poweron) {
+ if (!pciehp_card_present_or_link_active(ctrl) && poweron) {
pcie_disable_notification(ctrl);
- pciehp_power_off_slot(ctrl->slot);
+ pciehp_power_off_slot(ctrl);
diff --git a/patches.fixes/0001-PCI-pciehp-Tolerate-Presence-Detect-hardwired-to-zer.patch b/patches.fixes/0001-PCI-pciehp-Tolerate-Presence-Detect-hardwired-to-zer.patch
new file mode 100644
index 0000000000..f61a309b5d
--- /dev/null
+++ b/patches.fixes/0001-PCI-pciehp-Tolerate-Presence-Detect-hardwired-to-zer.patch
@@ -0,0 +1,200 @@
+From 80696f991424d05a784c0cf9c314ac09ac280406 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Sat, 8 Sep 2018 09:59:01 +0200
+Subject: [PATCH] PCI: pciehp: Tolerate Presence Detect hardwired to zero
+Git-commit: 80696f991424d05a784c0cf9c314ac09ac280406
+Patch-mainline: v4.20
+References: bsc#1133016
+
+The WiGig Bus Extension (WBE) specification allows tunneling PCIe over
+IEEE 802.11. A product implementing this spec is the wil6210 from
+Wilocity (now part of Qualcomm Atheros). It integrates a PCIe switch
+with a wireless network adapter:
+
+ 00.0-+ [1ae9:0101] Upstream Port
+ +-00.0-+ [1ae9:0200] Downstream Port
+ | +-00.0 [168c:0034] Atheros AR9462 Wireless Network Adapter
+ +-02.0 [1ae9:0201] Downstream Port
+ +-03.0 [1ae9:0201] Downstream Port
+
+Wirelessly attached devices presumably appear below the hotplug ports
+with device ID [1ae9:0201]. Oddly, the Downstream Port [1ae9:0200]
+leading to the wireless network adapter is likewise Hotplug Capable,
+but has its Presence Detect State bit hardwired to zero. Even if the
+Link Active bit is set, Presence Detect is zero, so this cannot be
+caused by in-band presence detection but only by broken hardware.
+
+pciehp assumes an empty slot if Presence Detect State is zero,
+regardless of Link Active being one. Consequently, up until v4.18 it
+removes the wireless network adapter in pciehp_resume(). From v4.19 it
+already does so in pciehp_probe().
+
+Be lenient towards broken hardware and assume the slot is occupied if
+Link Active is set: Introduce pciehp_card_present_or_link_active()
+and use it in lieu of pciehp_get_adapter_status() everywhere, except
+in pciehp_handle_presence_or_link_change() whose log messages depend
+on which of Presence Detect State or Link Active is set.
+
+Remove the Presence Detect State check from __pciehp_enable_slot()
+because it is only called if either of Presence Detect State or Link
+Active is set.
+
+Caution: There is a possibility that broken hardware exists which has
+working Presence Detect but hardwires Link Active to one. On such
+hardware the slot will now incorrectly be considered always occupied.
+If such hardware is discovered, this commit can be rolled back and a
+quirk can be added which sets is_hotplug_bridge = 0 for [1ae9:0200].
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=200839
+Reported-and-tested-by: David Yang <mmyangfl@gmail.com>
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Rajat Jain <rajatja@google.com>
+Cc: Ashok Raj <ashok.raj@intel.com>
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+---
+ drivers/pci/hotplug/pciehp.h | 3 ++-
+ drivers/pci/hotplug/pciehp_core.c | 6 +++---
+ drivers/pci/hotplug/pciehp_ctrl.c | 10 ++--------
+ 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);
+ }
+--
+2.16.4
+
diff --git a/series.conf b/series.conf
index 2fc2bc61fb..40047f2df8 100644
--- a/series.conf
+++ b/series.conf
@@ -41250,6 +41250,7 @@
patches.drivers/PCI-Add-support-for-Immediate-Readiness.patch
patches.drivers/0001-PCI-pciehp-Differentiate-between-surprise-and-safe-r.patch
patches.drivers/0001-PCI-pciehp-Drop-hotplug_slot_ops-wrappers.patch
+ patches.fixes/0001-PCI-pciehp-Tolerate-Presence-Detect-hardwired-to-zer.patch
patches.drivers/0001-PCI-pciehp-Unify-controller-and-slot-structs.patch
patches.drivers/0001-PCI-Do-not-skip-power-managed-bridges-in-pci_enable_.patch
patches.drivers/0001-PCI-ACPI-Enable-wake-automatically-for-power-managed.patch