diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h index bb5d581a8ba9..2090aa21755f 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h +++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h @@ -411,7 +411,6 @@ struct ep_pcie_dev_t { bool conf_ipa_msi_iatu; struct ep_pcie_register_event *event_reg; - struct work_struct handle_perst_work; struct work_struct handle_bme_work; struct work_struct handle_d3cold_work; diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index 219e0e97b794..29efab766e3d 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -2354,18 +2354,6 @@ static int ep_pcie_enumeration(struct ep_pcie_dev_t *dev) return ret; } -static void handle_perst_func(struct work_struct *work) -{ - struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, - handle_perst_work); - - EP_PCIE_DBG(dev, - "PCIe V%d: Start enumeration due to PERST deassertion\n", - dev->rev); - - ep_pcie_enumeration(dev); -} - static void handle_d3cold_func(struct work_struct *work) { struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, @@ -2403,6 +2391,7 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) { struct ep_pcie_dev_t *dev = data; unsigned long irqsave_flags; + irqreturn_t result = IRQ_HANDLED; u32 perst; spin_lock_irqsave(&dev->isr_lock, irqsave_flags); @@ -2427,8 +2416,11 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) "PCIe V%d: Acquired wakelock\n", dev->rev); } - /* start work for link enumeration with the host side */ - queue_work(system_highpri_wq, &dev->handle_perst_work); + /* + * Perform link enumeration with the host side in the + * bottom half + */ + result = IRQ_WAKE_THREAD; } else { dev->no_notify = true; /* shutdown the link if the link is already on */ @@ -2454,7 +2446,7 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) EP_PCIE_DBG(dev, "PCIe V%d: No. %ld PERST deassertion\n", dev->rev, dev->perst_deast_counter); - ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_RST_DEAST); + result = IRQ_WAKE_THREAD; } else { atomic_set(&dev->perst_deast, 0); dev->perst_ast_counter++; @@ -2480,6 +2472,22 @@ out: spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); + return result; +} + +static irqreturn_t ep_pcie_handle_perst_deassert(int irq, void *data) +{ + struct ep_pcie_dev_t *dev = data; + + if (!dev->enumerated) { + EP_PCIE_DBG(dev, + "PCIe V%d: Start enumeration due to PERST deassertion\n", + dev->rev); + ep_pcie_enumeration(dev); + } else { + ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_RST_DEAST); + } + return IRQ_HANDLED; } @@ -2598,7 +2606,6 @@ int32_t ep_pcie_irq_init(struct ep_pcie_dev_t *dev) EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); /* Initialize all works to be performed before registering for IRQs*/ - INIT_WORK(&dev->handle_perst_work, handle_perst_func); INIT_WORK(&dev->handle_bme_work, handle_bme_func); INIT_WORK(&dev->handle_d3cold_work, handle_d3cold_func); @@ -2718,7 +2725,8 @@ perst_irq: } /* register handler for PERST interrupt */ - ret = devm_request_irq(pdev, dev->perst_irq, ep_pcie_handle_perst_irq, + ret = devm_request_threaded_irq(pdev, dev->perst_irq, ep_pcie_handle_perst_irq, + ep_pcie_handle_perst_deassert, ((atomic_read(&dev->perst_deast) ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH) | IRQF_EARLY_RESUME), "ep_pcie_perst", dev);