Skip to contentSkip to conversation

usb/hcd: irq 18: nobody cared

-next-20130204 In review Peter Hurley 7 participants 27 messages Feb 5, 2013 – Feb 19, 2013

Subsystems (5)
Linux-next tree ACPI PCI Driver core +1 more subsystems
lore
Share & tools
lore
#0 lore raw

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18
Quoted 1 line

From earlier in the boot log:

[    1.297020] uhci_hcd 0000:00:1d.2: setting latency timer to 64
[    1.297032] uhci_hcd 0000:00:1d.2: UHCI Host Controller
[    1.297040] uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus number 4
[    1.297076] uhci_hcd 0000:00:1d.2: irq 18, io base 0x0000ff40
[    1.297213] hub 4-0:1.0: USB hub found
[    1.297221] hub 4-0:1.0: 2 ports detected

lsusb:
...
Bus 004 Device 002: ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS Bus 004 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
...

Didn't have this problem with -next-20120125. One of these commits, maybe? next/drivers/usb/core$ git log --oneline next-20130125..next-20130204 -- * 2c2e865 usb: forbid memory allocation with I/O during bus reset e9121a8 Merge remote-tracking branch 'usb/usb-next'
3b2ab2b Revert "usb: Register usb port's acpi power resources" da0aa71 USB: add usb_hcd_{start,end}_port_resume
192fef1 usb: enable usb port device's async suspend.
f6cced1 usb: expose usb port's pm qos flags to user space
ad493e5 usb: add usb port auto power off mechanism
971fcd4 usb: add runtime pm support for usb port device
88bb965 usb: Register usb port's acpi power resources
54a3ac0 usb: Using correct way to clear usb3.0 device's remote wakeup feature.

I didn't see any changes in the drivers/hid/hid-logitech-dj.c or usbhid but maybe it's doing something wrong anyway?

I'll open a bugzilla if a bunch more info is necessary.

Regards,
Peter Hurley

#1 lore raw
Quoted 37 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18

From earlier in the boot log:

[    1.297020] uhci_hcd 0000:00:1d.2: setting latency timer to 64
[    1.297032] uhci_hcd 0000:00:1d.2: UHCI Host Controller
[    1.297040] uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus number 4
[    1.297076] uhci_hcd 0000:00:1d.2: irq 18, io base 0x0000ff40
[    1.297213] hub 4-0:1.0: USB hub found
[    1.297221] hub 4-0:1.0: 2 ports detected

lsusb:
...
Bus 004 Device 002: ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS Bus 004 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
...

Quoted 12 lines

Didn't have this problem with -next-20120125. One of these commits, maybe? next/drivers/usb/core$ git log --oneline next-20130125..next-20130204 -- * 2c2e865 usb: forbid memory allocation with I/O during bus reset e9121a8 Merge remote-tracking branch 'usb/usb-next'
3b2ab2b Revert "usb: Register usb port's acpi power resources" da0aa71 USB: add usb_hcd_{start,end}_port_resume
192fef1 usb: enable usb port device's async suspend.
f6cced1 usb: expose usb port's pm qos flags to user space
ad493e5 usb: add usb port auto power off mechanism
971fcd4 usb: add runtime pm support for usb port device
88bb965 usb: Register usb port's acpi power resources
54a3ac0 usb: Using correct way to clear usb3.0 device's remote wakeup feature.

None of those commits seems likely to have caused the problem. The most likely is da0aa71, combined with one you didn't mention:

840008bb USB: UHCI: notify usbcore about port resumes

If you revert these two commits, does that make any difference? What if you revert all of these commits?

Quoted 4 lines

I didn't see any changes in the drivers/hid/hid-logitech-dj.c or usbhid but maybe it's doing something wrong anyway?

I'll open a bugzilla if a bunch more info is necessary.

If the suggestion above doesn't work out, bisection may be the best way to find the answer.

Alan Stern

#2 lore raw
Quoted 52 lines · Alan Stern
Quoted 37 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18

From earlier in the boot log:

[    1.297020] uhci_hcd 0000:00:1d.2: setting latency timer to 64
[    1.297032] uhci_hcd 0000:00:1d.2: UHCI Host Controller
[    1.297040] uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus number 4
[    1.297076] uhci_hcd 0000:00:1d.2: irq 18, io base 0x0000ff40
[    1.297213] hub 4-0:1.0: USB hub found
[    1.297221] hub 4-0:1.0: 2 ports detected

lsusb:
...
Bus 004 Device 002: ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS Bus 004 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
...

Quoted 12 lines

Didn't have this problem with -next-20120125. One of these commits, maybe? next/drivers/usb/core$ git log --oneline next-20130125..next-20130204 -- * 2c2e865 usb: forbid memory allocation with I/O during bus reset e9121a8 Merge remote-tracking branch 'usb/usb-next'
3b2ab2b Revert "usb: Register usb port's acpi power resources" da0aa71 USB: add usb_hcd_{start,end}_port_resume
192fef1 usb: enable usb port device's async suspend.
f6cced1 usb: expose usb port's pm qos flags to user space
ad493e5 usb: add usb port auto power off mechanism
971fcd4 usb: add runtime pm support for usb port device
88bb965 usb: Register usb port's acpi power resources
54a3ac0 usb: Using correct way to clear usb3.0 device's remote wakeup feature.

Quoted 7 lines

None of those commits seems likely to have caused the problem. The most likely is da0aa71, combined with one you didn't mention:

840008bb USB: UHCI: notify usbcore about port resumes

If you revert these two commits, does that make any difference? What if you revert all of these commits?

None of these commits are directly causing this. I tested Greg's usb master and usb-next and both run fine for me.

Quoted 7 lines
Quoted 4 lines

I didn't see any changes in the drivers/hid/hid-logitech-dj.c or usbhid but maybe it's doing something wrong anyway?

I'll open a bugzilla if a bunch more info is necessary.

If the suggestion above doesn't work out, bisection may be the best way to find the answer.

Any pointers on how to one of) build a linear history for -next, get bisect to work on an integration tree, or third option I haven't thought of?

Thanks,
Peter Hurley

author Acked-by Rafael J. Wysocki
#3 lore raw
In reply to Alan Stern
Quoted 37 lines · Alan Stern
Quoted 35 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18

From earlier in the boot log:

[    1.297020] uhci_hcd 0000:00:1d.2: setting latency timer to 64
[    1.297032] uhci_hcd 0000:00:1d.2: UHCI Host Controller
[    1.297040] uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus number 4
[    1.297076] uhci_hcd 0000:00:1d.2: irq 18, io base 0x0000ff40
[    1.297213] hub 4-0:1.0: USB hub found
[    1.297221] hub 4-0:1.0: 2 ports detected

lsusb:
...
Bus 004 Device 002: ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS Bus 004 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver

[...]

Quoted 2 lines

If the suggestion above doesn't work out, bisection may be the best way to find the answer.

This bad irq bisected to:

4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4 is the first bad commit commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4

Author: Yinghai Lu <[email protected]>
Date:   Mon Jan 21 13:20:52 2013 -0800

PCI: Put pci_dev in device tree as early as possible

We want to put pci_dev structs in the device tree as soon as possible so for_each_pci_dev() iteration will not miss them, but driver attachment needs to be delayed until after pci_assign_unassigned_resources() to make sure all devices have resources assigned first.

This patch moves device registering from pci_bus_add_devices() to pci_device_add(), which happens earlier, leaving driver attachment in pci_bus_add_devices().

It also removes unattached child bus handling in pci_bus_add_devices(). That's not needed because child bus via pci_add_new_bus() is already in parent bus children list.

:040000 040000 0540c98d04d00de24b4e12fa750f6cd26c5addd2 2e24946cb7165a4028b7efb0a622271cc3990005 M drivers

All is fine if I revert these 2 commits:

40064ac PCI: Remove unused "rc" in virtfn_add_bus()
4f53509 (HEAD, refs/bisect/bad) PCI: Put pci_dev in device tree as early as possible

Any ideas how these are causing the USB HCD core / hid-logitech-dj driver to drop interrupts?

Regards,
Peter Hurley

#4 lore raw
Quoted 73 lines · Peter Hurley
Quoted 37 lines · Alan Stern
Quoted 35 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18

From earlier in the boot log:

[    1.297020] uhci_hcd 0000:00:1d.2: setting latency timer to 64
[    1.297032] uhci_hcd 0000:00:1d.2: UHCI Host Controller
[    1.297040] uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus number 4
[    1.297076] uhci_hcd 0000:00:1d.2: irq 18, io base 0x0000ff40
[    1.297213] hub 4-0:1.0: USB hub found
[    1.297221] hub 4-0:1.0: 2 ports detected

lsusb:
...
Bus 004 Device 002: ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS Bus 004 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver

[...]

Quoted 2 lines

If the suggestion above doesn't work out, bisection may be the best way to find the answer.

This bad irq bisected to:

4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4 is the first bad commit commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4

Author: Yinghai Lu <[email protected]>
Date:   Mon Jan 21 13:20:52 2013 -0800

PCI: Put pci_dev in device tree as early as possible

We want to put pci_dev structs in the device tree as soon as possible so for_each_pci_dev() iteration will not miss them, but driver attachment needs to be delayed until after pci_assign_unassigned_resources() to make sure all devices have resources assigned first.

This patch moves device registering from pci_bus_add_devices() to pci_device_add(), which happens earlier, leaving driver attachment in pci_bus_add_devices().

It also removes unattached child bus handling in pci_bus_add_devices(). That's not needed because child bus via pci_add_new_bus() is already in parent bus children list.

:040000 040000 0540c98d04d00de24b4e12fa750f6cd26c5addd2 2e24946cb7165a4028b7efb0a622271cc3990005 M drivers

Quoted 7 lines

All is fine if I revert these 2 commits:

40064ac PCI: Remove unused "rc" in virtfn_add_bus()
4f53509 (HEAD, refs/bisect/bad) PCI: Put pci_dev in device tree as early as possible

Any ideas how these are causing the USB HCD core / hid-logitech-dj driver to drop interrupts?

https://bugzilla.kernel.org/show_bug.cgi?id=53561

Maybe this is some interaction with all the new ACPI code and fixes written in those 8 days.

peter@thor:~/src/kernels/next$ git log --oneline next-20130125..next-20130204 | grep -i acpi
65d6ce7 Merge remote-tracking branch 'acpi/next'
0d50e8c Merge branch 'acpi-pm-next' into linux-next
be6d286 PCI: acpiphp: Remove dead code for PCI host bridge hotplug
4b794a0 Merge branch 'acpi-assorted' into linux-next
bd3e4a3 Merge branch 'acpi-cleanup' into linux-next
02df734 ACPI / dock: Fix acpi_bus_get_device() check in drivers/acpi/dock.c
7217dac Merge branch 'acpi-lpss' into linux-next
4bede3f Merge branch 'acpi-pm' into linux-next
cc0755b Merge branch 'acpica' into linux-next
308b10d Merge branch 'acpi-scan' into linux-next
2ca344e PCI: acpiphp: Create companion ACPI devices before creating PCI devices
741220e cpufreq: Make acpi-cpufreq link first
c40a451 acpi-cpufreq: Do not load on K8
b378549 ACPI / PM: Do not power manage devices in unknown initial states
cfc5755 PNPACPI: Fix acpi_bus_get_device() check in drivers/pnp/pnpacpi/core.c
dde3bb4 ACPI / PM: Fix acpi_bus_get_device() check in drivers/acpi/device_pm.c
456de89 ACPI / scan: Clean up acpi_bus_get_parent()
0613e1f ACPI / scan: Fix acpi_bus_get_device() check in acpi_match_device()
141a297 ACPI / platform: Use struct acpi_scan_handler for creating devices
4daeaf6 ACPI / PCI: Make PCI IRQ link driver use struct acpi_scan_handler
00c43b9 ACPI / PCI: Make PCI root driver use struct acpi_scan_handler
ca589f9 ACPI / scan: Introduce struct acpi_scan_handler
3b2ab2b Revert "usb: Register usb port's acpi power resources"
8b4e2fa Merge branch 'acpi-lpss' into acpi-cleanup
64e94e7 Merge branch 'acpi-scan' into acpi-cleanup
2c0d4fe ACPI / scan: Make scanning of fixed devices follow the general scheme
8a78cf7 Merge branch 'acpi-pm' into acpi-cleanup
0d1c28a gpiolib-acpi: Add ACPI5 event model support to gpio.
65ab96f ACPI / PM: Fix /proc/acpi/wakeup for devices w/o bus or parent
c511cc1 ACPI / scan: Make namespace scanning and trimming mutually exclusive
fb45579 Merge branch 'pci/acpi-scan2' into next
09212fd ACPI: Drop device start operation that is not used
51fac83 ACPI: Remove useless type argument of driver .remove() operation
cc38e51 Merge branch 'acpi-scan' into acpi-cleanup
5baa1be ACPI: fix obsolete comment in custom_method.c
ca4e713 ACPI / thermal: Use mode to enable/disable kernel thermal processing
7e3cf24 ACPI thermal: remove unnecessary newline from exception message
c628423 ACPI sysfs: remove unnecessary newline from exception
bf6787e ACPI video: remove unnecessary newline from error messages
208f6cc ACPI: SRAT: report non-volatile memory in debug
33f767d ACPI: Rework acpi_get_child() to be more efficient
bfee26d ACPI / scan: Make it clear that acpi_bus_trim() cannot fail
d59f53b PCI: acpiphp: Keep driver loaded even if no slots found
121b090 PCI/ACPI: Print info if host bridge notify handler installation fails
668192b PCI: acpiphp: Move host bridge hotplug to pci_root.c
92d8aff PCI/ACPI: acpiphp: Rename alloc_acpiphp_hp_work() to alloc_acpi_hp_work()
660b111 ACPI / PM: Fix consistency check for power resources during resume
18a3870 ACPI / PM: Expose lists of device power resources to user space
1f96a96 PCI: acpiphp: Add is_hotplug_bridge detection
a276660 Merge branch 'acpi-scan' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm into pci/acpi-scan2
88bb965 usb: Register usb port's acpi power resources
2171953 ACPICA: Update version to 20130117
378bb8b ACPICA: Update predefined info table for _MLS method
5e30a96 ACPICA: Remove some extraneous newlines in ACPI_ERROR type calls
d9652b4 ACPICA: iASL/Disassembler: Add option to ignore NOOP opcodes/operators
48ffb94 ACPICA: AcpiGetSleepTypeData: Allow \_Sx to return either 1 or 2 integers
25f044e ACPICA: Update ACPICA copyrights to 2013
586ce51 ACPICA: Update predefined info table
afd51a0 x86/acpi: Use __pa_symbol instead of __pa on C visible symbols

