1. 10 Apr, 2022 9 commits
    • Maciej W. Rozycki's avatar
      x86/PCI: Add $IRT PIRQ routing table support · b584db0c
      Maciej W. Rozycki authored
      Handle the $IRT PCI IRQ Routing Table format used by AMI for its BCP 
      (BIOS Configuration Program) external tool meant for tweaking BIOS 
      structures without the need to rebuild it from sources[1].
      
      The $IRT format has been invented by AMI before Microsoft has come up 
      with its $PIR format and a $IRT table is therefore there in some systems 
      that lack a $PIR table, such as the DataExpert EXP8449 mainboard based 
      on the ALi FinALi 486 chipset (M1489/M1487), which predates DMI 2.0 and 
      cannot therefore be easily identified at run time.
      
      Unlike with the $PIR format there is no alignment guarantee as to the 
      placement of the $IRT table, so scan the whole BIOS area bytewise.
      
      Credit to Michal Necasek for helping me chase documentation for the 
      format.
      
      References:
      
      [1] "What is BCP? - AMI", <https://www.ami.com/what-is-bcp/>
      Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> # crosvm
      Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203302228410.9038@angie.orcam.me.uk
      b584db0c
    • Maciej W. Rozycki's avatar
      x86/PCI: Handle PIRQ routing tables with no router device given · ac7cd5e1
      Maciej W. Rozycki authored
      PIRQ routing tables provided by the PCI BIOS usually specify the PCI 
      vendor:device ID as well as the bus address of the device implementing 
      the PIRQ router, e.g.:
      
      PCI: Interrupt Routing Table found at 0xc00fde10
      [...]
      PCI: Attempting to find IRQ router for [8086:7000]
      pci 0000:00:07.0: PIIX/ICH IRQ router [8086:7000]
      
      however in some cases they do not, in which case we fail to match the 
      router handler, e.g.:
      
      PCI: Interrupt Routing Table found at 0xc00fdae0
      [...]
      PCI: Attempting to find IRQ router for [0000:0000]
      PCI: Interrupt router not found at 00:00
      
      This is because we always match the vendor:device ID and the bus address 
      literally, even if they are all zeros.
      
      Handle this case then and iterate over all PCI devices until we find a 
      matching router handler if the vendor ID given by the routing table is 
      the invalid value of zero:
      
      PCI: Attempting to find IRQ router for [0000:0000]
      PCI: Trying IRQ router for [1039:0496]
      pci 0000:00:05.0: SiS85C497 IRQ router [1039:0496]
      Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Tested-by: default avatarNikolai Zhubr <zhubr.2@gmail.com>
      Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203302018570.9038@angie.orcam.me.uk
      ac7cd5e1
    • Maciej W. Rozycki's avatar
      x86/PCI: Add PIRQ routing table range checks · 5d64089a
      Maciej W. Rozycki authored
      Verify that the PCI IRQ Routing Table header as well as individual slot 
      entries are all wholly contained within the BIOS memory area.  Do not 
      even call the checksum calculator if the header would overrun the area 
      and then bail out early if any slot would.
      Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203301735510.22465@angie.orcam.me.uk
      5d64089a
    • Maciej W. Rozycki's avatar
      x86/PCI: Add support for the SiS85C497 PIRQ router · fe62bc23
      Maciej W. Rozycki authored
      The SiS 85C496/497 486 Green PC VESA/ISA/PCI Chipset has support for PCI 
      steering and the ELCR register implemented.  These features are handled 
      by the SiS85C497 AT Bus Controller & Megacell (ATM) ISA bridge, however 
      the device is wired as a peer bridge directly to the host bus and has 
      its PCI configuration registers decoded at addresses 0x80-0xff by the 
      accompanying SiS85C496 PCI & CPU Memory Controller (PCM) host bridge[1].  
      Therefore we need to match on the host bridge's vendor and device ID.
      
      Like with the SiS85C503 PIRQ router handle link value ranges of 1-4 and 
      0xc0-0xc3, corresponding respectively to PIRQ line numbers counted from 
      1 and link register PCI configuration space addresses.
      
      References:
      
      [1]  "486 Green PC VESA/ISA/PCI Chipset, SiS 85C496/497", Rev 3.0,
           Silicon Integrated Systems Corp., July 1995, Part IV, Section 3. 
           "PCI Configuration Space Registers (00h ~ FFh)", p. 114
      Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Tested-by: default avatarNikolai Zhubr <zhubr.2@gmail.com>
      Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203301610490.22465@angie.orcam.me.uk
      fe62bc23
    • Maciej W. Rozycki's avatar
      x86/PCI: Disambiguate SiS85C503 PIRQ router code entities · 5a0e5fa9
      Maciej W. Rozycki authored
      In preparation to adding support for the SiS85C497 PIRQ router add `503' 
      to the names of SiS85C503 PIRQ router code entities so that they clearly 
      indicate which device they refer to.
      
      Also restructure `sis_router_probe' such that new device IDs will be 
      just new switch cases.
      
      No functional change.
      Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203301610000.22465@angie.orcam.me.uk
      5a0e5fa9
    • Maciej W. Rozycki's avatar
      x86/PCI: Handle IRQ swizzling with PIRQ routers · d88a8b1c
      Maciej W. Rozycki authored
      Similarly to MP-tables PIRQ routing tables may not list devices behind 
      PCI-to-PCI bridges, leading to interrupt routing failures, e.g.:
      
      pci 0000:00:07.0: PIIX/ICH IRQ router [8086:7000]
      pci 0000:02:00.0: ignoring bogus IRQ 255
      pci 0000:02:01.0: ignoring bogus IRQ 255
      pci 0000:02:02.0: ignoring bogus IRQ 255
      pci 0000:04:00.0: ignoring bogus IRQ 255
      pci 0000:04:00.3: ignoring bogus IRQ 255
      pci 0000:00:11.0: PCI INT A -> PIRQ 63, mask deb8, excl 0c20
      pci 0000:00:11.0: PCI INT A -> newirq 0
      PCI: setting IRQ 11 as level-triggered
      pci 0000:00:11.0: found PCI INT A -> IRQ 11
      pci 0000:00:11.0: sharing IRQ 11 with 0000:00:07.2
      pci 0000:02:00.0: PCI INT A not found in routing table
      pci 0000:02:01.0: PCI INT A not found in routing table
      pci 0000:02:02.0: PCI INT A not found in routing table
      pci 0000:04:00.0: PCI INT A not found in routing table
      pci 0000:04:00.3: PCI INT D not found in routing table
      pci 0000:06:05.0: PCI INT A not found in routing table
      pci 0000:06:08.0: PCI INT A not found in routing table
      pci 0000:06:08.1: PCI INT B not found in routing table
      pci 0000:06:08.2: PCI INT C not found in routing table
      
      and consequently non-working devices.  Since PCI-to-PCI bridges have a 
      standardised way of routing interrupts by the means of swizzling do it 
      for configurations that use a PIRQ router as well, like with APIC-based 
      setups, and use the determined corresponding topmost bridge's interrupt 
      pin assignment to route a given device's interrupt:
      
      pci 0000:00:07.0: PIIX/ICH IRQ router [8086:7000]
      pci 0000:02:00.0: ignoring bogus IRQ 255
      pci 0000:02:01.0: ignoring bogus IRQ 255
      pci 0000:02:02.0: ignoring bogus IRQ 255
      pci 0000:04:00.0: ignoring bogus IRQ 255
      pci 0000:04:00.3: ignoring bogus IRQ 255
      pci 0000:00:11.0: PCI INT A -> PIRQ 63, mask deb8, excl 0c20
      pci 0000:00:11.0: PCI INT A -> newirq 0
      PCI: setting IRQ 11 as level-triggered
      pci 0000:00:11.0: found PCI INT A -> IRQ 11
      pci 0000:00:11.0: sharing IRQ 11 with 0000:00:07.2
      pci 0000:02:00.0: using bridge 0000:00:11.0 INT A to get INT A
      pci 0000:00:11.0: sharing IRQ 11 with 0000:02:00.0
      pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A
      pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A
      pci 0000:04:00.0: using bridge 0000:00:11.0 INT B to get INT A
      pci 0000:04:00.3: using bridge 0000:00:11.0 INT A to get INT D
      pci 0000:00:11.0: sharing IRQ 11 with 0000:04:00.3
      pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A
      pci 0000:06:08.0: using bridge 0000:00:11.0 INT C to get INT A
      pci 0000:06:08.1: using bridge 0000:00:11.0 INT D to get INT B
      pci 0000:06:08.2: using bridge 0000:00:11.0 INT A to get INT C
      pci 0000:00:11.0: sharing IRQ 11 with 0000:06:08.2
      pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A
      pci 0000:02:01.0: PCI INT A -> PIRQ 60, mask deb8, excl 0c20
      pci 0000:02:01.0: PCI INT A -> newirq 0
      PCI: setting IRQ 10 as level-triggered
      pci 0000:02:01.0: found PCI INT A -> IRQ 10
      pci 0000:02:01.0: sharing IRQ 10 with 0000:00:14.0
      pci 0000:02:00.0: using bridge 0000:00:11.0 INT A to get INT A
      pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A
      pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A
      pci 0000:04:00.0: using bridge 0000:00:11.0 INT B to get INT A
      pci 0000:02:01.0: sharing IRQ 10 with 0000:04:00.0
      pci 0000:04:00.3: using bridge 0000:00:11.0 INT A to get INT D
      pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A
      pci 0000:06:08.0: using bridge 0000:00:11.0 INT C to get INT A
      pci 0000:06:08.1: using bridge 0000:00:11.0 INT D to get INT B
      pci 0000:06:08.2: using bridge 0000:00:11.0 INT A to get INT C
      pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A
      pci 0000:02:02.0: PCI INT A -> PIRQ 61, mask deb8, excl 0c20
      pci 0000:02:02.0: PCI INT A -> newirq 0
      PCI: setting IRQ 5 as level-triggered
      pci 0000:02:02.0: found PCI INT A -> IRQ 5
      pci 0000:02:02.0: sharing IRQ 5 with 0000:00:13.0
      pci 0000:02:00.0: using bridge 0000:00:11.0 INT A to get INT A
      pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A
      pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A
      pci 0000:04:00.0: using bridge 0000:00:11.0 INT B to get INT A
      pci 0000:04:00.3: using bridge 0000:00:11.0 INT A to get INT D
      pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A
      pci 0000:06:08.0: using bridge 0000:00:11.0 INT C to get INT A
      pci 0000:02:02.0: sharing IRQ 5 with 0000:06:08.0
      pci 0000:06:08.1: using bridge 0000:00:11.0 INT D to get INT B
      pci 0000:06:08.2: using bridge 0000:00:11.0 INT A to get INT C
      pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A
      pci 0000:06:05.0: PCI INT A -> PIRQ 62, mask deb8, excl 0c20
      pci 0000:06:05.0: PCI INT A -> newirq 0
      pci 0000:06:05.0: found PCI INT A -> IRQ 5
      pci 0000:06:05.0: sharing IRQ 5 with 0000:00:12.0
      pci 0000:02:00.0: using bridge 0000:00:11.0 INT A to get INT A
      pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A
      pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A
      pci 0000:04:00.0: using bridge 0000:00:11.0 INT B to get INT A
      pci 0000:04:00.3: using bridge 0000:00:11.0 INT A to get INT D
      pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A
      pci 0000:06:08.0: using bridge 0000:00:11.0 INT C to get INT A
      pci 0000:06:08.1: using bridge 0000:00:11.0 INT D to get INT B
      pci 0000:06:05.0: sharing IRQ 5 with 0000:06:08.1
      pci 0000:06:08.2: using bridge 0000:00:11.0 INT A to get INT C
      
      Adjust log messages accordingly.
      Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203301538440.22465@angie.orcam.me.uk
      d88a8b1c
    • Maciej W. Rozycki's avatar
      x86/PCI: Also match function number in $PIR table · 31324502
      Maciej W. Rozycki authored
      Contrary to the PCI BIOS specification[1] some systems include the PCI 
      function number for onboard devices in their $PIR table.  Consequently 
      the wrong entry can be matched leading to interrupt routing failures.
      
      For example the Tyan Tomcat IV S1564D board has:
      
      00:07.1 slot=00
       0:00/deb8
       1:00/deb8
       2:00/deb8
       3:00/deb8
      
      00:07.2 slot=00
       0:00/deb8
       1:00/deb8
       2:00/deb8
       3:63/deb8
      
      for its IDE interface and USB controller functions of the 82371SB PIIX3 
      southbridge.  Consequently the first entry matches causing the inability 
      to route the USB interrupt in the `noapic' mode, in which case we need 
      to rely on the interrupt line set by the BIOS:
      
      uhci_hcd 0000:00:07.2: runtime IRQ mapping not provided by arch
      uhci_hcd 0000:00:07.2: PCI INT D not routed
      uhci_hcd 0000:00:07.2: enabling bus mastering
      uhci_hcd 0000:00:07.2: UHCI Host Controller
      uhci_hcd 0000:00:07.2: new USB bus registered, assigned bus number 1
      uhci_hcd 0000:00:07.2: irq 11, io base 0x00006000
      
      Try to match the PCI device and function combined then and if that fails 
      move on to PCI device matching only.  Compliant systems will only have a 
      single $PIR table entry per PCI device, so this update does not change 
      the semantics with them, while systems that have several entries for 
      individual functions of a single PCI device each will match the correct 
      entry:
      
      uhci_hcd 0000:00:07.2: runtime IRQ mapping not provided by arch
      uhci_hcd 0000:00:07.2: PCI INT D -> PIRQ 63, mask deb8, excl 0c20
      uhci_hcd 0000:00:07.2: PCI INT D -> newirq 11
      uhci_hcd 0000:00:07.2: found PCI INT D -> IRQ 11
      uhci_hcd 0000:00:07.2: sharing IRQ 11 with 0000:00:11.0
      uhci_hcd 0000:00:07.2: enabling bus mastering
      uhci_hcd 0000:00:07.2: UHCI Host Controller
      uhci_hcd 0000:00:07.2: new USB bus registered, assigned bus number 1
      uhci_hcd 0000:00:07.2: irq 11, io base 0x00006000
      
      [1] "PCI BIOS Specification", Revision 2.1, PCI Special Interest Group,
          August 26, 1994, Table 4-1 "Layout of IRQ routing table entry.", p.
          12
      Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203301536020.22465@angie.orcam.me.uk
      31324502
    • Maciej W. Rozycki's avatar
      x86/PCI: Include function number in $PIR table dump · dc0e6408
      Maciej W. Rozycki authored
      Contrary to the PCI BIOS specification[1] some systems include the PCI 
      function number for motherboard devices in their $PIR table, e.g. this 
      is what the Tyan Tomcat IV S1564D board reports:
      
      00:14 slot=01
       0:60/deb8
       1:61/deb8
       2:62/deb8
       3:63/deb8
      
      00:13 slot=02
       0:61/deb8
       1:62/deb8
       2:63/deb8
       3:60/deb8
      
      00:12 slot=03
       0:62/deb8
       1:63/deb8
       2:60/deb8
       3:61/deb8
      
      00:11 slot=04
       0:63/deb8
       1:60/deb8
       2:61/deb8
       3:62/deb8
      
      00:07 slot=00
       0:00/deb8
       1:00/deb8
       2:00/deb8
       3:00/deb8
      
      00:07 slot=00
       0:00/deb8
       1:00/deb8
       2:00/deb8
       3:63/deb8
      
      Print the function number then in the debug $PIR table dump:
      
      00:14.0 slot=01
       0:60/deb8
       1:61/deb8
       2:62/deb8
       3:63/deb8
      
      00:13.0 slot=02
       0:61/deb8
       1:62/deb8
       2:63/deb8
       3:60/deb8
      
      00:12.0 slot=03
       0:62/deb8
       1:63/deb8
       2:60/deb8
       3:61/deb8
      
      00:11.0 slot=04
       0:63/deb8
       1:60/deb8
       2:61/deb8
       3:62/deb8
      
      00:07.1 slot=00
       0:00/deb8
       1:00/deb8
       2:00/deb8
       3:00/deb8
      
      00:07.2 slot=00
       0:00/deb8
       1:00/deb8
       2:00/deb8
       3:63/deb8
      
      References:
      
      [1] "PCI BIOS Specification", Revision 2.1, PCI Special Interest Group, 
          August 26, 1994, Table 4-1 "Layout of IRQ routing table entry.", p. 
          12
      Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203301534440.22465@angie.orcam.me.uk
      dc0e6408
    • Maciej W. Rozycki's avatar
      x86/PCI: Show the physical address of the $PIR table · 613fa6e2
      Maciej W. Rozycki authored
      It makes no sense to hide the address of the $PIR table in a debug dump:
      
      PCI: Interrupt Routing Table found at 0x(ptrval)
      
      let alone print its virtual address, given that this is a BIOS entity at 
      a fixed location in the system's memory map.  Show the physical address 
      instead then, e.g.:
      
      PCI: Interrupt Routing Table found at 0xfde10
      Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203301532330.22465@angie.orcam.me.uk
      613fa6e2
  2. 03 Apr, 2022 8 commits
  3. 02 Apr, 2022 23 commits