[PATCH 0/7] PCI irq mapping fixes and cleanups
Tim Harvey
tharvey at gateworks.com
Mon Mar 3 18:40:43 EST 2014
On Mon, Mar 3, 2014 at 9:49 AM, Tim Harvey <tharvey at gateworks.com> wrote:
> On Mon, Mar 3, 2014 at 12:11 AM, Jingoo Han <jg1.han at samsung.com> wrote:
>> On Sunday, March 02, 2014 3:31 AM, Jason Gunthorpe wrote:
>>> On Fri, Feb 28, 2014 at 04:53:33PM -0800, Tim Harvey wrote:
>>>
<snip>
> The configuration I'm testing is:
> root at OpenWrt:/# lspci -n
> 00:00.0 0604: 16c3:abcd (rev 01)
> 01:00.0 0604: 10b5:8609 (rev ba)
> 01:00.1 0880: 10b5:8609 (rev ba)
> 02:01.0 0604: 10b5:8609 (rev ba)
> 02:04.0 0604: 10b5:8609 (rev ba)
> 02:05.0 0604: 10b5:8609 (rev ba)
> 02:06.0 0604: 10b5:8609 (rev ba)
> 02:07.0 0604: 10b5:8609 (rev ba)
> 02:08.0 0604: 10b5:8609 (rev ba)
> 02:09.0 0604: 10b5:8609 (rev ba)
> 07:00.0 0280: 168c:002b (rev 01)
> 08:00.0 0200: 11ab:4380
> root at OpenWrt:/# lspci -tnv
> -[0000:00]---00.0-[01-09]--+-00.0-[02-09]--+-01.0-[03]--
> | +-04.0-[04]--
> | +-05.0-[05]--
> | +-06.0-[06]--
> | +-07.0-[07]----00.0 168c:002b
> | +-08.0-[08]----00.0 11ab:4380
> | \-09.0-[09]--
> \-00.1 10b5:8609
>
>
> The dev_info showing what of_irq_parse_and_map_pci() above produces:
> [ 1.818485] pci 0000:00:00.0: dw_pcie_map_irq: 16c3:abcd slot0 pin1 irq20
> [ 1.818703] pci 0000:01:00.0: dw_pcie_map_irq: 10b5:8609 slot0 pin1 irq20
> [ 1.818939] pci 0000:01:00.1: dw_pcie_map_irq: 10b5:8609 slot0 pin2 irq0
> [ 1.819179] pci 0000:02:01.0: dw_pcie_map_irq: 10b5:8609 slot0 pin2 irq0
> [ 1.819395] pci 0000:02:04.0: dw_pcie_map_irq: 10b5:8609 slot0 pin1 irq20
> [ 1.819631] pci 0000:02:05.0: dw_pcie_map_irq: 10b5:8609 slot0 pin2 irq0
> [ 1.819859] pci 0000:02:06.0: dw_pcie_map_irq: 10b5:8609 slot0 pin3 irq0
> [ 1.820087] pci 0000:02:07.0: dw_pcie_map_irq: 10b5:8609 slot0 pin4 irq0
> [ 1.820404] pci 0000:02:08.0: dw_pcie_map_irq: 10b5:8609 slot0 pin1 irq20
> [ 1.820650] pci 0000:02:09.0: dw_pcie_map_irq: 10b5:8609 slot0 pin2 irq0
> [ 1.820881] pci 0000:07:00.0: dw_pcie_map_irq: 168c:002b slot0 pin4 irq0
> [ 1.821100] pci 0000:08:00.0: dw_pcie_map_irq: 11ab:4380 slot0 pin1 irq20
>
> I'm not clear why irq 20 is getting returned for all the slots with
> (slot%4)=0 and func=0. If I start debugging of_irq_parse_pci() I see
> that it walks up the tree until it gets to the pcie host controller
> then calls of_irq_parse_raw() which is returning irq20 or -EINVAL.
For the slots above that are swizzling to pin1 this appears to be an
issue with irq_create_of_mapping() called form
of_irq_parse_and_map_pci(). The GIC function that translates the
interrupt per domain is given irq_data: 0x123 0x04 0x00 (meaning GIC
IRQ 123, which should get 32 added to it for irq155). Instead, the
implementation of gic_irq_domain_xlate()
(http://lxr.missinglinkelectronics.com/linux/drivers/irqchip/irq-gic.c#L832)
adds 32 to the 0x04 returning 20:
[ 1.841781] of_irq_parse_raw: /soc/pcie at 0x01000000:00000001
[ 1.841813] of_irq_parse_raw: ipar=/soc/pcie at 0x01000000, size=1
[ 1.841838] -> addrsize=3
[ 1.841870] -> match=1 (imaplen=28)
[ 1.841903] -> newintsize=3, newaddrsize=1
[ 1.841916] -> imaplen=23
[ 1.841928] -> new parent: /interrupt-controller at 00a01000
[ 1.841946] -> got it !
[ 1.841972] irq_create_of_mapping: calling xlate for 123/4/0 3
[ 1.841984] irq_create_of_mapping got irq from xlate: 20
^^^^^ added debugging shows 3 u32's passed to xlate and returned value of 20
[ 1.841998] irq: irq_create_mapping(0xbec10400, 0x14)
[ 1.842009] irq: -> using domain @bec10400
[ 1.842021] irq: -> existing mapping on virq 20
[ 1.842032] irq_create_of_mapping created virq=20
[ 1.842042] irq_create_of_mapping returning virq=20
[ 1.842059] pci 0000:00:00.0: dw_pcie_map_irq: 16c3:abcd slot0 pin1 irq20
Perhaps this is a byte-ordering issue? I'm wondering if the args
created in of_irq_parse_pci are getting put in the wrong place for
what irq_create_of_mapping() expects.
For the slots above that swizzle to pin2,3,4 of_irq_parse_raw()
returns -EINVAL because for some reason it can't match an interrupt
mapping for the pcie host controller:
[ 1.842996] of_irq_parse_raw: /soc/pcie at 0x01000000/pcie at 0,0:00000002
[ 1.843046] of_irq_parse_raw: ipar=/soc/pcie at 0x01000000, size=1
[ 1.843070] -> addrsize=3
[ 1.843100] -> match=0 (imaplen=28)
^^^^^ indicates no match in interrupt map.
I think this is because size=1 above, when we should see an
interrupt-map of size 4. I'm guessing that the function is confused
between the single interrupt in the DT for the host controller, vs the
interrupt-map for the PCI interrupts.
At this point, with no match, of_irq_parse_raw() will travel up to the
parent of the interrupt which is wrong.
Note the pcie host controller DT is:
pcie: pcie at 0x01000000 {
compatible = "fsl,imx6q-pcie", "snps,dw-pcie";
reg = <0x01ffc000 0x4000>; /* DBI */
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
ranges = <0x00000800 0 0x01f00000 0x01f00000 0 0x00080000 /*
configuration space */
0x81000000 0 0 0x01f80000 0 0x00010000 /* downstream I/O */
0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /*
non-prefetchable memory */
num-lanes = <1>;
interrupts = <0 123 0x04>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks 189>, <&clks 187>, <&clks 206>, <&clks 144>;
clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi";
status = "disabled";
};
Tim
>
> Tim
>
>> You can test i.MX PCIe with this.
>>
>> ./drivers/pci/host/pcie-designware.c
>> @@ -726,7 +727,7 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
>>
>> if (pp) {
>> pp->root_bus_nr = sys->busnr;
>> - bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops,
>> + bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,
>> sys, &sys->resources);
>> } else {
>> bus = NULL;
>>
>> However, I think that we may need to replace 'pci_common_init()'
>> with 'pci_common_init_dev()'.
>>
>> Best regards,
>> Jingoo Han
>>
More information about the linux-arm-kernel
mailing list