Regards,
Peter Hurley

#5 lore raw
Quoted 79 lines · Peter Hurley
Quoted 78 lines · Peter Hurley
Quoted 37 lines · Alan Stern
Quoted 35 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18

From earlier in the boot log:

[    1.297020] uhci_hcd 0000:00:1d.2: setting latency timer to 64
[    1.297032] uhci_hcd 0000:00:1d.2: UHCI Host Controller
[    1.297040] uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus number 4
[    1.297076] uhci_hcd 0000:00:1d.2: irq 18, io base 0x0000ff40
[    1.297213] hub 4-0:1.0: USB hub found
[    1.297221] hub 4-0:1.0: 2 ports detected

lsusb:
...
Bus 004 Device 002: ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS Bus 004 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver

[...]

Quoted 2 lines

If the suggestion above doesn't work out, bisection may be the best way to find the answer.

This bad irq bisected to:

4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4 is the first bad commit commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4

Author: Yinghai Lu <[email protected]>
Date:   Mon Jan 21 13:20:52 2013 -0800

PCI: Put pci_dev in device tree as early as possible

We want to put pci_dev structs in the device tree as soon as possible so for_each_pci_dev() iteration will not miss them, but driver attachment needs to be delayed until after pci_assign_unassigned_resources() to make sure all devices have resources assigned first.

This patch moves device registering from pci_bus_add_devices() to pci_device_add(), which happens earlier, leaving driver attachment in pci_bus_add_devices().

It also removes unattached child bus handling in pci_bus_add_devices(). That's not needed because child bus via pci_add_new_bus() is already in parent bus children list.

:040000 040000 0540c98d04d00de24b4e12fa750f6cd26c5addd2 2e24946cb7165a4028b7efb0a622271cc3990005 M drivers

All is fine if I revert these 2 commits:

40064ac PCI: Remove unused "rc" in virtfn_add_bus()
4f53509 (HEAD, refs/bisect/bad) PCI: Put pci_dev in device tree as early as possible

Quoted 7 lines
Quoted 2 lines

Any ideas how these are causing the USB HCD core / hid-logitech-dj driver to drop interrupts?

https://bugzilla.kernel.org/show_bug.cgi?id=53561

Maybe this is some interaction with all the new ACPI code and fixes written in those 8 days.

interrupt routing seems get changed:
next:
5: 0 0 0 0 0

0          0          0   IO-APIC-fasteoi   snd_ctxfi
  18:      99970         13         16         20      99940
13         13         16   IO-APIC-fasteoi   uhci_hcd:usb4

v3.8-rc7:
18: 424 15 11 112 420
16 18 105 IO-APIC-fasteoi uhci_hcd:usb4, snd_ctxfi

These messages in the bad dmesg log are interesting since PCI INT A is routed on
irq 18 with the kernels that work.

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

...

acpi_pci_irq_add_prt() add wrong bus for that bridge, because that that bridge is not scanned.

Will check if I can produce one patch for it.

Thanks

Yinghai

#6 lore raw
Quoted 46 lines · Yinghai Lu
Quoted 27 lines · Peter Hurley
Quoted 18 lines · Peter Hurley
Quoted 17 lines · Alan Stern
Quoted 15 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18
Quoted 4 lines

https://bugzilla.kernel.org/show_bug.cgi?id=53561

Maybe this is some interaction with all the new ACPI code and fixes written in those 8 days.

interrupt routing seems get changed:
next:
5: 0 0 0 0 0

0          0          0   IO-APIC-fasteoi   snd_ctxfi
  18:      99970         13         16         20      99940
13         13         16   IO-APIC-fasteoi   uhci_hcd:usb4

v3.8-rc7:
18: 424 15 11 112 420
16 18 105 IO-APIC-fasteoi uhci_hcd:usb4, snd_ctxfi

These messages in the bad dmesg log are interesting since PCI INT A is routed on
irq 18 with the kernels that work.

Quoted 8 lines
[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

...

acpi_pci_irq_add_prt() add wrong bus for that bridge, because that that bridge is not scanned.

Will check if I can produce one patch for it.

Hi Peter,

Can you try attached debug patch?

Thanks

Yinghai

drivers/pci/bus.c +5 -0
index 8647dc6..e901902 100644
@@ -160,6 +160,8 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 
 void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
 
+void __weak pcibios_irq_setup(struct device *dev) { }
+
 /**
  * pci_bus_add_device - start driver for a single device
  * @dev: device to add
@@ -170,6 +172,9 @@ int pci_bus_add_device(struct pci_dev *dev)
 {
 	int retval;
 
+	/* need to after bridge is scanned */
+	pcibios_irq_setup(&dev->dev);
+
 	/*
 	 * Can not put in pci_device_add yet because resources
 	 * are not assigned yet for some devices.
drivers/pci/pci-acpi.c +11 -2
index ba4545f..87bd80b 100644
@@ -302,14 +302,16 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 	return 0;
 }
 
-static void pci_acpi_setup(struct device *dev)
+void pcibios_irq_setup(struct device *dev)
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
-	struct acpi_device *adev;
 	acpi_status status;
 	acpi_handle dummy;
 
+	if (acpi_disabled || acpi_pci_disabled)
+		return;
+
 	/*
 	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
 	 * _PRT objects within the scope of non-bridge devices.  Note that
@@ -326,6 +328,13 @@ static void pci_acpi_setup(struct device *dev)
 			pci_dev->subordinate->number : pci_dev->bus->number;
 		acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
 	}
+}
+
+static void pci_acpi_setup(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	acpi_handle handle = ACPI_HANDLE(dev);
+	struct acpi_device *adev;
 
 	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
 		return;
#7 lore raw
Quoted 1 line · Yinghai Lu

Can you try attached debug patch?

FWIW this fixes it for me. No more 'derived' or 'nobody' in dmesg.

thanks,

Signature · 2 lines
js
suse labs
#8 lore raw
In reply to Yinghai Lu
Quoted 51 lines · Yinghai Lu
Quoted 50 lines · Yinghai Lu
Quoted 27 lines · Peter Hurley
Quoted 18 lines · Peter Hurley
Quoted 17 lines · Alan Stern
Quoted 15 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18
Quoted 4 lines

https://bugzilla.kernel.org/show_bug.cgi?id=53561

Maybe this is some interaction with all the new ACPI code and fixes written in those 8 days.

interrupt routing seems get changed:
next:
5: 0 0 0 0 0

0          0          0   IO-APIC-fasteoi   snd_ctxfi
  18:      99970         13         16         20      99940
13         13         16   IO-APIC-fasteoi   uhci_hcd:usb4

v3.8-rc7:
18: 424 15 11 112 420
16 18 105 IO-APIC-fasteoi uhci_hcd:usb4, snd_ctxfi

These messages in the bad dmesg log are interesting since PCI INT A is routed on
irq 18 with the kernels that work.

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

...

Quoted 8 lines
Quoted 4 lines

acpi_pci_irq_add_prt() add wrong bus for that bridge, because that that bridge is not scanned.

Will check if I can produce one patch for it.

Hi Peter,

Can you try attached debug patch?

Fixed, thanks.

Regards,
Peter Hurley

#9 lore raw
Quoted 55 lines · Peter Hurley
Quoted 54 lines · Yinghai Lu
Quoted 53 lines · Yinghai Lu
Quoted 27 lines · Peter Hurley
Quoted 18 lines · Peter Hurley
Quoted 17 lines · Alan Stern
Quoted 15 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18
Quoted 4 lines

https://bugzilla.kernel.org/show_bug.cgi?id=53561

Maybe this is some interaction with all the new ACPI code and fixes written in those 8 days.

interrupt routing seems get changed:
next:
5: 0 0 0 0 0

0          0          0   IO-APIC-fasteoi   snd_ctxfi
  18:      99970         13         16         20      99940
13         13         16   IO-APIC-fasteoi   uhci_hcd:usb4

v3.8-rc7:
18: 424 15 11 112 420
16 18 105 IO-APIC-fasteoi uhci_hcd:usb4, snd_ctxfi

These messages in the bad dmesg log are interesting since PCI INT A is routed on
irq 18 with the kernels that work.

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

...

acpi_pci_irq_add_prt() add wrong bus for that bridge, because that that bridge is not scanned.

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

Will check if I can produce one patch for it.

Hi Peter,

Can you try attached debug patch?

Fixed, thanks.

Bjorn, Rafael,

acpi_pci_irq_add_prt need to be called after pci bridge get scanned, so we can not call it from pci_acpi_setup, after we move dev_register for pci_dev early.

The attached debug patch move down that calling into pci_bus_add_devices and that will make prt works again.

Can acpi provide another hook after bridge get scanned?

Thanks

Yinghai

---
 drivers/pci/bus.c      |    5 +++++
 drivers/pci/pci-acpi.c |   13 +++++++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)
drivers/pci/bus.c +5 -0
Index: linux-2.6/drivers/pci/bus.c
===================================================================
@@ -160,6 +160,8 @@ pci_bus_alloc_resource(struct pci_bus *b
 
 void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
 
+void __weak pcibios_irq_setup(struct device *dev) { }
+
 /**
  * pci_bus_add_device - start driver for a single device
  * @dev: device to add
@@ -170,6 +172,9 @@ int pci_bus_add_device(struct pci_dev *d
 {
 	int retval;
 
+	/* need to after bridge is scanned */
+	pcibios_irq_setup(&dev->dev);
+
 	/*
 	 * Can not put in pci_device_add yet because resources
 	 * are not assigned yet for some devices.
drivers/pci/pci-acpi.c +11 -2
Index: linux-2.6/drivers/pci/pci-acpi.c
===================================================================
@@ -302,14 +302,16 @@ static int acpi_pci_find_device(struct d
 	return 0;
 }
 
-static void pci_acpi_setup(struct device *dev)
+void pcibios_irq_setup(struct device *dev)
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
-	struct acpi_device *adev;
 	acpi_status status;
 	acpi_handle dummy;
 
+	if (acpi_disabled || acpi_pci_disabled)
+		return;
+
 	/*
 	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
 	 * _PRT objects within the scope of non-bridge devices.  Note that
@@ -326,6 +328,13 @@ static void pci_acpi_setup(struct device
 			pci_dev->subordinate->number : pci_dev->bus->number;
 		acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
 	}
+}
+
+static void pci_acpi_setup(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	acpi_handle handle = ACPI_HANDLE(dev);
+	struct acpi_device *adev;
 
 	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
 		return;
#10 lore raw
Quoted 66 lines · Yinghai Lu
Quoted 55 lines · Peter Hurley
Quoted 54 lines · Yinghai Lu
Quoted 53 lines · Yinghai Lu
Quoted 27 lines · Peter Hurley
Quoted 18 lines · Peter Hurley
Quoted 17 lines · Alan Stern
Quoted 15 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18
Quoted 4 lines

https://bugzilla.kernel.org/show_bug.cgi?id=53561

Maybe this is some interaction with all the new ACPI code and fixes written in those 8 days.

interrupt routing seems get changed:
next:
5: 0 0 0 0 0

0          0          0   IO-APIC-fasteoi   snd_ctxfi
  18:      99970         13         16         20      99940
13         13         16   IO-APIC-fasteoi   uhci_hcd:usb4

v3.8-rc7:
18: 424 15 11 112 420
16 18 105 IO-APIC-fasteoi uhci_hcd:usb4, snd_ctxfi

These messages in the bad dmesg log are interesting since PCI INT A is routed on
irq 18 with the kernels that work.

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

...

acpi_pci_irq_add_prt() add wrong bus for that bridge, because that that bridge is not scanned.

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

Will check if I can produce one patch for it.

Hi Peter,

Can you try attached debug patch?

Fixed, thanks.

Bjorn, Rafael,

Quoted 9 lines

acpi_pci_irq_add_prt need to be called after pci bridge get scanned, so we can not call it from pci_acpi_setup, after we move dev_register for pci_dev early.

The attached debug patch move down that calling into pci_bus_add_devices and that will make prt works again.

Can acpi provide another hook after bridge get scanned?

23: + /* need to after bridge is scanned */
24: + pcibios_irq_setup(&dev->dev);

... need to *be called* after...

Even this is a temporary workaround, can you send a separate patch for this?

- Sedat -

P.S.: Still wonder why people use "linux-2.6" as prefix in their patches.

Quoted 3 lines

Thanks

Yinghai

#11 lore raw
Quoted 77 lines · Sedat Dilek
Quoted 66 lines · Yinghai Lu
Quoted 55 lines · Peter Hurley
Quoted 54 lines · Yinghai Lu
Quoted 53 lines · Yinghai Lu
Quoted 27 lines · Peter Hurley
Quoted 18 lines · Peter Hurley
Quoted 17 lines · Alan Stern
Quoted 15 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18
Quoted 4 lines

https://bugzilla.kernel.org/show_bug.cgi?id=53561

Maybe this is some interaction with all the new ACPI code and fixes written in those 8 days.

interrupt routing seems get changed:
next:
5: 0 0 0 0 0

0          0          0   IO-APIC-fasteoi   snd_ctxfi
  18:      99970         13         16         20      99940
13         13         16   IO-APIC-fasteoi   uhci_hcd:usb4

v3.8-rc7:
18: 424 15 11 112 420
16 18 105 IO-APIC-fasteoi uhci_hcd:usb4, snd_ctxfi

These messages in the bad dmesg log are interesting since PCI INT A is routed on
irq 18 with the kernels that work.

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

...

acpi_pci_irq_add_prt() add wrong bus for that bridge, because that that bridge is not scanned.

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

Will check if I can produce one patch for it.

Hi Peter,

Can you try attached debug patch?

Fixed, thanks.

Bjorn, Rafael,

Quoted 9 lines

acpi_pci_irq_add_prt need to be called after pci bridge get scanned, so we can not call it from pci_acpi_setup, after we move dev_register for pci_dev early.

The attached debug patch move down that calling into pci_bus_add_devices and that will make prt works again.

Can acpi provide another hook after bridge get scanned?

Quoted 6 lines

23: + /* need to after bridge is scanned */
24: + pcibios_irq_setup(&dev->dev);

... need to *be called* after...

Even this is a temporary workaround, can you send a separate patch for this?

again, this is debug patch.

Thanks

Yinghai

#12 lore raw
In reply to Yinghai Lu
Quoted 66 lines · Yinghai Lu
Quoted 55 lines · Peter Hurley
Quoted 54 lines · Yinghai Lu
Quoted 53 lines · Yinghai Lu
Quoted 27 lines · Peter Hurley
Quoted 18 lines · Peter Hurley
Quoted 17 lines · Alan Stern
Quoted 15 lines · Peter Hurley

With -next-20130204:

[   33.855570] irq 18: nobody cared (try booting with the "irqpoll" option)
[   33.855580] Pid: 0, comm: swapper/4 Not tainted 3.8.0-next-20130204-xeon #20130204
[   33.855582] Call Trace:
[   33.855585]  <IRQ>  [<ffffffff810f1076>] __report_bad_irq+0x36/0xe0
[   33.855600]  [<ffffffff810f152a>] note_interrupt+0x1aa/0x200
[   33.855606]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855610]  [<ffffffff810eed89>] handle_irq_event_percpu+0xc9/0x260
[   33.855614]  [<ffffffff810eef68>] handle_irq_event+0x48/0x70
[   33.855618]  [<ffffffff810f20ba>] handle_fasteoi_irq+0x5a/0x100
[   33.855624]  [<ffffffff810182f2>] handle_irq+0x22/0x40
[   33.855630]  [<ffffffff816e2a9a>] do_IRQ+0x5a/0xd0
[   33.855636]  [<ffffffff816d97ad>] common_interrupt+0x6d/0x6d
[   33.855638]  <EOI>  [<ffffffff810f8e2a>] ? rcu_eqs_enter_common+0x4a/0x320
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
[   33.855646]  [<ffffffff8101edf2>] ? mwait_idle+0x82/0x1b0
[   33.855649]  [<ffffffff8101ed99>] ? mwait_idle+0x29/0x1b0
[   33.855653]  [<ffffffff8101f8a6>] cpu_idle+0x116/0x130
[   33.855658]  [<ffffffff816c0c0f>] start_secondary+0x251/0x258
[   33.855660] handlers:
[   33.855664] [<ffffffff814f98a0>] usb_hcd_irq
[   33.855667] Disabling IRQ #18
Quoted 4 lines

