[PATCH] PCI: mediatek-gen3: Initialize all resources before installing ISR

Manivannan Sadhasivam mani at kernel.org
Wed Jul 29 07:16:53 PDT 2026


On Thu, Jul 16, 2026 at 01:31:42PM +0200, AngeloGioacchino Del Regno wrote:
> If the bootloader leaves the PCI-Express MAC+PHY enabled before
> booting the kernel, an interrupt may be pending while probing
> this driver, which means that the chained interrupt handler is
> called as soon as the irq is enabled and handler is installed.
> 
> Since the mtk_gen3_pcie structure gets fully initialized only
> after installing the handler, that condition results in a NULL
> pointer kernel panic (mostly due to pcie->base being NULL, but
> other members will be uninitialized as well).
> 
> In order to resolve this, disgregate the mtk_pcie_setup_irq()
> function and partially do the same to mtk_pcie_setup(), so that
> all of the required resources are initialized before installing
> and enabling the interrupt handler.
> 
> Also, install the ISR after deasserting resets and powering up
> the PCI-Express MAC and PHY, by moving the call to the function
> irq_set_chained_handler_and_data() to the appropriate place in
> mtk_pcie_setup(), as hardware registers cannot be modified if
> the hardware is powered down and could result in a SError.
> 
> This makes sure that all resources are actually available and
> hardware is powered on before any registers operation is done.
> 
> Fixes: eddbac092e5f ("PCI: mediatek-gen3: Move mtk_pcie_setup_irq() out of mtk_pcie_setup()")
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> ---
> 
> The real issue starts with commit eddbac092e5f but this still goes
> a bit further by reordering things a bit, enabling the interrupt
> after powerup and but before port startup, along with getting the
> irq in mtk_pcie_parse_port(), where a bunch of other devicetree
> resources retrieval is done, grouping them in one place.
> 
> This actually resolves the following issue:
> 
> <6>[    6.877824] mtk-pcie-gen3 16910000.pcie: host bridge /soc/pcie at 16910000 ranges:
> <6>[    6.877854] mtk-pcie-gen3 16910000.pcie:      MEM 0x0050000000..0x0057ffffff -> 0x0050000000
> <1>[    6.877972] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000184

These error logs should be part of the patch description. Please trim it as per:
Documentation/process/submitting-patches.rst

