summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManikanta Maddireddy <mmaddireddy@nvidia.com>2018-11-03 11:10:27 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-11-24 04:20:42 -0500
commit8b0b7a920036c37ff4e7beb1e5af6396b8e43bfe (patch)
tree33db296fb7b18982416223ac96de2e0e20cdb935
parentf723fb69fc8c56c2850f7a4c16eb5c2b6dbf6246 (diff)
PCI: tegra: Fix module remove sequence
Removing root port driver module will cause PERST# assert, which is processed by execute pex_ep_event_pex_rst_assert() function in kthread context. If endpoint driver module is removed immediately it will free the interrupt, sometimes this happens before PERST# assert irq is processed. To deinit controller execute pex_ep_event_pex_rst_assert() function in rmmod. To avoid the race condition between the kthread and rmmod, synchronize pex_ep_event_pex_rst_assert() function using mutex lock. bug 2422300 Change-Id: Id08c667c32aa240a150a2e8bb7b01367bec291f7 Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1953518 Reviewed-by: Vidya Sagar <vidyas@nvidia.com> Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/pci/ep/pcie-tegra-dw-ep.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/drivers/pci/ep/pcie-tegra-dw-ep.c b/drivers/pci/ep/pcie-tegra-dw-ep.c
index 68ff635a6..517ad45c9 100644
--- a/drivers/pci/ep/pcie-tegra-dw-ep.c
+++ b/drivers/pci/ep/pcie-tegra-dw-ep.c
@@ -282,8 +282,6 @@ enum ep_event {
282 EP_PEX_RST_ASSERT, 282 EP_PEX_RST_ASSERT,
283 EP_PEX_HOT_RST_DONE, 283 EP_PEX_HOT_RST_DONE,
284 EP_PEX_BME_CHANGE, 284 EP_PEX_BME_CHANGE,
285 EP_EVENT_EXIT,
286 EP_EVENT_INVALID,
287}; 285};
288 286
289enum margin_cmds { 287enum margin_cmds {
@@ -319,6 +317,7 @@ struct tegra_pcie_dw_ep {
319 int ep_state; 317 int ep_state;
320 struct phy **phy; 318 struct phy **phy;
321 struct task_struct *pcie_ep_task; 319 struct task_struct *pcie_ep_task;
320 struct mutex disable_lock;
322 wait_queue_head_t wq; 321 wait_queue_head_t wq;
323 DECLARE_KFIFO(event_fifo, u32, EVENT_QUEUE_LEN); 322 DECLARE_KFIFO(event_fifo, u32, EVENT_QUEUE_LEN);
324 u32 bar0_size; 323 u32 bar0_size;
@@ -579,8 +578,11 @@ static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw_ep *pcie)
579 u32 val = 0; 578 u32 val = 0;
580 int ret = 0, count = 0; 579 int ret = 0, count = 0;
581 580
582 if (pcie->ep_state == EP_STATE_DISABLED) 581 mutex_lock(&pcie->disable_lock);
582 if (pcie->ep_state == EP_STATE_DISABLED) {
583 mutex_unlock(&pcie->disable_lock);
583 return; 584 return;
585 }
584 586
585 /* disable LTSSM */ 587 /* disable LTSSM */
586 val = readl(pcie->appl_base + APPL_CTRL); 588 val = readl(pcie->appl_base + APPL_CTRL);
@@ -621,6 +623,7 @@ static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw_ep *pcie)
621 } 623 }
622 624
623 pcie->ep_state = EP_STATE_DISABLED; 625 pcie->ep_state = EP_STATE_DISABLED;
626 mutex_unlock(&pcie->disable_lock);
624 dev_info(pcie->dev, "EP deinit done\n"); 627 dev_info(pcie->dev, "EP deinit done\n");
625} 628}
626 629
@@ -947,13 +950,12 @@ static int pcie_ep_work_thread(void *p)
947 struct tegra_pcie_dw_ep *pcie = (struct tegra_pcie_dw_ep *)p; 950 struct tegra_pcie_dw_ep *pcie = (struct tegra_pcie_dw_ep *)p;
948 u32 event = 0; 951 u32 event = 0;
949 952
950 while (1) { 953 while (!kthread_should_stop()) {
951 wait_event_interruptible(pcie->wq, 954 wait_event_interruptible(pcie->wq,
952 !kfifo_is_empty(&pcie->event_fifo)); 955 !kfifo_is_empty(&pcie->event_fifo) ||
953 956 kthread_should_stop());
954 if (kthread_should_stop()) 957 if (kthread_should_stop())
955 break; 958 break;
956
957 if (!kfifo_get(&pcie->event_fifo, &event)) { 959 if (!kfifo_get(&pcie->event_fifo, &event)) {
958 dev_warn(pcie->dev, "empty kfifo\n"); 960 dev_warn(pcie->dev, "empty kfifo\n");
959 continue; 961 continue;
@@ -992,10 +994,8 @@ static void tegra_pcie_disable_phy(struct tegra_pcie_dw_ep *pcie)
992{ 994{
993 int phy_count = pcie->phy_count; 995 int phy_count = pcie->phy_count;
994 996
995 while (phy_count--) { 997 while (phy_count--)
996 phy_power_off(pcie->phy[phy_count]);
997 phy_exit(pcie->phy[phy_count]); 998 phy_exit(pcie->phy[phy_count]);
998 }
999} 999}
1000 1000
1001static int tegra_pcie_init_phy(struct tegra_pcie_dw_ep *pcie) 1001static int tegra_pcie_init_phy(struct tegra_pcie_dw_ep *pcie)
@@ -1424,6 +1424,7 @@ static int tegra_pcie_dw_ep_probe(struct platform_device *pdev)
1424 1424
1425 pcie->dev = &pdev->dev; 1425 pcie->dev = &pdev->dev;
1426 pcie->ep_state = EP_STATE_DISABLED; 1426 pcie->ep_state = EP_STATE_DISABLED;
1427 mutex_init(&pcie->disable_lock);
1427 1428
1428 ret = of_property_read_u32(np, "num-lanes", &pcie->num_lanes); 1429 ret = of_property_read_u32(np, "num-lanes", &pcie->num_lanes);
1429 if (ret < 0) { 1430 if (ret < 0) {
@@ -1777,9 +1778,10 @@ static int tegra_pcie_dw_ep_remove(struct platform_device *pdev)
1777 1778
1778 debugfs_remove_recursive(pcie->debugfs); 1779 debugfs_remove_recursive(pcie->debugfs);
1779 1780
1780 if (!kfifo_put(&pcie->event_fifo, EP_EVENT_EXIT))
1781 dev_err(pcie->dev, "EVENT: fifo is full\n");
1782 kthread_stop(pcie->pcie_ep_task); 1781 kthread_stop(pcie->pcie_ep_task);
1782 pex_ep_event_pex_rst_assert(pcie);
1783
1784 pm_runtime_disable(pcie->dev);
1783 1785
1784 tegra_bwmgr_unregister(pcie->emc_bw); 1786 tegra_bwmgr_unregister(pcie->emc_bw);
1785 1787