https://bugzilla.kernel.org/show_bug.cgi?id=53561

Maybe this is some interaction with all the new ACPI code and fixes written in those 8 days.

interrupt routing seems get changed:
next:
5: 0 0 0 0 0

0          0          0   IO-APIC-fasteoi   snd_ctxfi
  18:      99970         13         16         20      99940
13         13         16   IO-APIC-fasteoi   uhci_hcd:usb4

v3.8-rc7:
18: 424 15 11 112 420
16 18 105 IO-APIC-fasteoi uhci_hcd:usb4, snd_ctxfi

These messages in the bad dmesg log are interesting since PCI INT A is routed on
irq 18 with the kernels that work.

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

...

acpi_pci_irq_add_prt() add wrong bus for that bridge, because that that bridge is not scanned.

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

Will check if I can produce one patch for it.

Hi Peter,

Can you try attached debug patch?

Fixed, thanks.

Bjorn, Rafael,

Quoted 9 lines

acpi_pci_irq_add_prt need to be called after pci bridge get scanned, so we can not call it from pci_acpi_setup, after we move dev_register for pci_dev early.

The attached debug patch move down that calling into pci_bus_add_devices and that will make prt works again.

Can acpi provide another hook after bridge get scanned?

Can we extend platform_notify to be
platform_notify(struct device *dev, event) ?

and event could be _ADD, _SCAN, _REMOVE

Thanks

Yinghai

#13 lore raw
Quoted 7 lines · Yinghai Lu
Quoted 7 lines

Bjorn, Rafael,

acpi_pci_irq_add_prt need to be called after pci bridge get scanned, so we can not call it from pci_acpi_setup, after we move dev_register for pci_dev early.

Quoted 5 lines
Quoted 5 lines

The attached debug patch move down that calling into pci_bus_add_devices and that will make prt works again.

Can acpi provide another hook after bridge get scanned?

Rafael, Bjorn,

Can you check attached patch?

Thanks

Yinghai

Subject: [PATCH] ACPI, PCI: add acpi_platform_notify_scan()

Peter Hurley found irq nobody cared, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Add acpi_platform_notify_scan() to call acpi_pci_irq_add_prt later.

---
 drivers/acpi/glue.c     |   12 ++++++++++++
 drivers/base/core.c     |    1 +
 drivers/pci/bus.c       |    4 ++++
 drivers/pci/pci-acpi.c  |   27 +++++++++++++++++----------
 include/acpi/acpi_bus.h |    1 +
 include/linux/device.h  |    3 +--
 6 files changed, 36 insertions(+), 12 deletions(-)
drivers/acpi/glue.c +12 -0
Index: linux-2.6/drivers/acpi/glue.c
===================================================================
@@ -312,6 +312,17 @@ static int acpi_platform_notify(struct d
 	return ret;
 }
 
+static int acpi_platform_notify_scan(struct device *dev)
+{
+	struct acpi_bus_type *type;
+
+	type = acpi_get_bus_type(dev->bus);
+	if (type && type->setup_scan)
+		type->setup_scan(dev);
+
+	return 0;
+}
+
 static int acpi_platform_notify_remove(struct device *dev)
 {
 	struct acpi_bus_type *type;
@@ -331,6 +342,7 @@ int __init init_acpi_device_notify(void)
 		return 0;
 	}
 	platform_notify = acpi_platform_notify;
+	platform_notify_scan = acpi_platform_notify_scan;
 	platform_notify_remove = acpi_platform_notify_remove;
 	return 0;
 }
drivers/base/core.c +1 -0
Index: linux-2.6/drivers/base/core.c
===================================================================
@@ -44,6 +44,7 @@ early_param("sysfs.deprecated", sysfs_de
 #endif
 
 int (*platform_notify)(struct device *dev) = NULL;
+int (*platform_notify_scan)(struct device *dev) = NULL;
 int (*platform_notify_remove)(struct device *dev) = NULL;
 static struct kobject *dev_kobj;
 struct kobject *sysfs_dev_char_kobj;
drivers/pci/bus.c +4 -0
Index: linux-2.6/drivers/pci/bus.c
===================================================================
@@ -170,6 +170,10 @@ int pci_bus_add_device(struct pci_dev *d
 {
 	int retval;
 
+	/* need to be called after bridge is scanned */
+	if (platform_notify_scan)
+		platform_notify_scan(&dev->dev);
+
 	/*
 	 * Can not put in pci_device_add yet because resources
 	 * are not assigned yet for some devices.
drivers/pci/pci-acpi.c +17 -10
Index: linux-2.6/drivers/pci/pci-acpi.c
===================================================================
@@ -307,6 +307,22 @@ static void pci_acpi_setup(struct device
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
+
+	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
+		return;
+
+	device_set_wakeup_capable(dev, true);
+	acpi_pci_sleep_wake(pci_dev, false);
+
+	pci_acpi_add_pm_notifier(adev, pci_dev);
+	if (adev->wakeup.flags.run_wake)
+		device_set_run_wake(dev, true);
+}
+
+static void pci_acpi_setup_scan(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	acpi_handle handle = ACPI_HANDLE(dev);
 	acpi_status status;
 	acpi_handle dummy;
 
@@ -326,16 +342,6 @@ static void pci_acpi_setup(struct device
 			pci_dev->subordinate->number : pci_dev->bus->number;
 		acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
 	}
-
-	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
-		return;
-
-	device_set_wakeup_capable(dev, true);
-	acpi_pci_sleep_wake(pci_dev, false);
-
-	pci_acpi_add_pm_notifier(adev, pci_dev);
-	if (adev->wakeup.flags.run_wake)
-		device_set_run_wake(dev, true);
 }
 
 static void pci_acpi_cleanup(struct device *dev)
@@ -359,6 +365,7 @@ static struct acpi_bus_type acpi_pci_bus
 	.bus = &pci_bus_type,
 	.find_device = acpi_pci_find_device,
 	.setup = pci_acpi_setup,
+	.setup_scan = pci_acpi_setup_scan,
 	.cleanup = pci_acpi_cleanup,
 };
 
include/acpi/acpi_bus.h +1 -0
Index: linux-2.6/include/acpi/acpi_bus.h
===================================================================
@@ -440,6 +440,7 @@ struct acpi_bus_type {
 	/* For bridges, such as PCI root bridge, IDE controller */
 	int (*find_bridge) (struct device *, acpi_handle *);
 	void (*setup)(struct device *);
+	void (*setup_scan)(struct device *);
 	void (*cleanup)(struct device *);
 };
 int register_acpi_bus_type(struct acpi_bus_type *);
include/linux/device.h +1 -2
Index: linux-2.6/include/linux/device.h
===================================================================
@@ -897,10 +897,9 @@ extern void device_destroy(struct class
  */
 /* Notify platform of device discovery */
 extern int (*platform_notify)(struct device *dev);
-
+extern int (*platform_notify_scan)(struct device *dev);
 extern int (*platform_notify_remove)(struct device *dev);
 
-
 /*
  * get_device - atomically increment the reference count for the device.
  *
maintainer
#14 lore raw

[+cc linux-acpi, linux-pci]

Quoted 8 lines · Yinghai Lu
Quoted 7 lines · Yinghai Lu
Quoted 7 lines

Bjorn, Rafael,

acpi_pci_irq_add_prt need to be called after pci bridge get scanned, so we can not call it from pci_acpi_setup, after we move dev_register for pci_dev early.

Quoted 8 lines
Quoted 4 lines
Quoted 4 lines

The attached debug patch move down that calling into pci_bus_add_devices and that will make prt works again.

Can acpi provide another hook after bridge get scanned?

Rafael, Bjorn,

Can you check attached patch?

[Yinghai's patch included below for ease of review]

Quoted 63 lines

Subject: [PATCH] ACPI, PCI: add acpi_platform_notify_scan()

Peter Hurley found irq nobody cared, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Add acpi_platform_notify_scan() to call acpi_pci_irq_add_prt later.

---
 drivers/acpi/glue.c     |   12 ++++++++++++
 drivers/base/core.c     |    1 +
 drivers/pci/bus.c       |    4 ++++
 drivers/pci/pci-acpi.c  |   27 +++++++++++++++++----------
 include/acpi/acpi_bus.h |    1 +
 include/linux/device.h  |    3 +--
 6 files changed, 36 insertions(+), 12 deletions(-)

Index: linux-2.6/drivers/acpi/glue.c
===================================================================

drivers/acpi/glue.c +12 -0
@@ -312,6 +312,17 @@ static int acpi_platform_notify(struct d
 	return ret;
 }
 
+static int acpi_platform_notify_scan(struct device *dev)
+{
+	struct acpi_bus_type *type;
+
+	type = acpi_get_bus_type(dev->bus);
+	if (type && type->setup_scan)
+		type->setup_scan(dev);
+
+	return 0;
+}
+
 static int acpi_platform_notify_remove(struct device *dev)
 {
 	struct acpi_bus_type *type;
@@ -331,6 +342,7 @@ int __init init_acpi_device_notify(void)
 		return 0;
 	}
 	platform_notify = acpi_platform_notify;
+	platform_notify_scan = acpi_platform_notify_scan;
 	platform_notify_remove = acpi_platform_notify_remove;
 	return 0;
 }

Index: linux-2.6/drivers/base/core.c
===================================================================

drivers/base/core.c early_param("sysfs.deprecated", sysfs_de · line 47

Quoted 4 lines
drivers/base/core.c +1 -0
@@ -44,6 +44,7 @@ early_param("sysfs.deprecated", sysfs_de
 #endif
 
 int (*platform_notify)(struct device *dev) = NULL;
+int (*platform_notify_scan)(struct device *dev) = NULL;

I don't like the idea of adding another global function pointer just for this. That seems like overkill for a small, local, problem.

Quoted 46 lines
drivers/base/core.c +0 -0
 int (*platform_notify_remove)(struct device *dev) = NULL;
 static struct kobject *dev_kobj;
 struct kobject *sysfs_dev_char_kobj;

Index: linux-2.6/drivers/pci/bus.c
===================================================================

drivers/pci/bus.c +4 -0
@@ -170,6 +170,10 @@ int pci_bus_add_device(struct pci_dev *d
 {
 	int retval;
 
+	/* need to be called after bridge is scanned */
+	if (platform_notify_scan)
+		platform_notify_scan(&dev->dev);
+
 	/*
 	 * Can not put in pci_device_add yet because resources
 	 * are not assigned yet for some devices.

Index: linux-2.6/drivers/pci/pci-acpi.c
===================================================================

drivers/pci/pci-acpi.c +16 -0
@@ -307,6 +307,22 @@ static void pci_acpi_setup(struct device
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
+
+	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
+		return;
+
+	device_set_wakeup_capable(dev, true);
+	acpi_pci_sleep_wake(pci_dev, false);
+
+	pci_acpi_add_pm_notifier(adev, pci_dev);
+	if (adev->wakeup.flags.run_wake)
+		device_set_run_wake(dev, true);
+}
+
+static void pci_acpi_setup_scan(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	acpi_handle handle = ACPI_HANDLE(dev);
 	acpi_status status;
 	acpi_handle dummy;
 

drivers/pci/pci-acpi.c static void pci_acpi_setup(struct device · line 343

Quoted 2 lines
drivers/pci/pci-acpi.c +0 -0
@@ -326,16 +342,6 @@ static void pci_acpi_setup(struct device
 			pci_dev->subordinate->number : pci_dev->bus->number;
 		acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);

The _PRT describes motherboard interrupt wiring, which has nothing to do with PCI bus numbers. Our current drivers/acpi/pci_irq.c caches the PCI bus number along with the _PRT, and I think that's a mistake.

The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

Quoted 50 lines
drivers/pci/pci-acpi.c +1 -10
 	}
-
-	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
-		return;
-
-	device_set_wakeup_capable(dev, true);
-	acpi_pci_sleep_wake(pci_dev, false);
-
-	pci_acpi_add_pm_notifier(adev, pci_dev);
-	if (adev->wakeup.flags.run_wake)
-		device_set_run_wake(dev, true);
 }
 
 static void pci_acpi_cleanup(struct device *dev)
@@ -359,6 +365,7 @@ static struct acpi_bus_type acpi_pci_bus
 	.bus = &pci_bus_type,
 	.find_device = acpi_pci_find_device,
 	.setup = pci_acpi_setup,
+	.setup_scan = pci_acpi_setup_scan,
 	.cleanup = pci_acpi_cleanup,
 };
 

Index: linux-2.6/include/acpi/acpi_bus.h
===================================================================

include/acpi/acpi_bus.h +1 -0
@@ -440,6 +440,7 @@ struct acpi_bus_type {
 	/* For bridges, such as PCI root bridge, IDE controller */
 	int (*find_bridge) (struct device *, acpi_handle *);
 	void (*setup)(struct device *);
+	void (*setup_scan)(struct device *);
 	void (*cleanup)(struct device *);
 };
 int register_acpi_bus_type(struct acpi_bus_type *);

Index: linux-2.6/include/linux/device.h
===================================================================

include/linux/device.h +1 -2
@@ -897,10 +897,9 @@ extern void device_destroy(struct class
  */
 /* Notify platform of device discovery */
 extern int (*platform_notify)(struct device *dev);
-
+extern int (*platform_notify_scan)(struct device *dev);
 extern int (*platform_notify_remove)(struct device *dev);
 
-
 /*
  * get_device - atomically increment the reference count for the device.
  *
#15 lore raw
Quoted 10 lines · Bjorn Helgaas

[+cc linux-acpi, linux-pci]

The _PRT describes motherboard interrupt wiring, which has nothing to do with PCI bus numbers. Our current drivers/acpi/pci_irq.c caches the PCI bus number along with the _PRT, and I think that's a mistake.

The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

Quoted 7 lines

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

Agreed, will give it try to remove the _PRT caching completely.

Thanks

Yinghai

#16 lore raw
Quoted 19 lines · Yinghai Lu
Quoted 10 lines · Bjorn Helgaas

[+cc linux-acpi, linux-pci]

The _PRT describes motherboard interrupt wiring, which has nothing to do with PCI bus numbers. Our current drivers/acpi/pci_irq.c caches the PCI bus number along with the _PRT, and I think that's a mistake.

The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

Quoted 7 lines

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

Quoted 2 lines

Agreed, will give it try to remove the _PRT caching completely.

Please check attached patch that removes _PRT caching.

Thanks

Yinghai

Subject: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Peter Hurley found irq nobody cared, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

So here we try to remove _PRT caching completely.

---
 drivers/acpi/pci_irq.c      |   97 ++++++++++++++++++--------------------------
 drivers/acpi/pci_root.c     |   18 --------
 drivers/pci/pci-acpi.c      |   24 ----------
 include/acpi/acpi_drivers.h |    5 --
 4 files changed, 40 insertions(+), 104 deletions(-)
drivers/acpi/pci_irq.c +40 -57
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -53,9 +53,6 @@ struct acpi_prt_entry {
 	u32			index;		/* GSI, or link _CRS index */
 };
 
-static LIST_HEAD(acpi_prt_list);
-static DEFINE_SPINLOCK(acpi_prt_lock);
-
 static inline char pin_name(int pin)
 {
 	return 'A' + pin - 1;
@@ -65,28 +62,6 @@ static inline char pin_name(int pin)
                          PCI IRQ Routing Table (PRT) Support
    -------------------------------------------------------------------------- */
 
-static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
-							  int pin)
-{
-	struct acpi_prt_entry *entry;
-	int segment = pci_domain_nr(dev->bus);
-	int bus = dev->bus->number;
-	int device = PCI_SLOT(dev->devfn);
-
-	spin_lock(&acpi_prt_lock);
-	list_for_each_entry(entry, &acpi_prt_list, list) {
-		if ((segment == entry->id.segment)
-		    && (bus == entry->id.bus)
-		    && (device == entry->id.device)
-		    && (pin == entry->pin)) {
-			spin_unlock(&acpi_prt_lock);
-			return entry;
-		}
-	}
-	spin_unlock(&acpi_prt_lock);
-	return NULL;
-}
-
 /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
 static const struct dmi_system_id medion_md9580[] = {
 	{
@@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_pr
 	}
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
-				  struct acpi_pci_routing_table *prt)
+static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
+				  int pin, struct acpi_pci_routing_table *prt,
+				  struct acpi_prt_entry **prt_entry)
 {
+	int segment = pci_domain_nr(dev->bus);
+	int bus = dev->bus->number;
+	int device = PCI_SLOT(dev->devfn);
 	struct acpi_prt_entry *entry;
 
+	if (((prt->address >> 16) & 0xffff) != device ||
+	    prt->pin + 1 != pin)
+		return -ENODEV;
+
 	entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
@@ -237,26 +220,33 @@ static int acpi_pci_irq_add_entry(acpi_h
 			      entry->id.device, pin_name(entry->pin),
 			      prt->source, entry->index));
 
-	spin_lock(&acpi_prt_lock);
-	list_add_tail(&entry->list, &acpi_prt_list);
-	spin_unlock(&acpi_prt_lock);
+	*prt_entry = entry;
 
 	return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
+static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
+			  int pin, struct acpi_prt_entry **entry_ptr)
 {
 	acpi_status status;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_pci_routing_table *entry;
+	acpi_handle handle;
+	struct acpi_prt_entry *prt_entry = NULL;
+
+	if (dev->bus->bridge)
+		handle = ACPI_HANDLE(dev->bus->bridge);
+	else
+		return -ENODEV;
 
 	/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
 	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
-	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
-	       (char *) buffer.pointer);
+	dev_printk(KERN_DEBUG, &dev->dev,
+			"ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
+		       (char *) buffer.pointer);
 
 	kfree(buffer.pointer);
 
