diff options
author | Tony Truong <truong@codeaurora.org> | 2015-02-27 15:18:31 -0800 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:09:09 -0700 |
commit | 5e37fdc3f1d2f3b6f3057fb3763209e36483566f (patch) | |
tree | 3f722e03e8675871002c67ca463c7498b90965f9 /drivers/pci/host | |
parent | 3dabd56768212753e48d76bad64f0a82c20c26d3 (diff) |
msm: pcie: sanity check when calculating EP CAP offset
When searching for the endpoint's capabilities register,
check that the value from the register read is valid.
Change-Id: Ia64de3c75618ca0a51aa4588ac97f2fcb26d8829
Signed-off-by: Tony Truong <truong@codeaurora.org>
Diffstat (limited to 'drivers/pci/host')
-rw-r--r-- | drivers/pci/host/pci-msm.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index 744291eea457..4a53e7eb5a30 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -1057,6 +1057,19 @@ static int msm_pcie_restore_sec_config(struct msm_pcie_dev_t *dev) return 0; } +static inline int msm_pcie_check_align(struct msm_pcie_dev_t *dev, + u32 offset) +{ + if (offset % 4) { + PCIE_ERR(dev, + "PCIe: RC%d: offset 0x%x is not correctly aligned\n", + dev->rc_idx, offset); + return MSM_PCIE_ERROR; + } + + return 0; +} + static bool msm_pcie_confirm_linkup(struct msm_pcie_dev_t *dev, bool check_sw_stts, bool check_ep) @@ -2762,6 +2775,9 @@ static void msm_pcie_config_link_state(struct msm_pcie_dev_t *dev) current_offset = readl_relaxed(dev->conf + PCIE_CAP_PTR_OFFSET) & 0xff; while (current_offset) { + if (msm_pcie_check_align(dev, current_offset)) + return; + val = readl_relaxed(dev->conf + current_offset); if ((val & 0xff) == PCIE20_CAP_ID) { ep_link_cap_offset = current_offset + 0x0c; @@ -2867,6 +2883,9 @@ static void msm_pcie_config_link_state(struct msm_pcie_dev_t *dev) if (dev->l1ss_supported) { current_offset = PCIE_EXT_CAP_OFFSET; while (current_offset) { + if (msm_pcie_check_align(dev, current_offset)) + return; + val = readl_relaxed(dev->conf + current_offset); if ((val & 0xffff) == L1SUB_CAP_ID) { ep_l1sub_cap_reg1_offset = current_offset + 0x4; @@ -3506,6 +3525,9 @@ static void msm_pcie_config_ep_aer(struct msm_pcie_dev_t *dev, 0xff; while (current_offset) { + if (msm_pcie_check_align(dev, current_offset)) + return; + val = readl_relaxed(ep_base + current_offset); if ((val & 0xff) == PCIE20_CAP_ID) { ep_dev_info->dev_ctrlstts_offset = |