IO-SAPIC

From Linux PARISC Wiki
(Difference between revisions)
Jump to: navigation, search
m (Overview of exported iosapic functions)
m (formatting update)
Line 3: Line 3:
 
This is part of the PA-RISC [[Interrupts]] handling system.
 
This is part of the PA-RISC [[Interrupts]] handling system.
  
The following content is extracted from the file `drivers/parisc/iosapic.c`:
+
The following content is extracted from the file <tt>drivers/parisc/iosapic.c</tt>:
  
 
The I/O sapic driver manages the ''Interrupt Redirection Table'' which is
 
The I/O sapic driver manages the ''Interrupt Redirection Table'' which is
Line 44: Line 44:
 
PA-RISC platforms have two fundementally different types of firmware (see ProcessorDependentCode).
 
PA-RISC platforms have two fundementally different types of firmware (see ProcessorDependentCode).
  
For [[PCI]] devices, "''Legacy''" PDC initializes the `INTERRUPT_LINE` register
+
For [[PCI]] devices, "''Legacy''" PDC initializes the <tt>INTERRUPT_LINE</tt> register
 
and BARs similar to a traditional PC BIOS.
 
and BARs similar to a traditional PC BIOS.
 
The newer "''PAT''" firmware supports PDC calls which return tables.
 
The newer "''PAT''" firmware supports PDC calls which return tables.
Line 53: Line 53:
 
The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
 
The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
 
input line.  If the IRT is not available, this driver assumes
 
input line.  If the IRT is not available, this driver assumes
`INTERRUPT_LINE` register has been programmed by firmware. The latter
+
<tt>INTERRUPT_LINE</tt> register has been programmed by firmware. The latter
 
case also means online addition of PCI cards can '''NOT''' be supported
 
case also means online addition of PCI cards can '''NOT''' be supported
 
even if HW support is present.
 
even if HW support is present.
Line 66: Line 66:
 
will discover I/O Sapic. I/O Sapic driver learns about each device
 
will discover I/O Sapic. I/O Sapic driver learns about each device
 
when LBA driver advertises the presence of the I/O sapic by calling
 
when LBA driver advertises the presence of the I/O sapic by calling
`iosapic_register()`.
+
<tt>iosapic_register()</tt>.
  
 
== IRQ handling notes ==
 
== IRQ handling notes ==
Line 80: Line 80:
 