@@ -273,7 +263,11 @@ int acpi_pci_irq_add_prt(acpi_handle han
 
 	entry = buffer.pointer;
 	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, segment, bus, entry);
+		if (!acpi_pci_irq_check_entry(handle, dev, pin,
+						 entry, &prt_entry)) {
+			*entry_ptr = prt_entry;
+			break;
+		}
 		entry = (struct acpi_pci_routing_table *)
 		    ((unsigned long)entry + entry->length);
 	}
@@ -282,23 +276,6 @@ int acpi_pci_irq_add_prt(acpi_handle han
 	return 0;
 }
 
-void acpi_pci_irq_del_prt(int segment, int bus)
-{
-	struct acpi_prt_entry *entry, *tmp;
-
-	printk(KERN_DEBUG
-	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-	       segment, bus);
-	spin_lock(&acpi_prt_lock);
-	list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-		if (segment == entry->id.segment && bus == entry->id.bus) {
-			list_del(&entry->list);
-			kfree(entry);
-		}
-	}
-	spin_unlock(&acpi_prt_lock);
-}
-
 /* --------------------------------------------------------------------------
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
@@ -359,12 +336,13 @@ static int acpi_reroute_boot_interrupt(s
 
 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 {
-	struct acpi_prt_entry *entry;
+	struct acpi_prt_entry *entry = NULL;
 	struct pci_dev *bridge;
 	u8 bridge_pin, orig_pin = pin;
+	int ret;
 
-	entry = acpi_pci_irq_find_prt_entry(dev, pin);
-	if (entry) {
+	ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
+	if (!ret && entry) {
 #ifdef CONFIG_X86_IO_APIC
 		acpi_reroute_boot_interrupt(dev, entry);
 #endif /* CONFIG_X86_IO_APIC */
@@ -373,7 +351,7 @@ static struct acpi_prt_entry *acpi_pci_i
 		return entry;
 	}
 
-	/* 
+	/*
 	 * Attempt to derive an IRQ for this device from a parent bridge's
 	 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
 	 */
@@ -393,8 +371,8 @@ static struct acpi_prt_entry *acpi_pci_i
 			pin = bridge_pin;
 		}
 
-		entry = acpi_pci_irq_find_prt_entry(bridge, pin);
-		if (entry) {
+		ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
+		if (!ret && entry) {
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 					 "Derived GSI for %s INT %c from %s\n",
 					 pci_name(dev), pin_name(orig_pin),
@@ -470,6 +448,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 			dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
 				 pin_name(pin));
 		}
+
 		return 0;
 	}
 
@@ -477,6 +456,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 	if (rc < 0) {
 		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
 			 pin_name(pin));
+		kfree(entry);
 		return rc;
 	}
 	dev->irq = rc;
@@ -491,6 +471,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 		(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 		(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+	kfree(entry);
 	return 0;
 }
 
@@ -513,6 +494,8 @@ void acpi_pci_irq_disable(struct pci_dev
 	else
 		gsi = entry->index;
 
+	kfree(entry);
+
 	/*
 	 * TBD: It might be worth clearing dev->irq by magic constant
 	 * (e.g. PCI_UNDEFINED_IRQ).
drivers/acpi/pci_root.c +0 -18
Index: linux-2.6/drivers/acpi/pci_root.c
===================================================================
@@ -413,7 +413,6 @@ static int acpi_pci_root_add(struct acpi
 	acpi_status status;
 	int result;
 	struct acpi_pci_root *root;
-	acpi_handle handle;
 	struct acpi_pci_driver *driver;
 	u32 flags, base_flags;
 	bool is_osc_granted = false;
@@ -468,16 +467,6 @@ static int acpi_pci_root_add(struct acpi
 	       acpi_device_name(device), acpi_device_bid(device),
 	       root->segment, &root->secondary);
 
-	/*
-	 * PCI Routing Table
-	 * -----------------
-	 * Evaluate and parse _PRT, if exists.
-	 */
-	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_SUCCESS(status))
-		result = acpi_pci_irq_add_prt(device->handle, root->segment,
-					      root->secondary.start);
-
 	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
 	/*
@@ -602,7 +591,6 @@ out_del_root:
 	list_del(&root->node);
 	mutex_unlock(&acpi_pci_root_lock);
 
-	acpi_pci_irq_del_prt(root->segment, root->secondary.start);
 end:
 	kfree(root);
 	return result;
@@ -610,8 +598,6 @@ end:
 
 static void acpi_pci_root_remove(struct acpi_device *device)
 {
-	acpi_status status;
-	acpi_handle handle;
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
@@ -626,10 +612,6 @@ static void acpi_pci_root_remove(struct
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
-	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_SUCCESS(status))
-		acpi_pci_irq_del_prt(root->segment, root->secondary.start);
-
 	pci_remove_root_bus(root->bus);
 
 	mutex_lock(&acpi_pci_root_lock);
drivers/pci/pci-acpi.c +0 -24
Index: linux-2.6/drivers/pci/pci-acpi.c
===================================================================
@@ -307,25 +307,6 @@ static void pci_acpi_setup(struct device
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
-	acpi_status status;
-	acpi_handle dummy;
-
-	/*
-	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
-	 * _PRT objects within the scope of non-bridge devices.  Note that
-	 * _PRTs within the scope of a PCI bridge assume the bridge's
-	 * subordinate bus number.
-	 *
-	 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
-	 */
-	status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy);
-	if (ACPI_SUCCESS(status)) {
-		unsigned char bus;
-
-		bus = pci_dev->subordinate ?
-			pci_dev->subordinate->number : pci_dev->bus->number;
-		acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
-	}
 
 	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
 		return;
@@ -340,7 +321,6 @@ static void pci_acpi_setup(struct device
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
 
@@ -349,10 +329,6 @@ static void pci_acpi_cleanup(struct devi
 		device_set_run_wake(dev, false);
 		pci_acpi_remove_pm_notifier(adev);
 	}
-
-	if (pci_dev->subordinate)
-		acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus),
-				     pci_dev->subordinate->number);
 }
 
 static struct acpi_bus_type acpi_pci_bus = {
include/acpi/acpi_drivers.h +0 -5
Index: linux-2.6/include/acpi/acpi_drivers.h
===================================================================
@@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_hand
 			       int *polarity, char **name);
 int acpi_pci_link_free_irq(acpi_handle handle);
 
-/* ACPI PCI Interrupt Routing (pci_irq.c) */
-
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
-void acpi_pci_irq_del_prt(int segment, int bus);
-
 /* ACPI PCI Device Binding (pci_bind.c) */
 
 struct pci_bus;
#17 lore raw

PATCH 1/1 ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

So here we try to remove _PRT caching completely.

-v2: check !handle early.

---
 drivers/acpi/pci_irq.c      |   95 +++++++++++++++++---------------------------
 drivers/acpi/pci_root.c     |   18 --------
 drivers/pci/pci-acpi.c      |   24 -----------
 include/acpi/acpi_drivers.h |    5 --
 4 files changed, 38 insertions(+), 104 deletions(-)
drivers/acpi/pci_irq.c +38 -57
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -53,9 +53,6 @@ struct acpi_prt_entry {
 	u32			index;		/* GSI, or link _CRS index */
 };
 
-static LIST_HEAD(acpi_prt_list);
-static DEFINE_SPINLOCK(acpi_prt_lock);
-
 static inline char pin_name(int pin)
 {
 	return 'A' + pin - 1;
@@ -65,28 +62,6 @@ static inline char pin_name(int pin)
                          PCI IRQ Routing Table (PRT) Support
    -------------------------------------------------------------------------- */
 
-static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
-							  int pin)
-{
-	struct acpi_prt_entry *entry;
-	int segment = pci_domain_nr(dev->bus);
-	int bus = dev->bus->number;
-	int device = PCI_SLOT(dev->devfn);
-
-	spin_lock(&acpi_prt_lock);
-	list_for_each_entry(entry, &acpi_prt_list, list) {
-		if ((segment == entry->id.segment)
-		    && (bus == entry->id.bus)
-		    && (device == entry->id.device)
-		    && (pin == entry->pin)) {
-			spin_unlock(&acpi_prt_lock);
-			return entry;
-		}
-	}
-	spin_unlock(&acpi_prt_lock);
-	return NULL;
-}
-
 /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
 static const struct dmi_system_id medion_md9580[] = {
 	{
@@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_pr
 	}
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
-				  struct acpi_pci_routing_table *prt)
+static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
+				  int pin, struct acpi_pci_routing_table *prt,
+				  struct acpi_prt_entry **entry_ptr)
 {
+	int segment = pci_domain_nr(dev->bus);
+	int bus = dev->bus->number;
+	int device = PCI_SLOT(dev->devfn);
 	struct acpi_prt_entry *entry;
 
+	if (((prt->address >> 16) & 0xffff) != device ||
+	    prt->pin + 1 != pin)
+		return -ENODEV;
+
 	entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
@@ -237,26 +220,33 @@ static int acpi_pci_irq_add_entry(acpi_h
 			      entry->id.device, pin_name(entry->pin),
 			      prt->source, entry->index));
 
-	spin_lock(&acpi_prt_lock);
-	list_add_tail(&entry->list, &acpi_prt_list);
-	spin_unlock(&acpi_prt_lock);
+	*entry_ptr = entry;
 
 	return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
