diff options
author | Tony Truong <truong@codeaurora.org> | 2015-09-09 15:08:43 -0700 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:09:29 -0700 |
commit | 7a18379427ef530d391cd414be9bf89d241cba56 (patch) | |
tree | 1c6128228a01240346d658fe73da019553320856 /drivers/pci/host/pci-msm.c | |
parent | ab935b69aaaf2277b02313a86ed0c16255dab514 (diff) |
msm: pcie: add locks to protect PCIe common PHY init and deinit
The counter for the number of active root complexes
determines when PCIe common PHY should be powered on/off.
To avoid conflicts and a stale counter, add locks to protect
the access to PCIe common PHY.
Change-Id: I18ec54e52e804eb132f9c5c0270455dbc9187151
Signed-off-by: Tony Truong <truong@codeaurora.org>
Diffstat (limited to 'drivers/pci/host/pci-msm.c')
-rw-r--r-- | drivers/pci/host/pci-msm.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index a621684f8478..716e7d3c7aae 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -572,6 +572,9 @@ static ulong corr_counter_limit = 5; /* counter to keep track if common PHY needs to be configured */ static u32 num_rc_on; +/* global lock for PCIe common PHY */ +static struct mutex com_phy_lock; + /* Table to track info of PCIe devices */ static struct msm_pcie_device_info msm_pcie_dev_tbl[MAX_RC_NUM * MAX_DEVICE_NUM]; @@ -3664,10 +3667,14 @@ int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT, 0, BIT(31)); } + mutex_lock(&com_phy_lock); /* init PCIe PHY */ if (!num_rc_on) pcie_phy_init(dev); + num_rc_on++; + mutex_unlock(&com_phy_lock); + if (options & PM_PIPE_CLK) { usleep_range(PHY_STABILIZATION_DELAY_US_MIN, PHY_STABILIZATION_DELAY_US_MAX); @@ -3763,7 +3770,6 @@ int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) dev->power_on = true; dev->suspending = false; dev->link_turned_on_counter++; - num_rc_on++; goto out; @@ -3775,12 +3781,17 @@ link_fail: PCIE_N_SW_RESET(dev->rc_idx, dev->common_phy), 0x1); msm_pcie_write_reg(dev->phy, PCIE_N_POWER_DOWN_CONTROL(dev->rc_idx, dev->common_phy), 0); + + mutex_lock(&com_phy_lock); + num_rc_on--; if (!num_rc_on) { PCIE_DBG(dev, "PCIe: RC%d is powering down the common phy\n", dev->rc_idx); msm_pcie_write_reg(dev->phy, PCIE_COM_SW_RESET, 0x1); msm_pcie_write_reg(dev->phy, PCIE_COM_POWER_DOWN_CONTROL, 0); } + mutex_unlock(&com_phy_lock); + msm_pcie_pipe_clk_deinit(dev); msm_pcie_clk_deinit(dev); clk_fail: @@ -3810,7 +3821,6 @@ void msm_pcie_disable(struct msm_pcie_dev_t *dev, u32 options) dev->link_status = MSM_PCIE_LINK_DISABLED; dev->power_on = false; dev->link_turned_off_counter++; - num_rc_on--; PCIE_INFO(dev, "PCIe: Assert the reset of endpoint of RC%d.\n", dev->rc_idx); @@ -3823,12 +3833,15 @@ void msm_pcie_disable(struct msm_pcie_dev_t *dev, u32 options) msm_pcie_write_reg(dev->phy, PCIE_N_POWER_DOWN_CONTROL(dev->rc_idx, dev->common_phy), 0); + mutex_lock(&com_phy_lock); + num_rc_on--; if (!num_rc_on) { PCIE_DBG(dev, "PCIe: RC%d is powering down the common phy\n", dev->rc_idx); msm_pcie_write_reg(dev->phy, PCIE_COM_SW_RESET, 0x1); msm_pcie_write_reg(dev->phy, PCIE_COM_POWER_DOWN_CONTROL, 0); } + mutex_unlock(&com_phy_lock); if (options & PM_CLK) { msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_CTRL, 0, @@ -5364,6 +5377,7 @@ int __init pcie_init(void) pcie_drv.rc_num = 0; mutex_init(&pcie_drv.drv_lock); + mutex_init(&com_phy_lock); for (i = 0; i < MAX_RC_NUM; i++) { snprintf(rc_name, MAX_RC_NAME_LEN, "pcie%d-short", i); |