Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3bb65a0c authored by Vivek Pernamitta's avatar Vivek Pernamitta Committed by Gerrit - the friendly Code Review server
Browse files

msm: pci : Avoid deadlock with recovery and enemurate lock



Avoid deadlock scenario when wake interrupt arrives at enumeration
time and holds recovery lock and wake handler workqueue tries to
acquire enumeration lock. In parallel client driver can call
msm_pcie_pm_control for suspend where enumeration lock could
be successfully acquired by msm_pcie_pm_control instead by wake
handler and waiting for recovery lock which is currently acquired
by wake handler (which is currently waiting for enumertion lock)
which could leads to deadlock scenario.

msm_pcie_enumerate		wake handler		pm_control
	|			     |    	     (suspend thread)
	|			     |			   |
	|			     x acquired 	   |
	x acquired		     | recovery lock	   |
	| enumerate lock	     |  		   |
	|			     o waiting for	   |
  	|			       enumerate lock      |
	x released					   x acquired
	| enumerate lock			  	   | enumerate lock
							   |
							   o waiting for
							     recovery lock

we have fixed the order of locking in msm_pcie_pm_control to avoid
deadlock scenario.

Change-Id: Ifc72c643f7c0793cfa10a953723e953ce73a82b6
Signed-off-by: default avatarVivek Pernamitta <vpernami@codeaurora.org>
parent 774e9013
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -7898,6 +7898,7 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,
			break;
		}

		mutex_lock(&pcie_dev->recovery_lock);
		mutex_lock(&pcie_dev->enumerate_lock);

		/*
@@ -7928,12 +7929,12 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,
				 "PCIe: RC%d: request to suspend the link is rejected\n",
				 pcie_dev->rc_idx);
			mutex_unlock(&pcie_dev->enumerate_lock);
			mutex_unlock(&pcie_dev->recovery_lock);
			break;
		}

		pcie_dev->user_suspend = true;

		mutex_lock(&pcie_dev->recovery_lock);

		ret = msm_pcie_pm_suspend(dev, user, data, options);
		if (ret) {
@@ -7949,9 +7950,9 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,
			}
		}

		mutex_unlock(&pcie_dev->recovery_lock);

		mutex_unlock(&pcie_dev->enumerate_lock);

		mutex_unlock(&pcie_dev->recovery_lock);
		break;
	case MSM_PCIE_RESUME:
		PCIE_DBG(pcie_dev,
@@ -7964,6 +7965,8 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,
			break;
		}

		mutex_lock(&pcie_dev->recovery_lock);

		/* when link was suspended and link resume is requested */
		mutex_lock(&pcie_dev->enumerate_lock);
		list_for_each_entry(dev_info_itr, &pcie_dev->susp_ep_list,
@@ -7990,10 +7993,10 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,
			PCIE_ERR(pcie_dev,
				 "PCIe: RC%d: requested to resume when link is already powered on.\n",
				 pcie_dev->rc_idx);
			mutex_unlock(&pcie_dev->recovery_lock);
			break;
		}

		mutex_lock(&pcie_dev->recovery_lock);
		ret = msm_pcie_pm_resume(dev, user, data, options);
		if (ret) {
			PCIE_ERR(pcie_dev,