+static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
+			  int pin, struct acpi_prt_entry **entry_ptr)
 {
 	acpi_status status;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_pci_routing_table *entry;
+	acpi_handle handle = NULL;
+
+	if (dev->bus->bridge)
+		handle = ACPI_HANDLE(dev->bus->bridge);
+
+	if (!handle)
+		return -ENODEV;
 
 	/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
 	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
-	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
-	       (char *) buffer.pointer);
+	dev_printk(KERN_DEBUG, &dev->dev,
+			"ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
+		       (char *) buffer.pointer);
 
 	kfree(buffer.pointer);
 
@@ -273,7 +263,9 @@ int acpi_pci_irq_add_prt(acpi_handle han
 
 	entry = buffer.pointer;
 	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, segment, bus, entry);
+		if (!acpi_pci_irq_check_entry(handle, dev, pin,
+						 entry, entry_ptr))
+			break;
 		entry = (struct acpi_pci_routing_table *)
 		    ((unsigned long)entry + entry->length);
 	}
@@ -282,23 +274,6 @@ int acpi_pci_irq_add_prt(acpi_handle han
 	return 0;
 }
 
-void acpi_pci_irq_del_prt(int segment, int bus)
-{
-	struct acpi_prt_entry *entry, *tmp;
-
-	printk(KERN_DEBUG
-	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-	       segment, bus);
-	spin_lock(&acpi_prt_lock);
-	list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-		if (segment == entry->id.segment && bus == entry->id.bus) {
-			list_del(&entry->list);
-			kfree(entry);
-		}
-	}
-	spin_unlock(&acpi_prt_lock);
-}
-
 /* --------------------------------------------------------------------------
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
@@ -359,12 +334,13 @@ static int acpi_reroute_boot_interrupt(s
 
 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 {
-	struct acpi_prt_entry *entry;
+	struct acpi_prt_entry *entry = NULL;
 	struct pci_dev *bridge;
 	u8 bridge_pin, orig_pin = pin;
+	int ret;
 
-	entry = acpi_pci_irq_find_prt_entry(dev, pin);
-	if (entry) {
+	ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
+	if (!ret && entry) {
 #ifdef CONFIG_X86_IO_APIC
 		acpi_reroute_boot_interrupt(dev, entry);
 #endif /* CONFIG_X86_IO_APIC */
@@ -373,7 +349,7 @@ static struct acpi_prt_entry *acpi_pci_i
 		return entry;
 	}
 
-	/* 
+	/*
 	 * Attempt to derive an IRQ for this device from a parent bridge's
 	 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
 	 */
@@ -393,8 +369,8 @@ static struct acpi_prt_entry *acpi_pci_i
 			pin = bridge_pin;
 		}
 
-		entry = acpi_pci_irq_find_prt_entry(bridge, pin);
-		if (entry) {
+		ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
+		if (!ret && entry) {
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 					 "Derived GSI for %s INT %c from %s\n",
 					 pci_name(dev), pin_name(orig_pin),
@@ -470,6 +446,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 			dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
 				 pin_name(pin));
 		}
+
 		return 0;
 	}
 
@@ -477,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 	if (rc < 0) {
 		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
 			 pin_name(pin));
+		kfree(entry);
 		return rc;
 	}
 	dev->irq = rc;
@@ -491,6 +469,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 		(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 		(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+	kfree(entry);
 	return 0;
 }
 
@@ -513,6 +492,8 @@ void acpi_pci_irq_disable(struct pci_dev
 	else
 		gsi = entry->index;
 
+	kfree(entry);
+
 	/*
 	 * TBD: It might be worth clearing dev->irq by magic constant
 	 * (e.g. PCI_UNDEFINED_IRQ).
drivers/acpi/pci_root.c +0 -18
Index: linux-2.6/drivers/acpi/pci_root.c
===================================================================
@@ -413,7 +413,6 @@ static int acpi_pci_root_add(struct acpi
 	acpi_status status;
 	int result;
 	struct acpi_pci_root *root;
-	acpi_handle handle;
 	struct acpi_pci_driver *driver;
 	u32 flags, base_flags;
 	bool is_osc_granted = false;
@@ -468,16 +467,6 @@ static int acpi_pci_root_add(struct acpi
 	       acpi_device_name(device), acpi_device_bid(device),
 	       root->segment, &root->secondary);
 
-	/*
-	 * PCI Routing Table
-	 * -----------------
-	 * Evaluate and parse _PRT, if exists.
-	 */
-	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_SUCCESS(status))
-		result = acpi_pci_irq_add_prt(device->handle, root->segment,
-					      root->secondary.start);
-
 	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
 	/*
@@ -602,7 +591,6 @@ out_del_root:
 	list_del(&root->node);
 	mutex_unlock(&acpi_pci_root_lock);
 
-	acpi_pci_irq_del_prt(root->segment, root->secondary.start);
 end:
 	kfree(root);
 	return result;
@@ -610,8 +598,6 @@ end:
 
 static void acpi_pci_root_remove(struct acpi_device *device)
 {
-	acpi_status status;
-	acpi_handle handle;
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
@@ -626,10 +612,6 @@ static void acpi_pci_root_remove(struct
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
-	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_SUCCESS(status))
-		acpi_pci_irq_del_prt(root->segment, root->secondary.start);
-
 	pci_remove_root_bus(root->bus);
 
 	mutex_lock(&acpi_pci_root_lock);
drivers/pci/pci-acpi.c +0 -24
Index: linux-2.6/drivers/pci/pci-acpi.c
===================================================================
@@ -307,25 +307,6 @@ static void pci_acpi_setup(struct device
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
-	acpi_status status;
-	acpi_handle dummy;
-
-	/*
-	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
-	 * _PRT objects within the scope of non-bridge devices.  Note that
-	 * _PRTs within the scope of a PCI bridge assume the bridge's
-	 * subordinate bus number.
-	 *
-	 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
-	 */
-	status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy);
-	if (ACPI_SUCCESS(status)) {
-		unsigned char bus;
-
-		bus = pci_dev->subordinate ?
-			pci_dev->subordinate->number : pci_dev->bus->number;
-		acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
-	}
 
 	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
 		return;
@@ -340,7 +321,6 @@ static void pci_acpi_setup(struct device
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
 
@@ -349,10 +329,6 @@ static void pci_acpi_cleanup(struct devi
 		device_set_run_wake(dev, false);
 		pci_acpi_remove_pm_notifier(adev);
 	}
-
-	if (pci_dev->subordinate)
-		acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus),
-				     pci_dev->subordinate->number);
 }
 
 static struct acpi_bus_type acpi_pci_bus = {
include/acpi/acpi_drivers.h +0 -5
Index: linux-2.6/include/acpi/acpi_drivers.h
===================================================================
@@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_hand
 			       int *polarity, char **name);
 int acpi_pci_link_free_irq(acpi_handle handle);
 
-/* ACPI PCI Interrupt Routing (pci_irq.c) */
-
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
-void acpi_pci_irq_del_prt(int segment, int bus);
-
 /* ACPI PCI Device Binding (pci_bind.c) */
 
 struct pci_bus;
Acked-by on v1 1/1
#18 lore raw

Re: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Quoted 24 lines · Yinghai Lu

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

Quoted 7 lines

So here we try to remove _PRT caching completely.

-v2: check !handle early.

Quoted 339 lines
---
 drivers/acpi/pci_irq.c      |   95 +++++++++++++++++---------------------------
 drivers/acpi/pci_root.c     |   18 --------
 drivers/pci/pci-acpi.c      |   24 -----------
 include/acpi/acpi_drivers.h |    5 --
 4 files changed, 38 insertions(+), 104 deletions(-)

Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================

drivers/acpi/pci_irq.c +38 -57
@@ -53,9 +53,6 @@ struct acpi_prt_entry {
 	u32			index;		/* GSI, or link _CRS index */
 };
 
-static LIST_HEAD(acpi_prt_list);
-static DEFINE_SPINLOCK(acpi_prt_lock);
-
 static inline char pin_name(int pin)
 {
 	return 'A' + pin - 1;
@@ -65,28 +62,6 @@ static inline char pin_name(int pin)
                          PCI IRQ Routing Table (PRT) Support
    -------------------------------------------------------------------------- */
 
-static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
-							  int pin)
-{
-	struct acpi_prt_entry *entry;
-	int segment = pci_domain_nr(dev->bus);
-	int bus = dev->bus->number;
-	int device = PCI_SLOT(dev->devfn);
-
-	spin_lock(&acpi_prt_lock);
-	list_for_each_entry(entry, &acpi_prt_list, list) {
-		if ((segment == entry->id.segment)
-		    && (bus == entry->id.bus)
-		    && (device == entry->id.device)
-		    && (pin == entry->pin)) {
-			spin_unlock(&acpi_prt_lock);
-			return entry;
-		}
-	}
-	spin_unlock(&acpi_prt_lock);
-	return NULL;
-}
-
 /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
 static const struct dmi_system_id medion_md9580[] = {
 	{
@@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_pr
 	}
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
-				  struct acpi_pci_routing_table *prt)
+static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
+				  int pin, struct acpi_pci_routing_table *prt,
+				  struct acpi_prt_entry **entry_ptr)
 {
+	int segment = pci_domain_nr(dev->bus);
+	int bus = dev->bus->number;
+	int device = PCI_SLOT(dev->devfn);
 	struct acpi_prt_entry *entry;
 
+	if (((prt->address >> 16) & 0xffff) != device ||
+	    prt->pin + 1 != pin)
+		return -ENODEV;
+
 	entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
@@ -237,26 +220,33 @@ static int acpi_pci_irq_add_entry(acpi_h
 			      entry->id.device, pin_name(entry->pin),
 			      prt->source, entry->index));
 
-	spin_lock(&acpi_prt_lock);
-	list_add_tail(&entry->list, &acpi_prt_list);
-	spin_unlock(&acpi_prt_lock);
+	*entry_ptr = entry;
 
 	return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
+static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
+			  int pin, struct acpi_prt_entry **entry_ptr)
 {
 	acpi_status status;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_pci_routing_table *entry;
+	acpi_handle handle = NULL;
+
+	if (dev->bus->bridge)
+		handle = ACPI_HANDLE(dev->bus->bridge);
+
+	if (!handle)
+		return -ENODEV;
 
 	/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
 	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
-	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
-	       (char *) buffer.pointer);
+	dev_printk(KERN_DEBUG, &dev->dev,
+			"ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
+		       (char *) buffer.pointer);
 
 	kfree(buffer.pointer);
 
@@ -273,7 +263,9 @@ int acpi_pci_irq_add_prt(acpi_handle han
 
 	entry = buffer.pointer;
 	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, segment, bus, entry);
+		if (!acpi_pci_irq_check_entry(handle, dev, pin,
+						 entry, entry_ptr))
+			break;
 		entry = (struct acpi_pci_routing_table *)
 		    ((unsigned long)entry + entry->length);
 	}
@@ -282,23 +274,6 @@ int acpi_pci_irq_add_prt(acpi_handle han
 	return 0;
 }
 
-void acpi_pci_irq_del_prt(int segment, int bus)
-{
-	struct acpi_prt_entry *entry, *tmp;
-
-	printk(KERN_DEBUG
-	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-	       segment, bus);
-	spin_lock(&acpi_prt_lock);
-	list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-		if (segment == entry->id.segment && bus == entry->id.bus) {
-			list_del(&entry->list);
-			kfree(entry);
-		}
-	}
-	spin_unlock(&acpi_prt_lock);
-}
-
 /* --------------------------------------------------------------------------
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
@@ -359,12 +334,13 @@ static int acpi_reroute_boot_interrupt(s
 
 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 {
-	struct acpi_prt_entry *entry;
+	struct acpi_prt_entry *entry = NULL;
 	struct pci_dev *bridge;
 	u8 bridge_pin, orig_pin = pin;
+	int ret;
 
-	entry = acpi_pci_irq_find_prt_entry(dev, pin);
-	if (entry) {
+	ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
+	if (!ret && entry) {
 #ifdef CONFIG_X86_IO_APIC
 		acpi_reroute_boot_interrupt(dev, entry);
 #endif /* CONFIG_X86_IO_APIC */
@@ -373,7 +349,7 @@ static struct acpi_prt_entry *acpi_pci_i
 		return entry;
 	}
 
-	/* 
+	/*
 	 * Attempt to derive an IRQ for this device from a parent bridge's
 	 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
 	 */
@@ -393,8 +369,8 @@ static struct acpi_prt_entry *acpi_pci_i
 			pin = bridge_pin;
 		}
 
-		entry = acpi_pci_irq_find_prt_entry(bridge, pin);
-		if (entry) {
+		ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
+		if (!ret && entry) {
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 					 "Derived GSI for %s INT %c from %s\n",
 					 pci_name(dev), pin_name(orig_pin),
@@ -470,6 +446,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 			dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
 				 pin_name(pin));
 		}
+
 		return 0;
 	}
 
@@ -477,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 	if (rc < 0) {
 		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
 			 pin_name(pin));
+		kfree(entry);
 		return rc;
 	}
 	dev->irq = rc;
@@ -491,6 +469,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 		(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 		(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+	kfree(entry);
 	return 0;
 }
 
@@ -513,6 +492,8 @@ void acpi_pci_irq_disable(struct pci_dev
 	else
 		gsi = entry->index;
 
+	kfree(entry);
+
 	/*
 	 * TBD: It might be worth clearing dev->irq by magic constant
 	 * (e.g. PCI_UNDEFINED_IRQ).

Index: linux-2.6/drivers/acpi/pci_root.c
===================================================================

drivers/acpi/pci_root.c +0 -18
@@ -413,7 +413,6 @@ static int acpi_pci_root_add(struct acpi
 	acpi_status status;
 	int result;
 	struct acpi_pci_root *root;
-	acpi_handle handle;
 	struct acpi_pci_driver *driver;
 	u32 flags, base_flags;
 	bool is_osc_granted = false;
@@ -468,16 +467,6 @@ static int acpi_pci_root_add(struct acpi
 	       acpi_device_name(device), acpi_device_bid(device),
 	       root->segment, &root->secondary);
 
-	/*
-	 * PCI Routing Table
-	 * -----------------
-	 * Evaluate and parse _PRT, if exists.
-	 */
-	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_SUCCESS(status))
-		result = acpi_pci_irq_add_prt(device->handle, root->segment,
-					      root->secondary.start);
-
 	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
 	/*
@@ -602,7 +591,6 @@ out_del_root:
 	list_del(&root->node);
 	mutex_unlock(&acpi_pci_root_lock);
 
-	acpi_pci_irq_del_prt(root->segment, root->secondary.start);
 end:
 	kfree(root);
 	return result;
@@ -610,8 +598,6 @@ end:
 
 static void acpi_pci_root_remove(struct acpi_device *device)
 {
-	acpi_status status;
-	acpi_handle handle;
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
@@ -626,10 +612,6 @@ static void acpi_pci_root_remove(struct
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
-	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_SUCCESS(status))
-		acpi_pci_irq_del_prt(root->segment, root->secondary.start);
-
 	pci_remove_root_bus(root->bus);
 
 	mutex_lock(&acpi_pci_root_lock);

Index: linux-2.6/drivers/pci/pci-acpi.c
===================================================================

drivers/pci/pci-acpi.c +0 -24
@@ -307,25 +307,6 @@ static void pci_acpi_setup(struct device
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
-	acpi_status status;
-	acpi_handle dummy;
-
-	/*
-	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
-	 * _PRT objects within the scope of non-bridge devices.  Note that
-	 * _PRTs within the scope of a PCI bridge assume the bridge's
-	 * subordinate bus number.
-	 *
-	 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
-	 */
-	status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy);
-	if (ACPI_SUCCESS(status)) {
-		unsigned char bus;
-
-		bus = pci_dev->subordinate ?
-			pci_dev->subordinate->number : pci_dev->bus->number;
-		acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
-	}
 
 	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
 		return;
