diff options
author | Achal Verma <achalv@nvidia.com> | 2020-03-27 07:52:59 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2020-03-31 11:39:03 -0400 |
commit | 4313f4cf073dffd094dfb31fe5416dcc32b73462 (patch) | |
tree | 2fc36ab35d11086f0ccc412f92d1f7457033c48e | |
parent | 92f6db5e541437fbc3cfea3ee3d426c274a16b59 (diff) |
pcie-tegra-dw-ep:fix 'out of bound access'
correct range in find_first_bit.
This fixes coverity issue: 5755194
Bug 2028892
Change-Id: I73d83aa667290f4b39a7fece92eafbedab572763
Signed-off-by: Achal Verma <achalv@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2319434
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Dmitry Pervushin <dpervushin@nvidia.com>
Reviewed-by: Phoenix Jung <pjung@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r-- | drivers/pci/ep/pcie-tegra-dw-ep.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/pci/ep/pcie-tegra-dw-ep.c b/drivers/pci/ep/pcie-tegra-dw-ep.c index 2ea27adff..d9e599544 100644 --- a/drivers/pci/ep/pcie-tegra-dw-ep.c +++ b/drivers/pci/ep/pcie-tegra-dw-ep.c | |||
@@ -892,10 +892,29 @@ static void pex_ep_event_hot_rst_done(struct tegra_pcie_dw_ep *pcie) | |||
892 | writel(val, pcie->appl_base + APPL_CTRL); | 892 | writel(val, pcie->appl_base + APPL_CTRL); |
893 | } | 893 | } |
894 | 894 | ||
895 | static inline int find_width_index(unsigned long width) | ||
896 | { | ||
897 | if (width & (width-1)) | ||
898 | return -1; | ||
899 | switch (width) { | ||
900 | case PCIE_LNK_X1: | ||
901 | return 0; | ||
902 | case PCIE_LNK_X2: | ||
903 | return 1; | ||
904 | case PCIE_LNK_X4: | ||
905 | return 2; | ||
906 | case PCIE_LNK_X8: | ||
907 | return 3; | ||
908 | default : | ||
909 | return -1; | ||
910 | } | ||
911 | } | ||
912 | |||
895 | static void pex_ep_event_bme_change(struct tegra_pcie_dw_ep *pcie) | 913 | static void pex_ep_event_bme_change(struct tegra_pcie_dw_ep *pcie) |
896 | { | 914 | { |
897 | u32 val = 0, speed = 0; | 915 | u32 val = 0, speed = 0; |
898 | unsigned long freq, width = 0; | 916 | unsigned long freq, width = 0; |
917 | int width_index; | ||
899 | 918 | ||
900 | /* If EP doesn't advertise L1SS, just return */ | 919 | /* If EP doesn't advertise L1SS, just return */ |
901 | val = readl(pcie->dbi_base + pcie->cfg_link_cap_l1sub); | 920 | val = readl(pcie->dbi_base + pcie->cfg_link_cap_l1sub); |
@@ -932,7 +951,13 @@ static void pex_ep_event_bme_change(struct tegra_pcie_dw_ep *pcie) | |||
932 | /* Make EMC FLOOR freq request based on link width and speed */ | 951 | /* Make EMC FLOOR freq request based on link width and speed */ |
933 | val = readl(pcie->dbi_base + CFG_LINK_STATUS_CONTROL); | 952 | val = readl(pcie->dbi_base + CFG_LINK_STATUS_CONTROL); |
934 | width = ((val >> 16) & PCI_EXP_LNKSTA_NLW) >> 4; | 953 | width = ((val >> 16) & PCI_EXP_LNKSTA_NLW) >> 4; |
935 | width = find_first_bit(&width, sizeof(width)); | 954 | width_index = find_width_index(width); |
955 | if (width_index == -1) { | ||
956 | dev_err(pcie->dev, "error in %s", __func__); | ||
957 | dev_err(pcie->dev, "width in CFG_LINK_STATUS_CONTROL is" | ||
958 | "wrong\n"); | ||
959 | return; | ||
960 | } | ||
936 | speed = ((val >> 16) & PCI_EXP_LNKSTA_CLS); | 961 | speed = ((val >> 16) & PCI_EXP_LNKSTA_CLS); |
937 | freq = pcie->dvfs_tbl[width][speed - 1]; | 962 | freq = pcie->dvfs_tbl[width][speed - 1]; |
938 | dev_dbg(pcie->dev, "EMC Freq requested = %lu\n", freq); | 963 | dev_dbg(pcie->dev, "EMC Freq requested = %lu\n", freq); |