[PATCH v4] PCI: mediatek: Fix integer truncation and handle oversized resources

Manivannan Sadhasivam mani at kernel.org
Tue Oct 27 06:11:32 PDT 2026


On Wed, Sep 30, 2026 at 12:05:39PM +0000, Sreeraj S Kurup wrote:
> resource_size() returns a resource_size_t, which is 64-bit on 64-bit
> architectures or 32-bit systems with LPAE/PAE enabled. Passing this
> directly to fls(), which accepts an unsigned int, implicitly
> truncates the upper 32 bits.
> 
> Furthermore, AHB2PCIE_SIZE() uses a 5-bit mask GENMASK(4, 0). If a
> resource size exceeds 2 GiB (order > 31), the log2 size order
> overflows the 5-bit mask. Clamping the value silently truncates the
> hardware window while leaving the OS resource intact, causing bus
> errors when accessing BARs in the unmapped upper region.
> 
> Fix this by using fls64(size - 1) to accurately calculate log2 size
> orders without off-by-one errors and returning -EINVAL if the resource
> size exceeds the maximum supported 31-bit window order.
> 
> Signed-off-by: Sreeraj S Kurup <sreekuttan2156239 at gmail.com>
> ---
>  drivers/pci/controller/pcie-mediatek.c | 29 ++++++++++++++++++++++++--
>  1 file changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
> index a60d1ae076f8..639884b22ad7 100644
> --- a/drivers/pci/controller/pcie-mediatek.c
> +++ b/drivers/pci/controller/pcie-mediatek.c
> @@ -8,6 +8,7 @@
>   */
>  
>  #include <linux/bitfield.h>
> +#include <linux/bitops.h>
>  #include <linux/clk.h>
>  #include <linux/delay.h>
>  #include <linux/errno.h>
> @@ -686,6 +687,8 @@ static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port)
>  	const struct mtk_pcie_soc *soc = port->pcie->soc;
>  	u32 val;
>  	int err;
> +	resource_size_t size;
> +	int size_order;
>  
>  	entry = resource_list_first_type(&host->windows, IORESOURCE_MEM);
>  	if (entry)
> @@ -753,8 +756,18 @@ static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port)
>  		mtk_pcie_enable_msi(port);
>  
>  	/* Set AHB to PCIe translation windows */
> +	size = resource_size(mem);
> +	if (!size)
> +		return -EINVAL;

PCI core already rejects the zero sized MEM regions. So this check is a dead
code.

> +
> +	size_order = fls64(size - 1);

This is wrong. AHB2PCIE_SIZE() register needs the full size value to enable the
whole window. Check:

c61df57343bf ("PCI: mediatek: Fix memory mapped IO range size computation")

> +	if (size_order > 31) {
> +		dev_err(pcie->dev, "Memory resource size too large: %pa\n", &size);
> +		return -EINVAL;
> +	}
> +
>  	val = lower_32_bits(mem->start) |
> -	      AHB2PCIE_SIZE(fls(resource_size(mem)));
> +	      AHB2PCIE_SIZE(size_order);

Why can't you just do, fls64(resource_size(mem))?

- Mani

-- 
மணிவண்ணன் சதாசிவம்



More information about the Linux-mediatek mailing list