@@ -340,7 +321,6 @@ static void pci_acpi_setup(struct device
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
 
@@ -349,10 +329,6 @@ static void pci_acpi_cleanup(struct devi
 		device_set_run_wake(dev, false);
 		pci_acpi_remove_pm_notifier(adev);
 	}
-
-	if (pci_dev->subordinate)
-		acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus),
-				     pci_dev->subordinate->number);
 }
 
 static struct acpi_bus_type acpi_pci_bus = {

Index: linux-2.6/include/acpi/acpi_drivers.h
===================================================================

include/acpi/acpi_drivers.h +0 -5
@@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_hand
 			       int *polarity, char **name);
 int acpi_pci_link_free_irq(acpi_handle handle);
 
-/* ACPI PCI Interrupt Routing (pci_irq.c) */
-
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
-void acpi_pci_irq_del_prt(int segment, int bus);
-
 /* ACPI PCI Device Binding (pci_bind.c) */
 
 struct pci_bus;
Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#19 lore raw

Re: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Quoted 27 lines · Rafael J. Wysocki
Quoted 26 lines · Yinghai Lu

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

So here we try to remove _PRT caching completely.

Quoted 14 lines
Quoted 5 lines

-v2: check !handle early.

Quoted 6 lines
---
 drivers/acpi/pci_irq.c      |   95 +++++++++++++++++---------------------------
 drivers/acpi/pci_root.c     |   18 --------
 drivers/pci/pci-acpi.c      |   24 -----------
 include/acpi/acpi_drivers.h |    5 --
 4 files changed, 38 insertions(+), 104 deletions(-)

Bjorn,

Can you put this one into pci/next?

Thanks

Yinghai

Quoted 340 lines
Quoted 323 lines

Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================

drivers/acpi/pci_irq.c +38 -57
@@ -53,9 +53,6 @@ struct acpi_prt_entry {
      u32                     index;          /* GSI, or link _CRS index */
 };
 
-static LIST_HEAD(acpi_prt_list);
-static DEFINE_SPINLOCK(acpi_prt_lock);
-
 static inline char pin_name(int pin)
 {
      return 'A' + pin - 1;
@@ -65,28 +62,6 @@ static inline char pin_name(int pin)
                          PCI IRQ Routing Table (PRT) Support
    -------------------------------------------------------------------------- */
 
-static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
-                                                       int pin)
-{
-     struct acpi_prt_entry *entry;
-     int segment = pci_domain_nr(dev->bus);
-     int bus = dev->bus->number;
-     int device = PCI_SLOT(dev->devfn);
-
-     spin_lock(&acpi_prt_lock);
-     list_for_each_entry(entry, &acpi_prt_list, list) {
-             if ((segment == entry->id.segment)
-                 && (bus == entry->id.bus)
-                 && (device == entry->id.device)
-                 && (pin == entry->pin)) {
-                     spin_unlock(&acpi_prt_lock);
-                     return entry;
-             }
-     }
-     spin_unlock(&acpi_prt_lock);
-     return NULL;
-}
-
 /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
 static const struct dmi_system_id medion_md9580[] = {
      {
@@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_pr
      }
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
-                               struct acpi_pci_routing_table *prt)
+static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
+                               int pin, struct acpi_pci_routing_table *prt,
+                               struct acpi_prt_entry **entry_ptr)
 {
+     int segment = pci_domain_nr(dev->bus);
+     int bus = dev->bus->number;
+     int device = PCI_SLOT(dev->devfn);
      struct acpi_prt_entry *entry;
 
+     if (((prt->address >> 16) & 0xffff) != device ||
+         prt->pin + 1 != pin)
+             return -ENODEV;
+
      entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
      if (!entry)
              return -ENOMEM;
@@ -237,26 +220,33 @@ static int acpi_pci_irq_add_entry(acpi_h
                            entry->id.device, pin_name(entry->pin),
                            prt->source, entry->index));
 
-     spin_lock(&acpi_prt_lock);
-     list_add_tail(&entry->list, &acpi_prt_list);
-     spin_unlock(&acpi_prt_lock);
+     *entry_ptr = entry;
 
      return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
+static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
+                       int pin, struct acpi_prt_entry **entry_ptr)
 {
      acpi_status status;
      struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
      struct acpi_pci_routing_table *entry;
+     acpi_handle handle = NULL;
+
+     if (dev->bus->bridge)
+             handle = ACPI_HANDLE(dev->bus->bridge);
+
+     if (!handle)
+             return -ENODEV;
 
      /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
      status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
      if (ACPI_FAILURE(status))
              return -ENODEV;
 
-     printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
-            (char *) buffer.pointer);
+     dev_printk(KERN_DEBUG, &dev->dev,
+                     "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
+                    (char *) buffer.pointer);
 
      kfree(buffer.pointer);
 
@@ -273,7 +263,9 @@ int acpi_pci_irq_add_prt(acpi_handle han
 
      entry = buffer.pointer;
      while (entry && (entry->length > 0)) {
-             acpi_pci_irq_add_entry(handle, segment, bus, entry);
+             if (!acpi_pci_irq_check_entry(handle, dev, pin,
+                                              entry, entry_ptr))
+                     break;
              entry = (struct acpi_pci_routing_table *)
                  ((unsigned long)entry + entry->length);
      }
@@ -282,23 +274,6 @@ int acpi_pci_irq_add_prt(acpi_handle han
      return 0;
 }
 
-void acpi_pci_irq_del_prt(int segment, int bus)
-{
-     struct acpi_prt_entry *entry, *tmp;
-
-     printk(KERN_DEBUG
-            "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-            segment, bus);
-     spin_lock(&acpi_prt_lock);
-     list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-             if (segment == entry->id.segment && bus == entry->id.bus) {
-                     list_del(&entry->list);
-                     kfree(entry);
-             }
-     }
-     spin_unlock(&acpi_prt_lock);
-}
-
 /* --------------------------------------------------------------------------
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
@@ -359,12 +334,13 @@ static int acpi_reroute_boot_interrupt(s
 
 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 {
-     struct acpi_prt_entry *entry;
+     struct acpi_prt_entry *entry = NULL;
      struct pci_dev *bridge;
      u8 bridge_pin, orig_pin = pin;
+     int ret;
 
-     entry = acpi_pci_irq_find_prt_entry(dev, pin);
-     if (entry) {
+     ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
+     if (!ret && entry) {
 #ifdef CONFIG_X86_IO_APIC
              acpi_reroute_boot_interrupt(dev, entry);
 #endif /* CONFIG_X86_IO_APIC */
@@ -373,7 +349,7 @@ static struct acpi_prt_entry *acpi_pci_i
              return entry;
      }
 
-     /*
+     /*
       * Attempt to derive an IRQ for this device from a parent bridge's
       * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
       */
@@ -393,8 +369,8 @@ static struct acpi_prt_entry *acpi_pci_i
                      pin = bridge_pin;
              }
 
-             entry = acpi_pci_irq_find_prt_entry(bridge, pin);
-             if (entry) {
+             ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
+             if (!ret && entry) {
                      ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                       "Derived GSI for %s INT %c from %s\n",
                                       pci_name(dev), pin_name(orig_pin),
@@ -470,6 +446,7 @@ int acpi_pci_irq_enable(struct pci_dev *
                      dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
                               pin_name(pin));
              }
+
              return 0;
      }
 
@@ -477,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *
      if (rc < 0) {
              dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
                       pin_name(pin));
+             kfree(entry);
              return rc;
      }
      dev->irq = rc;
@@ -491,6 +469,7 @@ int acpi_pci_irq_enable(struct pci_dev *
              (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
              (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+     kfree(entry);
      return 0;
 }
 
@@ -513,6 +492,8 @@ void acpi_pci_irq_disable(struct pci_dev
      else
              gsi = entry->index;
 
+     kfree(entry);
+
      /*
       * TBD: It might be worth clearing dev->irq by magic constant
       * (e.g. PCI_UNDEFINED_IRQ).

Index: linux-2.6/drivers/acpi/pci_root.c
===================================================================

drivers/acpi/pci_root.c +0 -18
@@ -413,7 +413,6 @@ static int acpi_pci_root_add(struct acpi
      acpi_status status;
      int result;
      struct acpi_pci_root *root;
-     acpi_handle handle;
      struct acpi_pci_driver *driver;
      u32 flags, base_flags;
      bool is_osc_granted = false;
@@ -468,16 +467,6 @@ static int acpi_pci_root_add(struct acpi
             acpi_device_name(device), acpi_device_bid(device),
             root->segment, &root->secondary);
 
-     /*
-      * PCI Routing Table
-      * -----------------
-      * Evaluate and parse _PRT, if exists.
-      */
-     status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-     if (ACPI_SUCCESS(status))
-             result = acpi_pci_irq_add_prt(device->handle, root->segment,
-                                           root->secondary.start);
-
      root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
      /*
@@ -602,7 +591,6 @@ out_del_root:
      list_del(&root->node);
      mutex_unlock(&acpi_pci_root_lock);
 
-     acpi_pci_irq_del_prt(root->segment, root->secondary.start);
 end:
      kfree(root);
      return result;
@@ -610,8 +598,6 @@ end:
 
 static void acpi_pci_root_remove(struct acpi_device *device)
 {
-     acpi_status status;
-     acpi_handle handle;
      struct acpi_pci_root *root = acpi_driver_data(device);
      struct acpi_pci_driver *driver;
 
@@ -626,10 +612,6 @@ static void acpi_pci_root_remove(struct
      device_set_run_wake(root->bus->bridge, false);
      pci_acpi_remove_bus_pm_notifier(device);
 
-     status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-     if (ACPI_SUCCESS(status))
-             acpi_pci_irq_del_prt(root->segment, root->secondary.start);
-
      pci_remove_root_bus(root->bus);
 
      mutex_lock(&acpi_pci_root_lock);

Index: linux-2.6/drivers/pci/pci-acpi.c
===================================================================

drivers/pci/pci-acpi.c +0 -24
@@ -307,25 +307,6 @@ static void pci_acpi_setup(struct device
      struct pci_dev *pci_dev = to_pci_dev(dev);
      acpi_handle handle = ACPI_HANDLE(dev);
      struct acpi_device *adev;
-     acpi_status status;
-     acpi_handle dummy;
-
-     /*
-      * Evaluate and parse _PRT, if exists.  This code allows parsing of
-      * _PRT objects within the scope of non-bridge devices.  Note that
-      * _PRTs within the scope of a PCI bridge assume the bridge's
-      * subordinate bus number.
-      *
-      * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
-      */
-     status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy);
-     if (ACPI_SUCCESS(status)) {
-             unsigned char bus;
-
-             bus = pci_dev->subordinate ?
-                     pci_dev->subordinate->number : pci_dev->bus->number;
-             acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
-     }
 
      if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
              return;
@@ -340,7 +321,6 @@ static void pci_acpi_setup(struct device
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-     struct pci_dev *pci_dev = to_pci_dev(dev);
      acpi_handle handle = ACPI_HANDLE(dev);
      struct acpi_device *adev;
 
@@ -349,10 +329,6 @@ static void pci_acpi_cleanup(struct devi
              device_set_run_wake(dev, false);
              pci_acpi_remove_pm_notifier(adev);
      }
-
-     if (pci_dev->subordinate)
-             acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus),
-                                  pci_dev->subordinate->number);
 }
 
 static struct acpi_bus_type acpi_pci_bus = {

Index: linux-2.6/include/acpi/acpi_drivers.h
===================================================================

include/acpi/acpi_drivers.h +0 -0
@@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_hand
                             int *polarity, char **name);

