summaryrefslogtreecommitdiff
path: root/drivers/pci/host/pci-msm.c
diff options
context:
space:
mode:
authorTony Truong <truong@codeaurora.org>2015-09-09 15:08:43 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:09:29 -0700
commit7a18379427ef530d391cd414be9bf89d241cba56 (patch)
tree1c6128228a01240346d658fe73da019553320856 /drivers/pci/host/pci-msm.c
parentab935b69aaaf2277b02313a86ed0c16255dab514 (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.c18
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);