162306a36Sopenharmony_ci=============================================== 262306a36Sopenharmony_ciThe irq_domain interrupt number mapping library 362306a36Sopenharmony_ci=============================================== 462306a36Sopenharmony_ci 562306a36Sopenharmony_ciThe current design of the Linux kernel uses a single large number 662306a36Sopenharmony_cispace where each separate IRQ source is assigned a different number. 762306a36Sopenharmony_ciThis is simple when there is only one interrupt controller, but in 862306a36Sopenharmony_cisystems with multiple interrupt controllers the kernel must ensure 962306a36Sopenharmony_cithat each one gets assigned non-overlapping allocations of Linux 1062306a36Sopenharmony_ciIRQ numbers. 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciThe number of interrupt controllers registered as unique irqchips 1362306a36Sopenharmony_cishow a rising tendency: for example subdrivers of different kinds 1462306a36Sopenharmony_cisuch as GPIO controllers avoid reimplementing identical callback 1562306a36Sopenharmony_cimechanisms as the IRQ core system by modelling their interrupt 1662306a36Sopenharmony_cihandlers as irqchips, i.e. in effect cascading interrupt controllers. 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciHere the interrupt number loose all kind of correspondence to 1962306a36Sopenharmony_cihardware interrupt numbers: whereas in the past, IRQ numbers could 2062306a36Sopenharmony_cibe chosen so they matched the hardware IRQ line into the root 2162306a36Sopenharmony_ciinterrupt controller (i.e. the component actually fireing the 2262306a36Sopenharmony_ciinterrupt line to the CPU) nowadays this number is just a number. 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciFor this reason we need a mechanism to separate controller-local 2562306a36Sopenharmony_ciinterrupt numbers, called hardware irq's, from Linux IRQ numbers. 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ciThe irq_alloc_desc*() and irq_free_desc*() APIs provide allocation of 2862306a36Sopenharmony_ciirq numbers, but they don't provide any support for reverse mapping of 2962306a36Sopenharmony_cithe controller-local IRQ (hwirq) number into the Linux IRQ number 3062306a36Sopenharmony_cispace. 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciThe irq_domain library adds mapping between hwirq and IRQ numbers on 3362306a36Sopenharmony_citop of the irq_alloc_desc*() API. An irq_domain to manage mapping is 3462306a36Sopenharmony_cipreferred over interrupt controller drivers open coding their own 3562306a36Sopenharmony_cireverse mapping scheme. 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciirq_domain also implements translation from an abstract irq_fwspec 3862306a36Sopenharmony_cistructure to hwirq numbers (Device Tree and ACPI GSI so far), and can 3962306a36Sopenharmony_cibe easily extended to support other IRQ topology data sources. 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciirq_domain usage 4262306a36Sopenharmony_ci================ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciAn interrupt controller driver creates and registers an irq_domain by 4562306a36Sopenharmony_cicalling one of the irq_domain_add_*() or irq_domain_create_*() functions 4662306a36Sopenharmony_ci(each mapping method has a different allocator function, more on that later). 4762306a36Sopenharmony_ciThe function will return a pointer to the irq_domain on success. The caller 4862306a36Sopenharmony_cimust provide the allocator function with an irq_domain_ops structure. 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciIn most cases, the irq_domain will begin empty without any mappings 5162306a36Sopenharmony_cibetween hwirq and IRQ numbers. Mappings are added to the irq_domain 5262306a36Sopenharmony_ciby calling irq_create_mapping() which accepts the irq_domain and a 5362306a36Sopenharmony_cihwirq number as arguments. If a mapping for the hwirq doesn't already 5462306a36Sopenharmony_ciexist then it will allocate a new Linux irq_desc, associate it with 5562306a36Sopenharmony_cithe hwirq, and call the .map() callback so the driver can perform any 5662306a36Sopenharmony_cirequired hardware setup. 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ciOnce a mapping has been established, it can be retrieved or used via a 5962306a36Sopenharmony_civariety of methods: 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci- irq_resolve_mapping() returns a pointer to the irq_desc structure 6262306a36Sopenharmony_ci for a given domain and hwirq number, and NULL if there was no 6362306a36Sopenharmony_ci mapping. 6462306a36Sopenharmony_ci- irq_find_mapping() returns a Linux IRQ number for a given domain and 6562306a36Sopenharmony_ci hwirq number, and 0 if there was no mapping 6662306a36Sopenharmony_ci- irq_linear_revmap() is now identical to irq_find_mapping(), and is 6762306a36Sopenharmony_ci deprecated 6862306a36Sopenharmony_ci- generic_handle_domain_irq() handles an interrupt described by a 6962306a36Sopenharmony_ci domain and a hwirq number 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ciNote that irq domain lookups must happen in contexts that are 7262306a36Sopenharmony_cicompatible with a RCU read-side critical section. 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ciThe irq_create_mapping() function must be called *at least once* 7562306a36Sopenharmony_cibefore any call to irq_find_mapping(), lest the descriptor will not 7662306a36Sopenharmony_cibe allocated. 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciIf the driver has the Linux IRQ number or the irq_data pointer, and 7962306a36Sopenharmony_cineeds to know the associated hwirq number (such as in the irq_chip 8062306a36Sopenharmony_cicallbacks) then it can be directly obtained from irq_data->hwirq. 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ciTypes of irq_domain mappings 8362306a36Sopenharmony_ci============================ 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ciThere are several mechanisms available for reverse mapping from hwirq 8662306a36Sopenharmony_cito Linux irq, and each mechanism uses a different allocation function. 8762306a36Sopenharmony_ciWhich reverse map type should be used depends on the use case. Each 8862306a36Sopenharmony_ciof the reverse map types are described below: 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciLinear 9162306a36Sopenharmony_ci------ 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci:: 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci irq_domain_add_linear() 9662306a36Sopenharmony_ci irq_domain_create_linear() 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciThe linear reverse map maintains a fixed size table indexed by the 9962306a36Sopenharmony_cihwirq number. When a hwirq is mapped, an irq_desc is allocated for 10062306a36Sopenharmony_cithe hwirq, and the IRQ number is stored in the table. 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ciThe Linear map is a good choice when the maximum number of hwirqs is 10362306a36Sopenharmony_cifixed and a relatively small number (~ < 256). The advantages of this 10462306a36Sopenharmony_cimap are fixed time lookup for IRQ numbers, and irq_descs are only 10562306a36Sopenharmony_ciallocated for in-use IRQs. The disadvantage is that the table must be 10662306a36Sopenharmony_cias large as the largest possible hwirq number. 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ciirq_domain_add_linear() and irq_domain_create_linear() are functionally 10962306a36Sopenharmony_ciequivalent, except for the first argument is different - the former 11062306a36Sopenharmony_ciaccepts an Open Firmware specific 'struct device_node', while the latter 11162306a36Sopenharmony_ciaccepts a more general abstraction 'struct fwnode_handle'. 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ciThe majority of drivers should use the linear map. 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciTree 11662306a36Sopenharmony_ci---- 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci:: 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci irq_domain_add_tree() 12162306a36Sopenharmony_ci irq_domain_create_tree() 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciThe irq_domain maintains a radix tree map from hwirq numbers to Linux 12462306a36Sopenharmony_ciIRQs. When an hwirq is mapped, an irq_desc is allocated and the 12562306a36Sopenharmony_cihwirq is used as the lookup key for the radix tree. 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciThe tree map is a good choice if the hwirq number can be very large 12862306a36Sopenharmony_cisince it doesn't need to allocate a table as large as the largest 12962306a36Sopenharmony_cihwirq number. The disadvantage is that hwirq to IRQ number lookup is 13062306a36Sopenharmony_cidependent on how many entries are in the table. 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ciirq_domain_add_tree() and irq_domain_create_tree() are functionally 13362306a36Sopenharmony_ciequivalent, except for the first argument is different - the former 13462306a36Sopenharmony_ciaccepts an Open Firmware specific 'struct device_node', while the latter 13562306a36Sopenharmony_ciaccepts a more general abstraction 'struct fwnode_handle'. 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ciVery few drivers should need this mapping. 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ciNo Map 14062306a36Sopenharmony_ci------ 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci:: 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci irq_domain_add_nomap() 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciThe No Map mapping is to be used when the hwirq number is 14762306a36Sopenharmony_ciprogrammable in the hardware. In this case it is best to program the 14862306a36Sopenharmony_ciLinux IRQ number into the hardware itself so that no mapping is 14962306a36Sopenharmony_cirequired. Calling irq_create_direct_mapping() will allocate a Linux 15062306a36Sopenharmony_ciIRQ number and call the .map() callback so that driver can program the 15162306a36Sopenharmony_ciLinux IRQ number into the hardware. 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ciMost drivers cannot use this mapping, and it is now gated on the 15462306a36Sopenharmony_ciCONFIG_IRQ_DOMAIN_NOMAP option. Please refrain from introducing new 15562306a36Sopenharmony_ciusers of this API. 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ciLegacy 15862306a36Sopenharmony_ci------ 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci:: 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci irq_domain_add_simple() 16362306a36Sopenharmony_ci irq_domain_add_legacy() 16462306a36Sopenharmony_ci irq_domain_create_simple() 16562306a36Sopenharmony_ci irq_domain_create_legacy() 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ciThe Legacy mapping is a special case for drivers that already have a 16862306a36Sopenharmony_cirange of irq_descs allocated for the hwirqs. It is used when the 16962306a36Sopenharmony_cidriver cannot be immediately converted to use the linear mapping. For 17062306a36Sopenharmony_ciexample, many embedded system board support files use a set of #defines 17162306a36Sopenharmony_cifor IRQ numbers that are passed to struct device registrations. In that 17262306a36Sopenharmony_cicase the Linux IRQ numbers cannot be dynamically assigned and the legacy 17362306a36Sopenharmony_cimapping should be used. 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ciAs the name implies, the \*_legacy() functions are deprecated and only 17662306a36Sopenharmony_ciexist to ease the support of ancient platforms. No new users should be 17762306a36Sopenharmony_ciadded. Same goes for the \*_simple() functions when their use results 17862306a36Sopenharmony_ciin the legacy behaviour. 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ciThe legacy map assumes a contiguous range of IRQ numbers has already 18162306a36Sopenharmony_cibeen allocated for the controller and that the IRQ number can be 18262306a36Sopenharmony_cicalculated by adding a fixed offset to the hwirq number, and 18362306a36Sopenharmony_civisa-versa. The disadvantage is that it requires the interrupt 18462306a36Sopenharmony_cicontroller to manage IRQ allocations and it requires an irq_desc to be 18562306a36Sopenharmony_ciallocated for every hwirq, even if it is unused. 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ciThe legacy map should only be used if fixed IRQ mappings must be 18862306a36Sopenharmony_cisupported. For example, ISA controllers would use the legacy map for 18962306a36Sopenharmony_cimapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ 19062306a36Sopenharmony_cinumbers. 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ciMost users of legacy mappings should use irq_domain_add_simple() or 19362306a36Sopenharmony_ciirq_domain_create_simple() which will use a legacy domain only if an IRQ range 19462306a36Sopenharmony_ciis supplied by the system and will otherwise use a linear domain mapping. 19562306a36Sopenharmony_ciThe semantics of this call are such that if an IRQ range is specified then 19662306a36Sopenharmony_cidescriptors will be allocated on-the-fly for it, and if no range is 19762306a36Sopenharmony_cispecified it will fall through to irq_domain_add_linear() or 19862306a36Sopenharmony_ciirq_domain_create_linear() which means *no* irq descriptors will be allocated. 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ciA typical use case for simple domains is where an irqchip provider 20162306a36Sopenharmony_ciis supporting both dynamic and static IRQ assignments. 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ciIn order to avoid ending up in a situation where a linear domain is 20462306a36Sopenharmony_ciused and no descriptor gets allocated it is very important to make sure 20562306a36Sopenharmony_cithat the driver using the simple domain call irq_create_mapping() 20662306a36Sopenharmony_cibefore any irq_find_mapping() since the latter will actually work 20762306a36Sopenharmony_cifor the static IRQ assignment case. 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ciirq_domain_add_simple() and irq_domain_create_simple() as well as 21062306a36Sopenharmony_ciirq_domain_add_legacy() and irq_domain_create_legacy() are functionally 21162306a36Sopenharmony_ciequivalent, except for the first argument is different - the former 21262306a36Sopenharmony_ciaccepts an Open Firmware specific 'struct device_node', while the latter 21362306a36Sopenharmony_ciaccepts a more general abstraction 'struct fwnode_handle'. 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ciHierarchy IRQ domain 21662306a36Sopenharmony_ci-------------------- 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ciOn some architectures, there may be multiple interrupt controllers 21962306a36Sopenharmony_ciinvolved in delivering an interrupt from the device to the target CPU. 22062306a36Sopenharmony_ciLet's look at a typical interrupt delivering path on x86 platforms:: 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci Device --> IOAPIC -> Interrupt remapping Controller -> Local APIC -> CPU 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ciThere are three interrupt controllers involved: 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci1) IOAPIC controller 22762306a36Sopenharmony_ci2) Interrupt remapping controller 22862306a36Sopenharmony_ci3) Local APIC controller 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ciTo support such a hardware topology and make software architecture match 23162306a36Sopenharmony_cihardware architecture, an irq_domain data structure is built for each 23262306a36Sopenharmony_ciinterrupt controller and those irq_domains are organized into hierarchy. 23362306a36Sopenharmony_ciWhen building irq_domain hierarchy, the irq_domain near to the device is 23462306a36Sopenharmony_cichild and the irq_domain near to CPU is parent. So a hierarchy structure 23562306a36Sopenharmony_cias below will be built for the example above:: 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci CPU Vector irq_domain (root irq_domain to manage CPU vectors) 23862306a36Sopenharmony_ci ^ 23962306a36Sopenharmony_ci | 24062306a36Sopenharmony_ci Interrupt Remapping irq_domain (manage irq_remapping entries) 24162306a36Sopenharmony_ci ^ 24262306a36Sopenharmony_ci | 24362306a36Sopenharmony_ci IOAPIC irq_domain (manage IOAPIC delivery entries/pins) 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ciThere are four major interfaces to use hierarchy irq_domain: 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci1) irq_domain_alloc_irqs(): allocate IRQ descriptors and interrupt 24862306a36Sopenharmony_ci controller related resources to deliver these interrupts. 24962306a36Sopenharmony_ci2) irq_domain_free_irqs(): free IRQ descriptors and interrupt controller 25062306a36Sopenharmony_ci related resources associated with these interrupts. 25162306a36Sopenharmony_ci3) irq_domain_activate_irq(): activate interrupt controller hardware to 25262306a36Sopenharmony_ci deliver the interrupt. 25362306a36Sopenharmony_ci4) irq_domain_deactivate_irq(): deactivate interrupt controller hardware 25462306a36Sopenharmony_ci to stop delivering the interrupt. 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ciFollowing changes are needed to support hierarchy irq_domain: 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci1) a new field 'parent' is added to struct irq_domain; it's used to 25962306a36Sopenharmony_ci maintain irq_domain hierarchy information. 26062306a36Sopenharmony_ci2) a new field 'parent_data' is added to struct irq_data; it's used to 26162306a36Sopenharmony_ci build hierarchy irq_data to match hierarchy irq_domains. The irq_data 26262306a36Sopenharmony_ci is used to store irq_domain pointer and hardware irq number. 26362306a36Sopenharmony_ci3) new callbacks are added to struct irq_domain_ops to support hierarchy 26462306a36Sopenharmony_ci irq_domain operations. 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ciWith support of hierarchy irq_domain and hierarchy irq_data ready, an 26762306a36Sopenharmony_ciirq_domain structure is built for each interrupt controller, and an 26862306a36Sopenharmony_ciirq_data structure is allocated for each irq_domain associated with an 26962306a36Sopenharmony_ciIRQ. Now we could go one step further to support stacked(hierarchy) 27062306a36Sopenharmony_ciirq_chip. That is, an irq_chip is associated with each irq_data along 27162306a36Sopenharmony_cithe hierarchy. A child irq_chip may implement a required action by 27262306a36Sopenharmony_ciitself or by cooperating with its parent irq_chip. 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ciWith stacked irq_chip, interrupt controller driver only needs to deal 27562306a36Sopenharmony_ciwith the hardware managed by itself and may ask for services from its 27662306a36Sopenharmony_ciparent irq_chip when needed. So we could achieve a much cleaner 27762306a36Sopenharmony_cisoftware architecture. 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ciFor an interrupt controller driver to support hierarchy irq_domain, it 28062306a36Sopenharmony_cineeds to: 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci1) Implement irq_domain_ops.alloc and irq_domain_ops.free 28362306a36Sopenharmony_ci2) Optionally implement irq_domain_ops.activate and 28462306a36Sopenharmony_ci irq_domain_ops.deactivate. 28562306a36Sopenharmony_ci3) Optionally implement an irq_chip to manage the interrupt controller 28662306a36Sopenharmony_ci hardware. 28762306a36Sopenharmony_ci4) No need to implement irq_domain_ops.map and irq_domain_ops.unmap, 28862306a36Sopenharmony_ci they are unused with hierarchy irq_domain. 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ciHierarchy irq_domain is in no way x86 specific, and is heavily used to 29162306a36Sopenharmony_cisupport other architectures, such as ARM, ARM64 etc. 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ciDebugging 29462306a36Sopenharmony_ci========= 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ciMost of the internals of the IRQ subsystem are exposed in debugfs by 29762306a36Sopenharmony_citurning CONFIG_GENERIC_IRQ_DEBUGFS on. 298