From 2172c01a6d89328466cf22078ccd74ada07153a5 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Uppala Date: Wed, 8 Feb 2023 14:46:46 +0000 Subject: [PATCH] ethernet: Get VM IRQ config sequence from nvidia,vm-irq-id Ethernet driver expect the VM IRQ configuration. The VM IRQ is provided with the property "interrupt" which have multiple VM irq numbers and their configurations via the vm irq configuration node which is referred by property "nvidia,vm-irq-config". The vm irq configuration node have the configuration of all VM IRQ and each configuration is separated with the child node like below. ethernet@6800000 { nvidia,vm-irq-config = <&mgbe_vm_irq_config>; } mgbe_vm_irq_config: mgbe-vm-irq-config { nvidia,num-vm-irqs = <5>; vm_irq1 { nvidia,num-vm-channels = <2>; nvidia,vm-channels = <0 1>; nvidia,vm-num = <0>; nvidia,vm-irq-id = <0>; }; vm_irq2 { nvidia,num-vm-channels = <2>; nvidia,vm-channels = <2 3>; nvidia,vm-num = <1>; nvidia,vm-irq-id = <1>; }; vm_irq3 { nvidia,num-vm-channels = <2>; nvidia,vm-channels = <4 5>; nvidia,vm-num = <2>; nvidia,vm-irq-id = <2>; }; vm_irq4 { nvidia,num-vm-channels = <2>; nvidia,vm-channels = <6 7>; nvidia,vm-num = <3>; nvidia,vm-irq-id = <3>; }; vm_irq5 { nvidia,num-vm-channels = <2>; nvidia,vm-channels = <8 9>; nvidia,vm-num = <4>; nvidia,vm-irq-id = <4>; }; }; }; The child 1(vm_irq1) is link with the VM IRQ 1 listed in interrupt property, next child which is vm_irq2 is link with the 2nd VM irq. So, the order of VM configuration child must be in same order as VM IRQ provided in the property interrupt. If the irq configuration order i..e child order is not matching with VM irq number then there is interrupt issue. Now, if the VM IRQ config child nodes are provided in base DT file in same order then the ethernet works fine. But when applying via overlay, it does not work. This is because of overlay technique. The overlay logic is such that it iterates all child node in overlay and apply the child as first child of target node. Hence the child sequence provided in overlay fragment is applied in reverse order in target node. This causes the irq configuration order not matching with VM IRQs. To address the overlay issue, read the sequence of interrupt in property "interrupt" from the newly added property "nvidia,vm-irq-id" of each child. This way child node sequence does not matter, and sequence is identified by property. Bug 3956724 Change-Id: I5c08edcd8a7e8d3112618dd23050d8b5c10ddc59 Signed-off-by: Revanth Kumar Uppala Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2855639 Reviewed-by: Bhadram Varka Reviewed-by: Narayan Reddy Reviewed-by: Laxman Dewangan GVS: Gerrit_Virtual_Submit --- .../ethernet/nvidia/nvethernet/ether_linux.c | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c index c4ac0282..07af3788 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c @@ -4374,7 +4374,7 @@ static int ether_get_vm_irq_data(struct platform_device *pdev, struct osi_core_priv_data *osi_core = pdata->osi_core; struct device_node *vm_node, *temp; unsigned int i, j, node = 0; - int ret = 0; + int vm_irq_id, child_id, ret =0; vm_node = of_parse_phandle(pdev->dev.of_node, "nvidia,vm-irq-config", 0); @@ -4414,10 +4414,24 @@ static int ether_get_vm_irq_data(struct platform_device *pdev, return -EINVAL; } + child_id = 0; for_each_child_of_node(vm_node, temp) { - if (node == osi_core->num_vm_irqs) + ret = of_property_read_u32(temp, "nvidia,vm-irq-id", &vm_irq_id); + if (ret != 0) { + vm_irq_id = child_id; + } + + if (vm_irq_id >= osi_core->num_vm_irqs) break; + node = vm_irq_id; + + ret = of_property_read_u32(temp, "nvidia,vm-num", &osi_core->irq_data[node].vm_num); + if (ret != 0) { + dev_err(&pdev->dev, "failed to read VM Number\n"); + return ret; + } + ret = of_property_read_u32(temp, "nvidia,num-vm-channels", &osi_core->irq_data[node].num_vm_chans); if (ret != 0) { @@ -4433,21 +4447,15 @@ static int ether_get_vm_irq_data(struct platform_device *pdev, dev_err(&pdev->dev, "failed to get VM channels\n"); return ret; } + child_id++; + } - ret = of_property_read_u32(temp, "nvidia,vm-num", - &osi_core->irq_data[node].vm_num); - if (ret != 0) { - dev_err(&pdev->dev, "failed to read VM Number\n"); - return ret; - } - + for (node = 0; node < osi_core->num_vm_irqs; node++) { ether_set_vm_irq_chan_mask(&pdata->vm_irq_data[node], osi_core->irq_data[node].num_vm_chans, osi_core->irq_data[node].vm_chans); pdata->vm_irq_data[node].pdata = pdata; - - node++; } for (i = 0, j = 1; i < osi_core->num_vm_irqs; i++, j++) {