include/acpi/acpi_drivers.h int acpi_pci_link_allocate_irq(acpi_hand · line 95

Quoted 10 lines
include/acpi/acpi_drivers.h +0 -5
 int acpi_pci_link_free_irq(acpi_handle handle);
 
-/* ACPI PCI Interrupt Routing (pci_irq.c) */
-
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
-void acpi_pci_irq_del_prt(int segment, int bus);
-
 /* ACPI PCI Device Binding (pci_bind.c) */
 
 struct pci_bus;

--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer
#20 lore raw

Re: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Quoted 43 lines · Yinghai Lu
Quoted 27 lines · Rafael J. Wysocki
Quoted 26 lines · Yinghai Lu

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

So here we try to remove _PRT caching completely.

Quoted 14 lines
Quoted 5 lines

-v2: check !handle early.

Quoted 6 lines
---
 drivers/acpi/pci_irq.c      |   95 +++++++++++++++++---------------------------
 drivers/acpi/pci_root.c     |   18 --------
 drivers/pci/pci-acpi.c      |   24 -----------
 include/acpi/acpi_drivers.h |    5 --
 4 files changed, 38 insertions(+), 104 deletions(-)
Quoted 3 lines

Bjorn,

Can you put this one into pci/next?

I'm not sure what this patch is based on or what the best way to merge it is. It doesn't apply cleanly to my next or pci/yinghai-root-bus-hotplug branches.

I did apply it manually on top of pci/yinghai-root-bus-hotplug to try it out, but we need to tweak the messages a little bit.

Previously we printed "ACPI: PCI Interrupt Routing Table [%s._PRT]" once when loading it, which was fine. Now we print it every time we look at a _PRT, which is too much because it isn't really adding any information.

We also print "ACPI Exception: AE_NOT_FOUND, Evaluating _PRT [AE_NOT_FOUND] (20121018/pci_irq-259)" if we find ACPI nodes without _PRTs, which we shouldn't do, because that's a common and normal situation.

Bjorn

Quoted 339 lines
Quoted 339 lines
Quoted 322 lines

Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================

drivers/acpi/pci_irq.c +38 -57
@@ -53,9 +53,6 @@ struct acpi_prt_entry {
      u32                     index;          /* GSI, or link _CRS index */
 };
 
-static LIST_HEAD(acpi_prt_list);
-static DEFINE_SPINLOCK(acpi_prt_lock);
-
 static inline char pin_name(int pin)
 {
      return 'A' + pin - 1;
@@ -65,28 +62,6 @@ static inline char pin_name(int pin)
                          PCI IRQ Routing Table (PRT) Support
    -------------------------------------------------------------------------- */
 
-static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
-                                                       int pin)
-{
-     struct acpi_prt_entry *entry;
-     int segment = pci_domain_nr(dev->bus);
-     int bus = dev->bus->number;
-     int device = PCI_SLOT(dev->devfn);
-
-     spin_lock(&acpi_prt_lock);
-     list_for_each_entry(entry, &acpi_prt_list, list) {
-             if ((segment == entry->id.segment)
-                 && (bus == entry->id.bus)
-                 && (device == entry->id.device)
-                 && (pin == entry->pin)) {
-                     spin_unlock(&acpi_prt_lock);
-                     return entry;
-             }
-     }
-     spin_unlock(&acpi_prt_lock);
-     return NULL;
-}
-
 /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
 static const struct dmi_system_id medion_md9580[] = {
      {
@@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_pr
      }
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
-                               struct acpi_pci_routing_table *prt)
+static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
+                               int pin, struct acpi_pci_routing_table *prt,
+                               struct acpi_prt_entry **entry_ptr)
 {
+     int segment = pci_domain_nr(dev->bus);
+     int bus = dev->bus->number;
+     int device = PCI_SLOT(dev->devfn);
      struct acpi_prt_entry *entry;
 
+     if (((prt->address >> 16) & 0xffff) != device ||
+         prt->pin + 1 != pin)
+             return -ENODEV;
+
      entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
      if (!entry)
              return -ENOMEM;
@@ -237,26 +220,33 @@ static int acpi_pci_irq_add_entry(acpi_h
                            entry->id.device, pin_name(entry->pin),
                            prt->source, entry->index));
 
-     spin_lock(&acpi_prt_lock);
-     list_add_tail(&entry->list, &acpi_prt_list);
-     spin_unlock(&acpi_prt_lock);
+     *entry_ptr = entry;
 
      return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
+static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
+                       int pin, struct acpi_prt_entry **entry_ptr)
 {
      acpi_status status;
      struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
      struct acpi_pci_routing_table *entry;
+     acpi_handle handle = NULL;
+
+     if (dev->bus->bridge)
+             handle = ACPI_HANDLE(dev->bus->bridge);
+
+     if (!handle)
+             return -ENODEV;
 
      /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
      status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
      if (ACPI_FAILURE(status))
              return -ENODEV;
 
-     printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
-            (char *) buffer.pointer);
+     dev_printk(KERN_DEBUG, &dev->dev,
+                     "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
+                    (char *) buffer.pointer);
 
      kfree(buffer.pointer);
 
@@ -273,7 +263,9 @@ int acpi_pci_irq_add_prt(acpi_handle han
 
      entry = buffer.pointer;
      while (entry && (entry->length > 0)) {
-             acpi_pci_irq_add_entry(handle, segment, bus, entry);
+             if (!acpi_pci_irq_check_entry(handle, dev, pin,
+                                              entry, entry_ptr))
+                     break;
              entry = (struct acpi_pci_routing_table *)
                  ((unsigned long)entry + entry->length);
      }
@@ -282,23 +274,6 @@ int acpi_pci_irq_add_prt(acpi_handle han
      return 0;
 }
 
-void acpi_pci_irq_del_prt(int segment, int bus)
-{
-     struct acpi_prt_entry *entry, *tmp;
-
-     printk(KERN_DEBUG
-            "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-            segment, bus);
-     spin_lock(&acpi_prt_lock);
-     list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-             if (segment == entry->id.segment && bus == entry->id.bus) {
-                     list_del(&entry->list);
-                     kfree(entry);
-             }
-     }
-     spin_unlock(&acpi_prt_lock);
-}
-
 /* --------------------------------------------------------------------------
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
@@ -359,12 +334,13 @@ static int acpi_reroute_boot_interrupt(s
 
 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 {
-     struct acpi_prt_entry *entry;
+     struct acpi_prt_entry *entry = NULL;
      struct pci_dev *bridge;
      u8 bridge_pin, orig_pin = pin;
+     int ret;
 
-     entry = acpi_pci_irq_find_prt_entry(dev, pin);
-     if (entry) {
+     ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
+     if (!ret && entry) {
 #ifdef CONFIG_X86_IO_APIC
              acpi_reroute_boot_interrupt(dev, entry);
 #endif /* CONFIG_X86_IO_APIC */
@@ -373,7 +349,7 @@ static struct acpi_prt_entry *acpi_pci_i
              return entry;
      }
 
-     /*
+     /*
       * Attempt to derive an IRQ for this device from a parent bridge's
       * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
       */
@@ -393,8 +369,8 @@ static struct acpi_prt_entry *acpi_pci_i
                      pin = bridge_pin;
              }
 
-             entry = acpi_pci_irq_find_prt_entry(bridge, pin);
-             if (entry) {
+             ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
+             if (!ret && entry) {
                      ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                       "Derived GSI for %s INT %c from %s\n",
                                       pci_name(dev), pin_name(orig_pin),
@@ -470,6 +446,7 @@ int acpi_pci_irq_enable(struct pci_dev *
                      dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
                               pin_name(pin));
              }
+
              return 0;
      }
 
@@ -477,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *
      if (rc < 0) {
              dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
                       pin_name(pin));
+             kfree(entry);
              return rc;
      }
      dev->irq = rc;
@@ -491,6 +469,7 @@ int acpi_pci_irq_enable(struct pci_dev *
              (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
              (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+     kfree(entry);
      return 0;
 }
 
@@ -513,6 +492,8 @@ void acpi_pci_irq_disable(struct pci_dev
      else
              gsi = entry->index;
 
+     kfree(entry);
+
      /*
       * TBD: It might be worth clearing dev->irq by magic constant
       * (e.g. PCI_UNDEFINED_IRQ).

Index: linux-2.6/drivers/acpi/pci_root.c
===================================================================

drivers/acpi/pci_root.c +0 -18
@@ -413,7 +413,6 @@ static int acpi_pci_root_add(struct acpi
      acpi_status status;
      int result;
      struct acpi_pci_root *root;
-     acpi_handle handle;
      struct acpi_pci_driver *driver;
      u32 flags, base_flags;
      bool is_osc_granted = false;
@@ -468,16 +467,6 @@ static int acpi_pci_root_add(struct acpi
             acpi_device_name(device), acpi_device_bid(device),
             root->segment, &root->secondary);
 
-     /*
-      * PCI Routing Table
-      * -----------------
-      * Evaluate and parse _PRT, if exists.
-      */
-     status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-     if (ACPI_SUCCESS(status))
-             result = acpi_pci_irq_add_prt(device->handle, root->segment,
-                                           root->secondary.start);
-
      root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
      /*
@@ -602,7 +591,6 @@ out_del_root:
      list_del(&root->node);
      mutex_unlock(&acpi_pci_root_lock);
 
-     acpi_pci_irq_del_prt(root->segment, root->secondary.start);
 end:
      kfree(root);
      return result;
@@ -610,8 +598,6 @@ end:
 
 static void acpi_pci_root_remove(struct acpi_device *device)
 {
-     acpi_status status;
-     acpi_handle handle;
      struct acpi_pci_root *root = acpi_driver_data(device);
      struct acpi_pci_driver *driver;
 
@@ -626,10 +612,6 @@ static void acpi_pci_root_remove(struct
      device_set_run_wake(root->bus->bridge, false);
      pci_acpi_remove_bus_pm_notifier(device);
 
-     status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-     if (ACPI_SUCCESS(status))
-             acpi_pci_irq_del_prt(root->segment, root->secondary.start);
-
      pci_remove_root_bus(root->bus);
 
      mutex_lock(&acpi_pci_root_lock);

Index: linux-2.6/drivers/pci/pci-acpi.c
===================================================================

drivers/pci/pci-acpi.c +0 -24
@@ -307,25 +307,6 @@ static void pci_acpi_setup(struct device
      struct pci_dev *pci_dev = to_pci_dev(dev);
      acpi_handle handle = ACPI_HANDLE(dev);
      struct acpi_device *adev;
-     acpi_status status;
-     acpi_handle dummy;
-
-     /*
-      * Evaluate and parse _PRT, if exists.  This code allows parsing of
-      * _PRT objects within the scope of non-bridge devices.  Note that
-      * _PRTs within the scope of a PCI bridge assume the bridge's
-      * subordinate bus number.
-      *
-      * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
-      */
-     status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy);
-     if (ACPI_SUCCESS(status)) {
-             unsigned char bus;
-
-             bus = pci_dev->subordinate ?
-                     pci_dev->subordinate->number : pci_dev->bus->number;
-             acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
-     }
 
      if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
              return;
@@ -340,7 +321,6 @@ static void pci_acpi_setup(struct device
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-     struct pci_dev *pci_dev = to_pci_dev(dev);
      acpi_handle handle = ACPI_HANDLE(dev);
      struct acpi_device *adev;
 
@@ -349,10 +329,6 @@ static void pci_acpi_cleanup(struct devi
              device_set_run_wake(dev, false);
              pci_acpi_remove_pm_notifier(adev);
      }
-
-     if (pci_dev->subordinate)
-             acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus),
-                                  pci_dev->subordinate->number);
 }
 
 static struct acpi_bus_type acpi_pci_bus = {

Index: linux-2.6/include/acpi/acpi_drivers.h
===================================================================

include/acpi/acpi_drivers.h +0 -0
@@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_hand
                             int *polarity, char **name);

include/acpi/acpi_drivers.h int acpi_pci_link_allocate_irq(acpi_hand · line 95

Quoted 10 lines
include/acpi/acpi_drivers.h +0 -5
 int acpi_pci_link_free_irq(acpi_handle handle);
 
-/* ACPI PCI Interrupt Routing (pci_irq.c) */
-
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
-void acpi_pci_irq_del_prt(int segment, int bus);
-
 /* ACPI PCI Device Binding (pci_bind.c) */
 
 struct pci_bus;

--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#21 lore raw

Re: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Quoted 44 lines · Bjorn Helgaas
Quoted 43 lines · Yinghai Lu
Quoted 41 lines · Rafael J. Wysocki
Quoted 24 lines · Yinghai Lu

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

Quoted 7 lines

So here we try to remove _PRT caching completely.

-v2: check !handle early.

Quoted 6 lines
---
 drivers/acpi/pci_irq.c      |   95 +++++++++++++++++---------------------------
 drivers/acpi/pci_root.c     |   18 --------
 drivers/pci/pci-acpi.c      |   24 -----------
 include/acpi/acpi_drivers.h |    5 --
 4 files changed, 38 insertions(+), 104 deletions(-)
Quoted 7 lines
Quoted 3 lines

Bjorn,

Can you put this one into pci/next?

I'm not sure what this patch is based on or what the best way to merge it is. It doesn't apply cleanly to my next or pci/yinghai-root-bus-hotplug branches.

My fault, that is based on pci/next + pm/linux-next

linux-next removed
acpi_power_resource_(un)register_device ...

Quoted 9 lines

I did apply it manually on top of pci/yinghai-root-bus-hotplug to try it out, but we need to tweak the messages a little bit.

Previously we printed "ACPI: PCI Interrupt Routing Table [%s._PRT]" once when loading it, which was fine. Now we print it every time we look at a _PRT, which is too much because it isn't really adding any information.

Quoted 4 lines

We also print "ACPI Exception: AE_NOT_FOUND, Evaluating _PRT [AE_NOT_FOUND] (20121018/pci_irq-259)" if we find ACPI nodes without _PRTs, which we shouldn't do, because that's a common and normal situation.

Sure. Can you have separated patch to do that ?

Or want me to resend the patch.

Thanks

Yinghai

#22 lore raw

Re: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Quoted 67 lines · Yinghai Lu
Quoted 44 lines · Bjorn Helgaas
Quoted 43 lines · Yinghai Lu
Quoted 41 lines · Rafael J. Wysocki
Quoted 24 lines · Yinghai Lu

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

Quoted 7 lines

So here we try to remove _PRT caching completely.

-v2: check !handle early.

Quoted 6 lines
---
 drivers/acpi/pci_irq.c      |   95 +++++++++++++++++---------------------------
 drivers/acpi/pci_root.c     |   18 --------
 drivers/pci/pci-acpi.c      |   24 -----------
 include/acpi/acpi_drivers.h |    5 --
 4 files changed, 38 insertions(+), 104 deletions(-)
Quoted 7 lines
Quoted 3 lines

Bjorn,

Can you put this one into pci/next?

I'm not sure what this patch is based on or what the best way to merge it is. It doesn't apply cleanly to my next or pci/yinghai-root-bus-hotplug branches.

My fault, that is based on pci/next + pm/linux-next

linux-next removed
acpi_power_resource_(un)register_device ...

Quoted 9 lines

I did apply it manually on top of pci/yinghai-root-bus-hotplug to try it out, but we need to tweak the messages a little bit.

Previously we printed "ACPI: PCI Interrupt Routing Table [%s._PRT]" once when loading it, which was fine. Now we print it every time we look at a _PRT, which is too much because it isn't really adding any information.

Quoted 8 lines
Quoted 4 lines

We also print "ACPI Exception: AE_NOT_FOUND, Evaluating _PRT [AE_NOT_FOUND] (20121018/pci_irq-259)" if we find ACPI nodes without _PRTs, which we shouldn't do, because that's a common and normal situation.

Sure. Can you have separated patch to do that ?

Or want me to resend the patch.

Please check attached updated version that remove print out ...

and it could be applied cleanly on top of pci/yinghai-root-bus-hotplug

Thanks

Yinghai

From: Yinghai Lu <[email protected]>
Subject: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

So here we try to remove _PRT caching completely.

-v2: check !handle early.
-v3: remove not needed print out according to Bjorn.

---
 drivers/acpi/pci_irq.c      |  102 ++++++++++++++------------------------------
 drivers/acpi/pci_root.c     |   18 -------
 drivers/pci/pci-acpi.c      |   24 ----------
 include/acpi/acpi_drivers.h |    5 --
 4 files changed, 34 insertions(+), 115 deletions(-)
drivers/acpi/pci_irq.c +34 -68
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -53,9 +53,6 @@ struct acpi_prt_entry {
 	u32			index;		/* GSI, or link _CRS index */
 };
 
-static LIST_HEAD(acpi_prt_list);
-static DEFINE_SPINLOCK(acpi_prt_lock);
-
 static inline char pin_name(int pin)
 {
 	return 'A' + pin - 1;
@@ -65,28 +62,6 @@ static inline char pin_name(int pin)
                          PCI IRQ Routing Table (PRT) Support
    -------------------------------------------------------------------------- */
 
-static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
-							  int pin)
-{
-	struct acpi_prt_entry *entry;
-	int segment = pci_domain_nr(dev->bus);
-	int bus = dev->bus->number;
-	int device = PCI_SLOT(dev->devfn);
-
-	spin_lock(&acpi_prt_lock);
-	list_for_each_entry(entry, &acpi_prt_list, list) {
-		if ((segment == entry->id.segment)
-		    && (bus == entry->id.bus)
-		    && (device == entry->id.device)
-		    && (pin == entry->pin)) {
-			spin_unlock(&acpi_prt_lock);
-			return entry;
-		}
-	}
-	spin_unlock(&acpi_prt_lock);
-	return NULL;
-}
-
 /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
 static const struct dmi_system_id medion_md9580[] = {
 	{
@@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_pr
 	}
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
-				  struct acpi_pci_routing_table *prt)
+static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
+				  int pin, struct acpi_pci_routing_table *prt,
+				  struct acpi_prt_entry **entry_ptr)
 {
+	int segment = pci_domain_nr(dev->bus);
+	int bus = dev->bus->number;
+	int device = PCI_SLOT(dev->devfn);
 	struct acpi_prt_entry *entry;
 
+	if (((prt->address >> 16) & 0xffff) != device ||
+	    prt->pin + 1 != pin)
+		return -ENODEV;
+
 	entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
@@ -237,43 +220,37 @@ static int acpi_pci_irq_add_entry(acpi_h
 			      entry->id.device, pin_name(entry->pin),
 			      prt->source, entry->index));
 