(caveat: code isn't finished yet - this is just the plan)
 
(caveat: code isn't finished yet - this is just the plan)
  
;`iosapic_init`:
+
;<tt>iosapic_init</tt>:
 
: initialize globals (lock, etc)
 
: initialize globals (lock, etc)
 
: try to read IRT. Presence of IRT determines if this is a PAT platform or not.
 
: try to read IRT. Presence of IRT determines if this is a PAT platform or not.
  
;`iosapic_register()`:
+
;<tt>iosapic_register()</tt>:
: create `iosapic_info` instance data structure
+
: create <tt>iosapic_info</tt> instance data structure
: allocate `vector_info` array for this iosapic
+
: allocate <tt>vector_info</tt> array for this iosapic
: initialize `vector_info` - read corresponding IRdT?
+
: initialize <tt>vector_info</tt> - read corresponding IRdT?
  
;`iosapic_xlate_pin`: (only called by fixup_irq for PAT platform)
+
;<tt>iosapic_xlate_pin</tt>: (only called by fixup_irq for PAT platform)
: `intr_pin = read cfg (INTERRUPT_PIN);`
+
: <code>intr_pin = read cfg (INTERRUPT_PIN);</code>
 
: if (device under PCI-PCI bridge)  
 
: if (device under PCI-PCI bridge)  
 
:: translate slot/pin
 
:: translate slot/pin
  
;`iosapic_fixup_irq`:
+
;<tt>iosapic_fixup_irq</tt>:
 
: if PAT platform (IRT present)
 
: if PAT platform (IRT present)
:: `intr_pin = iosapic_xlate_pin(isi,pcidev)`
+
:: <code>intr_pin = iosapic_xlate_pin(isi,pcidev)</code>
:: `intr_line = find IRT entry(isi, PCI_SLOT(pcidev), intr_pin)`
+
:: <code>intr_line = find IRT entry(isi, PCI_SLOT(pcidev), intr_pin)</code>
 
:: save IRT entry into vector_info later
 
:: save IRT entry into vector_info later
:: write cfg `INTERRUPT_LINE` (with intr_line)?
+
:: write cfg <tt>INTERRUPT_LINE</tt> (with intr_line)?
 
: else
 
: else
:: `intr_line = pcidev->irq`
+
:: <tt>intr_line = pcidev->irq</tt>
::  IRT pointer = `NULL`
+
::  IRT pointer = <tt>NULL</tt>
 
: endif
 
: endif
: locate `vector_info` (needs: `isi, intr_line`)
+
: locate <tt>vector_info</tt> (needs: <tt>isi, intr_line</tt>)
: allocate processor "irq" and get `txn_addr/data`
+
: allocate processor "irq" and get <tt>txn_addr/data</tt>
: `request_irq(processor_irq,  iosapic_interrupt, vector_info,...)`
+
: <code>request_irq(processor_irq,  iosapic_interrupt, vector_info,...)</code>
  
;`iosapic_enable_irq`:
+
;<tt>iosapic_enable_irq</tt>:
 
: clear any pending IRQ on that line
 
: clear any pending IRQ on that line
: enable IRdT - call `enable_irq(vector[line]->processor_irq)`
+
: enable IRdT - call <tt>enable_irq(vector[line]->processor_irq)</tt>
 
: write EOI in case line is already asserted.
 
: write EOI in case line is already asserted.
  
; `iosapic_disable_irq`:
+
; <tt>iosapic_disable_irq</tt>:
: disable IRdT - call `disable_irq(vector[line]->processor_irq)`
+
: disable IRdT - call <tt>disable_irq(vector[line]->processor_irq)</tt>

Revision as of 20:52, 30 May 2014

Contents

IO-SAPIC

This is part of the PA-RISC Interrupts handling system.

The following content is extracted from the file drivers/parisc/iosapic.c:

The I/O sapic driver manages the Interrupt Redirection Table which is the control logic to convert PCI line based interrupts into a Message Signaled Interrupt (aka Transaction Based Interrupt, TBI).

Acronyms

  • HPA: Hard Physical Address (aka MMIO address)
  • IRQ: Interrupt Request. Implies Line based interrupt.
  • IRT: Interrupt Routing Table (provided by PAT firmware)
  • IRdT: Interrupt Redirection Table. IRQ line to TXN ADDR/DATA table which is implemented in IO SAPIC.
  • ISR: Interrupt Service Routine. aka Interrupt handler.
  • MSI: Message Signaled Interrupt. PCI 2.2 functionality. aka Transaction Based Interrupt (or TBI).
  • PA: Precision Architecture. HP's RISC architecture.
  • RISC: Reduced Instruction Set Computer.

What's a Message Signalled Interrupt?

MSI is a write transaction which targets a processor and is similar to a processor write to memory or MMIO. MSIs can be generated by I/O devices as well as processors and require architecture to work.

PA only supports MSI. So I/O subsystems must either natively generate MSIs (e.g. GSC or HP-PB) or convert line based interrupts into MSIs (e.g. PCI and EISA). IA64 supports MSIs via a "local SAPIC" which acts on behalf of a processor.

MSI allows any I/O device to interrupt any processor. This makes load balancing of the interrupt processing possible on an SMP platform. Interrupts are also ordered with respect to DMA data. It's possible on I/O coherent systems to completely eliminate PIO reads from the interrupt path. The device and driver must be designed and implemented to guarantee all DMA has been issued (issues about atomicity here) before the MSI is issued. I/O status can then safely be read from DMA'd data by the ISR.

PA Firmware

PA-RISC platforms have two fundementally different types of firmware (see ProcessorDependentCode).

For PCI devices, "Legacy" PDC initializes the INTERRUPT_LINE register and BARs similar to a traditional PC BIOS. The newer "PAT" firmware supports PDC calls which return tables. PAT firmware only initializes PCI Console and Boot interface. With these tables, the OS can progam all other PCI devices.

One such PAT PDC call returns the "Interrupt Routing Table" (IRT). The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC input line. If the IRT is not available, this driver assumes INTERRUPT_LINE register has been programmed by firmware. The latter case also means online addition of PCI cards can NOT be supported even if HW support is present.

All platforms with PAT firmware to date (Oct 1999) use one Interrupt Routing Table for the entire platform.

Where's the iosapic?

I/O sapic is part of the "Core Electronics Complex". And on HP platforms it's integrated as part of the PCI bus adapter, LBA. So no bus walk will discover I/O Sapic. I/O Sapic driver learns about each device when LBA driver advertises the presence of the I/O sapic by calling iosapic_register().

IRQ handling notes

The IO-SAPIC can indicate to the CPU which interrupt was asserted. So, unlike the GSC-ASIC and Dino, we allocate one CPU interrupt per IO-SAPIC interrupt and call the device driver's handler directly. The IO-SAPIC driver hijacks the CPU interrupt handler so it can issue the End Of Interrupt command to the IO-SAPIC.

Overview of exported iosapic functions

(caveat: code isn't finished yet - this is just the plan)

iosapic_init
initialize globals (lock, etc)
try to read IRT. Presence of IRT determines if this is a PAT platform or not.
iosapic_register()
create iosapic_info instance data structure
allocate vector_info array for this iosapic
initialize vector_info - read corresponding IRdT?
iosapic_xlate_pin
(only called by fixup_irq for PAT platform)
intr_pin = read cfg (INTERRUPT_PIN);
if (device under PCI-PCI bridge)
translate slot/pin
iosapic_fixup_irq
if PAT platform (IRT present)
intr_pin = iosapic_xlate_pin(isi,pcidev)
intr_line = find IRT entry(isi, PCI_SLOT(pcidev), intr_pin)
save IRT entry into vector_info later
write cfg INTERRUPT_LINE (with intr_line)?
else
intr_line = pcidev->irq
IRT pointer = NULL
endif
locate vector_info (needs: isi, intr_line)
allocate processor "irq" and get txn_addr/data
request_irq(processor_irq, iosapic_interrupt, vector_info,...)
iosapic_enable_irq
clear any pending IRQ on that line
enable IRdT - call enable_irq(vector[line]->processor_irq)
write EOI in case line is already asserted.
iosapic_disable_irq
disable IRdT - call disable_irq(vector[line]->processor_irq)
Personal tools