> <1>[    6.877978] Mem abort info:
> <1>[    6.877980]   ESR = 0x0000000096000004
> <1>[    6.877983]   EC = 0x25: DABT (current EL), IL = 32 bits
> <1>[    6.877988]   SET = 0, FnV = 0
> <1>[    6.877991]   EA = 0, S1PTW = 0
> <1>[    6.877993]   FSC = 0x04: level 0 translation fault
> <1>[    6.877996] Data abort info:
> <1>[    6.877998]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
> <1>[    6.878001]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> <1>[    6.878005]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> <1>[    6.878008] [0000000000000184] user address but active_mm is swapper
> <0>[    6.878012] Internal error: Oops: 0000000096000004 [#1]  SMP
> <4>[    6.878018] Modules linked in:
> <4>[    6.878027] CPU: 0 UID: 0 PID: 82 Comm: kworker/u32:3 Tainted: G        W           7.1.0-rc5-next-20260525+ #1700 PREEMPT(full) 
> <4>[    6.878037] Tainted: [W]=WARN
> <4>[    6.878040] Hardware name: Google Hylia SKU1/2/4/5 board (DT)
> <4>[    6.878044] Workqueue: async async_run_entry_fn
> <4>[    6.878060] pstate: 034000c9 (nzcv daIF +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
> <4>[    6.878068] pc : mtk_pcie_irq_handler+0x40/0x1f0
> <4>[    6.878082] lr : handle_irq_desc+0x3c/0x68
> <4>[    6.878095] sp : ffff800080003f50
> <4>[    6.878098] x29: ffff800080003f50 x28: ffff000080b7d3c0 x27: 0000000000000000
> <4>[    6.878109] x26: ffffcc9bfd8ca990 x25: 0000000000000000 x24: ffff000080204a05
> <4>[    6.878117] x23: 0000000043400009 x22: ffffcc9bfb60793c x21: 0000000000000000
> <4>[    6.878125] x20: 0000000000000000 x19: 0000000000000184 x18: 00000000ffffffff
> <4>[    6.878133] x17: ffff3367f0734000 x16: ffff800080000000 x15: 00000000ffffffff
> <4>[    6.878140] x14: ffff000081866bd3 x13: ffff000081866bd5 x12: 0000000000000020
> <4>[    6.878147] x11: 0000000000000040 x10: ffff0000802136a8 x9 : ffffcc9bf9da34c4
> <4>[    6.878155] x8 : ffff000083149020 x7 : 0000000000000000 x6 : 0000000000000000
> <4>[    6.878162] x5 : ffff000083148ff8 x4 : ffff0000831491a8 x3 : 0000000000000000
> <4>[    6.878169] x2 : 0000000000000000 x1 : ffffcc9bfa594188 x0 : ffff000080b4c830
> <4>[    6.878177] Call trace:
> <4>[    6.878180]  mtk_pcie_irq_handler+0x40/0x1f0 (P)
> <4>[    6.878192]  handle_irq_desc+0x3c/0x68
> <4>[    6.878204]  generic_handle_domain_irq+0x20/0x40
> <4>[    6.878217]  gic_handle_irq+0x144/0x2c0
> <4>[    6.878224]  call_on_irq_stack+0x30/0x48
> <4>[    6.878231]  do_interrupt_handler+0x88/0x98
> <4>[    6.878239]  el1_interrupt+0x48/0xb0
> <4>[    6.878252]  el1h_64_irq_handler+0x18/0x28
> <4>[    6.878264]  el1h_64_irq+0x84/0x88
> <4>[    6.878271]  _raw_spin_unlock_irqrestore+0x14/0x68 (P)
> <4>[    6.878283]  irq_set_chained_handler_and_data+0xc8/0xe0
> <4>[    6.878294]  mtk_pcie_probe+0x98/0x4b0
> <4>[    6.878304]  platform_probe+0x64/0xc0
> <4>[    6.878317]  really_probe+0xc8/0x3f0
> <4>[    6.878327]  __driver_probe_device+0x168/0x1d8
> <4>[    6.878337]  driver_probe_device+0x44/0x128
> <4>[    6.878347]  __device_attach_driver+0xc4/0x198
> <4>[    6.878357]  bus_for_each_drv+0x8c/0xf8
> <4>[    6.878365]  __device_attach_async_helper+0xbc/0x148
> <4>[    6.878375]  async_run_entry_fn+0x3c/0x188
> <4>[    6.878385]  process_one_work+0x164/0x4f0
> <4>[    6.878391]  worker_thread+0x19c/0x320
> <4>[    6.878396]  kthread+0x138/0x150
> <4>[    6.878407]  ret_from_fork+0x10/0x20
> <0>[    6.878416] Code: 9100c000 f90037e0 f9400793 91061273 (b9400273) 
> <4>[    6.878421] ---[ end trace 0000000000000000 ]---
> <0>[    6.891047] Kernel panic - not syncing: Oops: Fatal exception in interrupt
> <2>[    6.891051] SMP: stopping secondary CPUs
> <0>[    6.893869] Kernel Offset: 0x4c9b79c00000 from 0xffff800080000000
> <0>[    6.893873] PHYS_OFFSET: 0x80000000
> <0>[    6.893874] CPU features: 0x08000000,003c018b,a6c605a1,357e7663
> <0>[    6.893879] Memory Limit: none
> <0>[    7.258223] ---[ end Kernel panic - not syncing: Oops: Fatal exception in interrupt ]---
> 
> 
>  drivers/pci/controller/pcie-mediatek-gen3.c | 44 ++++++++-------------
>  1 file changed, 16 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c
> index 66c33a09dd95..2c28b8e983c3 100644
> --- a/drivers/pci/controller/pcie-mediatek-gen3.c
> +++ b/drivers/pci/controller/pcie-mediatek-gen3.c
> @@ -903,25 +903,6 @@ static void mtk_pcie_irq_handler(struct irq_desc *desc)
>  	chained_irq_exit(irqchip, desc);
>  }
>  
> -static int mtk_pcie_setup_irq(struct mtk_gen3_pcie *pcie)
> -{
> -	struct device *dev = pcie->dev;
> -	struct platform_device *pdev = to_platform_device(dev);
> -	int err;
> -
> -	pcie->irq = platform_get_irq(pdev, 0);
> -	if (pcie->irq < 0)
> -		return pcie->irq;
> -
> -	err = mtk_pcie_init_irq_domains(pcie);
> -	if (err)
> -		return err;
> -
> -	irq_set_chained_handler_and_data(pcie->irq, mtk_pcie_irq_handler, pcie);
> -
> -	return 0;
> -}
> -
>  static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
>  {
>  	int i, ret, num_resets = pcie->soc->phy_resets.num_resets;
> @@ -939,6 +920,10 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
>  
>  	pcie->reg_base = regs->start;
>  
> +	pcie->irq = platform_get_irq(pdev, 0);
> +	if (pcie->irq < 0)
> +		return pcie->irq;
> +
>  	for (i = 0; i < num_resets; i++)
>  		pcie->phy_resets[i].id = pcie->soc->phy_resets.id[i];
>  
> @@ -1175,10 +1160,6 @@ static int mtk_pcie_setup(struct mtk_gen3_pcie *pcie)
>  {
>  	int err, max_speed;
>  
> -	err = mtk_pcie_parse_port(pcie);
> -	if (err)
> -		return err;
> -
>  	/*
>  	 * Deassert the line in order to avoid unbalance in deassert_count
>  	 * counter since the bulk is shared.
> @@ -1205,6 +1186,9 @@ static int mtk_pcie_setup(struct mtk_gen3_pcie *pcie)
>  		}
>  	}
>  
> +	/* All resources are now available: install the chained handler */
> +	irq_set_chained_handler_and_data(pcie->irq, mtk_pcie_irq_handler, pcie);

As Sashiko pointed out, 'msi_set->base' is not set at this point.

- Mani

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



More information about the Linux-mediatek mailing list