-	spin_lock(&acpi_prt_lock);
-	list_add_tail(&entry->list, &acpi_prt_list);
-	spin_unlock(&acpi_prt_lock);
+	*entry_ptr = entry;
 
 	return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
+static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
+			  int pin, struct acpi_prt_entry **entry_ptr)
 {
 	acpi_status status;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_pci_routing_table *entry;
+	acpi_handle handle = NULL;
 
-	/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
-	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
-	       (char *) buffer.pointer);
-
-	kfree(buffer.pointer);
+	if (dev->bus->bridge)
+		handle = ACPI_HANDLE(dev->bus->bridge);
 
-	buffer.length = ACPI_ALLOCATE_BUFFER;
-	buffer.pointer = NULL;
+	if (!handle)
+		return -ENODEV;
 
+	/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
 	status = acpi_get_irq_routing_table(handle, &buffer);
 	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]",
-				acpi_format_exception(status)));
 		kfree(buffer.pointer);
 		return -ENODEV;
 	}
 
 	entry = buffer.pointer;
 	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, segment, bus, entry);
+		if (!acpi_pci_irq_check_entry(handle, dev, pin,
+						 entry, entry_ptr))
+			break;
 		entry = (struct acpi_pci_routing_table *)
 		    ((unsigned long)entry + entry->length);
 	}
@@ -282,23 +259,6 @@ int acpi_pci_irq_add_prt(acpi_handle han
 	return 0;
 }
 
-void acpi_pci_irq_del_prt(int segment, int bus)
-{
-	struct acpi_prt_entry *entry, *tmp;
-
-	printk(KERN_DEBUG
-	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-	       segment, bus);
-	spin_lock(&acpi_prt_lock);
-	list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-		if (segment == entry->id.segment && bus == entry->id.bus) {
-			list_del(&entry->list);
-			kfree(entry);
-		}
-	}
-	spin_unlock(&acpi_prt_lock);
-}
-
 /* --------------------------------------------------------------------------
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
@@ -359,12 +319,13 @@ static int acpi_reroute_boot_interrupt(s
 
 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 {
-	struct acpi_prt_entry *entry;
+	struct acpi_prt_entry *entry = NULL;
 	struct pci_dev *bridge;
 	u8 bridge_pin, orig_pin = pin;
+	int ret;
 
-	entry = acpi_pci_irq_find_prt_entry(dev, pin);
-	if (entry) {
+	ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
+	if (!ret && entry) {
 #ifdef CONFIG_X86_IO_APIC
 		acpi_reroute_boot_interrupt(dev, entry);
 #endif /* CONFIG_X86_IO_APIC */
@@ -373,7 +334,7 @@ static struct acpi_prt_entry *acpi_pci_i
 		return entry;
 	}
 
-	/* 
+	/*
 	 * Attempt to derive an IRQ for this device from a parent bridge's
 	 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
 	 */
@@ -393,8 +354,8 @@ static struct acpi_prt_entry *acpi_pci_i
 			pin = bridge_pin;
 		}
 
-		entry = acpi_pci_irq_find_prt_entry(bridge, pin);
-		if (entry) {
+		ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
+		if (!ret && entry) {
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 					 "Derived GSI for %s INT %c from %s\n",
 					 pci_name(dev), pin_name(orig_pin),
@@ -470,6 +431,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 			dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
 				 pin_name(pin));
 		}
+
 		return 0;
 	}
 
@@ -477,6 +439,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 	if (rc < 0) {
 		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
 			 pin_name(pin));
+		kfree(entry);
 		return rc;
 	}
 	dev->irq = rc;
@@ -491,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *
 		(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 		(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+	kfree(entry);
 	return 0;
 }
 
@@ -513,6 +477,8 @@ void acpi_pci_irq_disable(struct pci_dev
 	else
 		gsi = entry->index;
 
+	kfree(entry);
+
 	/*
 	 * TBD: It might be worth clearing dev->irq by magic constant
 	 * (e.g. PCI_UNDEFINED_IRQ).
drivers/acpi/pci_root.c +0 -18
Index: linux-2.6/drivers/acpi/pci_root.c
===================================================================
@@ -434,7 +434,6 @@ static int acpi_pci_root_add(struct acpi
 	acpi_status status;
 	int result;
 	struct acpi_pci_root *root;
-	acpi_handle handle;
 	struct acpi_pci_driver *driver;
 	u32 flags, base_flags;
 	bool is_osc_granted = false;
@@ -489,16 +488,6 @@ static int acpi_pci_root_add(struct acpi
 	       acpi_device_name(device), acpi_device_bid(device),
 	       root->segment, &root->secondary);
 
-	/*
-	 * PCI Routing Table
-	 * -----------------
-	 * Evaluate and parse _PRT, if exists.
-	 */
-	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_SUCCESS(status))
-		result = acpi_pci_irq_add_prt(device->handle, root->segment,
-					      root->secondary.start);
-
 	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
 	/*
@@ -623,7 +612,6 @@ out_del_root:
 	list_del(&root->node);
 	mutex_unlock(&acpi_pci_root_lock);
 
-	acpi_pci_irq_del_prt(root->segment, root->secondary.start);
 end:
 	kfree(root);
 	return result;
@@ -631,8 +619,6 @@ end:
 
 static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
-	acpi_status status;
-	acpi_handle handle;
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
@@ -647,10 +633,6 @@ static int acpi_pci_root_remove(struct a
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
-	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_SUCCESS(status))
-		acpi_pci_irq_del_prt(root->segment, root->secondary.start);
-
 	pci_remove_root_bus(root->bus);
 
 	mutex_lock(&acpi_pci_root_lock);
drivers/pci/pci-acpi.c +0 -24
Index: linux-2.6/drivers/pci/pci-acpi.c
===================================================================
@@ -325,25 +325,6 @@ static void pci_acpi_setup(struct device
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
-	acpi_status status;
-	acpi_handle dummy;
-
-	/*
-	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
-	 * _PRT objects within the scope of non-bridge devices.  Note that
-	 * _PRTs within the scope of a PCI bridge assume the bridge's
-	 * subordinate bus number.
-	 *
-	 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
-	 */
-	status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy);
-	if (ACPI_SUCCESS(status)) {
-		unsigned char bus;
-
-		bus = pci_dev->subordinate ?
-			pci_dev->subordinate->number : pci_dev->bus->number;
-		acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
-	}
 
 	acpi_power_resource_register_device(dev, handle);
 	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
@@ -359,7 +340,6 @@ static void pci_acpi_setup(struct device
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-	struct pci_dev *pci_dev = to_pci_dev(dev);
 	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
 
@@ -369,10 +349,6 @@ static void pci_acpi_cleanup(struct devi
 		pci_acpi_remove_pm_notifier(adev);
 	}
 	acpi_power_resource_unregister_device(dev, handle);
-
-	if (pci_dev->subordinate)
-		acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus),
-				     pci_dev->subordinate->number);
 }
 
 static struct acpi_bus_type acpi_pci_bus = {
include/acpi/acpi_drivers.h +0 -5
Index: linux-2.6/include/acpi/acpi_drivers.h
===================================================================
@@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_hand
 			       int *polarity, char **name);
 int acpi_pci_link_free_irq(acpi_handle handle);
 
-/* ACPI PCI Interrupt Routing (pci_irq.c) */
-
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
-void acpi_pci_irq_del_prt(int segment, int bus);
-
 /* ACPI PCI Device Binding (pci_bind.c) */
 
 struct pci_bus;
maintainer
#23 lore raw

Re: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Quoted 73 lines · Yinghai Lu
Quoted 72 lines · Yinghai Lu
Quoted 44 lines · Bjorn Helgaas
Quoted 43 lines · Yinghai Lu
Quoted 41 lines · Rafael J. Wysocki
Quoted 24 lines · Yinghai Lu

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

Quoted 7 lines

So here we try to remove _PRT caching completely.

-v2: check !handle early.

Quoted 6 lines
---
 drivers/acpi/pci_irq.c      |   95 +++++++++++++++++---------------------------
 drivers/acpi/pci_root.c     |   18 --------
 drivers/pci/pci-acpi.c      |   24 -----------
 include/acpi/acpi_drivers.h |    5 --
 4 files changed, 38 insertions(+), 104 deletions(-)
Quoted 7 lines
Quoted 3 lines

Bjorn,

Can you put this one into pci/next?

I'm not sure what this patch is based on or what the best way to merge it is. It doesn't apply cleanly to my next or pci/yinghai-root-bus-hotplug branches.

My fault, that is based on pci/next + pm/linux-next

linux-next removed
acpi_power_resource_(un)register_device ...

Quoted 13 lines

I did apply it manually on top of pci/yinghai-root-bus-hotplug to try it out, but we need to tweak the messages a little bit.

Previously we printed "ACPI: PCI Interrupt Routing Table [%s._PRT]" once when loading it, which was fine. Now we print it every time we look at a _PRT, which is too much because it isn't really adding any information.

We also print "ACPI Exception: AE_NOT_FOUND, Evaluating _PRT [AE_NOT_FOUND] (20121018/pci_irq-259)" if we find ACPI nodes without _PRTs, which we shouldn't do, because that's a common and normal situation.

Quoted 7 lines
Quoted 3 lines

Sure. Can you have separated patch to do that ?

Or want me to resend the patch.

Please check attached updated version that remove print out ...

and it could be applied cleanly on top of pci/yinghai-root-bus-hotplug

Thanks, I applied this to pci/yinghai-root-bus-hotplug and merged it into my next branch.

Bjorn

#24 lore raw

Re: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

In reply to Yinghai Lu
Quoted 24 lines · Yinghai Lu

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

Quoted 5 lines

So here we try to remove _PRT caching completely.

-v2: check !handle early.

Reported-and-tested-by Peter Hurley <[email protected]>

Actually true now :)

Reported-and-tested-by Peter Hurley <[email protected]>

Regards and thanks again,
Peter Hurley

PS - I just happened to see this version on the list. Would you please cc me on any future versions?

#25 lore raw

Re: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Quoted 27 lines · Peter Hurley
Quoted 26 lines · Yinghai Lu

Peter Hurley found "irq 18 nobody cared" with pci-next, and dmesg has

[    8.983246] pci 0000:00:1e.0: can't derive routing for PCI INT A
[    8.983600] snd_ctxfi 0000:09:02.0: PCI INT A: no GSI - using ISA IRQ 5

bisect to
| commit 4f535093cf8f6da8cfda7c36c2c1ecd2e9586ee4
| PCI: Put pci_dev in device tree as early as possible

It turns out we need to call acpi_pci_irq_add_prt() after the pci bridges are scanned.

Bjorn said:
The bus number binding means acpi_pci_irq_add_prt() has to happen after enumerating everything below a bridge, and it will prevent us from doing any bus number reassignment for hotplug.

I think we should remove the bus numbers from the cached _PRT (or maybe even remove the _PRT caching completely). When we enable a PCI device's IRQ, we should search up the PCI device tree looking for a _PRT associated with each node, and applying normal PCI bridge swizzling when we don't find a _PRT. I think this can be done without using PCI bus numbers at all.

So here we try to remove _PRT caching completely.

Quoted 7 lines
Quoted 3 lines

-v2: check !handle early.

Reported-and-tested-by Peter Hurley <[email protected]>

Actually true now :)

Reported-and-tested-by Peter Hurley <[email protected]>

Thanks.

Quoted 2 lines

PS - I just happened to see this version on the list. Would you please cc me on any future versions?

oh, my fault. I take it for granted that "git send-email" will pick that email from
patch just like Cc.

Yinghai

#26 lore raw

Re: [PATCH] ACPI, PCI: Get PRT entry during acpi_pci_enable_irq()

Quoted 4 lines · Yinghai Lu
Quoted 2 lines · Peter Hurley
Reported-and-tested-by Peter Hurley <[email protected]>
Quoted 8 lines

Thanks.

Quoted 2 lines

PS - I just happened to see this version on the list. Would you please cc me on any future versions?

oh, my fault. I take it for granted that "git send-email" will pick that email from
patch just like Cc.

No problem. Actually, I'm sorry it took this long for me to test. I was stuck in an epic bisect that I eventually abandoned at the 41st test with it still in merge bases.