irq_domain 中斷號對映庫

Linux 核心的當前設計使用一個大的編號空間,其中每個單獨的 IRQ 源都被分配一個唯一的編號。當只有一箇中斷控制器時,這很簡單。但在具有多箇中斷控制器的系統中,核心必須確保為每個中斷控制器分配不重疊的 Linux IRQ 編號。

註冊為唯一 irqchip 的中斷控制器數量呈上升趨勢。例如,諸如 GPIO 控制器之類的不同型別的子驅動程式透過將其中斷處理程式建模為 irqchip 來避免重新實現與 IRQ 核心系統相同的回撥機制。即,實際上是級聯中斷控制器。

因此,在過去,IRQ 編號可以選擇為與硬體 IRQ 線匹配到根中斷控制器(即,實際向 CPU 發出中斷線的元件)。如今,這個數字只是一個數字,並且該數字失去了與硬體中斷號的任何對應關係。

因此,我們需要一種機制來分離控制器本地中斷號(稱為硬體 IRQ)與 Linux IRQ 編號。

irq_alloc_desc*() 和 irq_free_desc*() API 提供 IRQ 編號的分配,但它們不提供對控制器本地 IRQ (hwirq) 編號到 Linux IRQ 編號空間的逆向對映的任何支援。

irq_domain 庫在 irq_alloc_desc*() API 之上添加了 hwirq 和 IRQ 編號之間的對映。優先使用 irq_domain 來管理對映,而不是中斷控制器驅動程式開放編碼其自己的反向對映方案。

irq_domain 還實現了從抽象 struct irq_fwspec 到 hwirq 編號的轉換(目前為止為裝置樹、非 DT 韌體節點、ACPI GSI 和軟體節點),並且可以輕鬆擴充套件以支援其他 IRQ 拓撲資料來源。該實現無需任何額外的平臺支援程式碼即可執行。

irq_domain 用法

struct irq_domain 可以定義為 irq 域控制器。也就是說,它處理給定中斷域的硬體和虛擬中斷號之間的對映。域結構通常由給定 PIC 例項的 PIC 程式碼建立(儘管域可以覆蓋多個 PIC,如果它們具有扁平編號模型)。域回撥負責在給定 irq_desc 上設定 irq_chip(在對映之後)。

主機程式碼和資料結構使用 fwnode_handle 指標來標識域。在某些情況下,為了保持原始碼相容性,此 fwnode 指標被“升級”為 DT device_node。對於那些不為中斷控制器提供唯一識別符號的韌體基礎設施,irq_domain 程式碼提供了一個 fwnode 分配器。

中斷控制器驅動程式透過呼叫 irq_domain_create_*() 函式之一(每種對映方法都有不同的分配器函式,稍後會詳細介紹)來建立和註冊 struct irq_domain。該函式將成功後返回指向 struct irq_domain 的指標。呼叫者必須為分配器函式提供一個 struct irq_domain_ops 指標。

在大多數情況下,irq_domain 將以空狀態開始,沒有任何 hwirq 和 IRQ 編號之間的對映。透過呼叫 irq_create_mapping() 將對映新增到 irq_domain,該函式接受 irq_domain 和 hwirq 編號作為引數。如果 hwirq 的對映尚不存在,irq_create_mapping() 將分配一個新的 Linux irq_desc,將其與 hwirq 關聯,並呼叫 irq_domain_ops.map() 回撥。在那裡,驅動程式可以執行任何所需的硬體設定。

一旦建立了對映,就可以透過多種方法檢索或使用它

請注意,irq 域查詢必須發生在與 RCU 讀取端關鍵部分相容的上下文中。

必須在任何呼叫 irq_find_mapping() 之前至少一次呼叫 irq_create_mapping() 函式,否則不會分配描述符。

如果驅動程式具有 Linux IRQ 編號或 irq_data 指標,並且需要知道關聯的 hwirq 編號(例如在 irq_chip 回撥中),則可以直接從 irq_data.hwirq 獲取。

irq_domain 對映型別

有幾種機制可用於從 hwirq 到 Linux irq 的反向對映,每種機制都使用不同的分配函式。應使用哪種反向對映型別取決於用例。以下描述了每種反向對映型別

線性

irq_domain_create_linear()

線性反向對映維護一個由 hwirq 編號索引的固定大小表。當對映 hwirq 時,將為 hwirq 分配一個 irq_desc,並將 IRQ 編號儲存在表中。

當 hwirq 的最大數量是固定的並且相對較小(~ < 256)時,線性對映是一個不錯的選擇。此對映的優點是 IRQ 編號的固定時間查詢,並且僅為使用中的 IRQ 分配 irq_desc。缺點是表必須與最大的 hwirq 編號一樣大。

大多數驅動程式應使用線性對映。

irq_domain_create_tree()

irq_domain 維護從 hwirq 編號到 Linux IRQ 的基數樹對映。當對映 hwirq 時,將分配一個 irq_desc,並且 hwirq 用作基數樹的查詢鍵。

如果 hwirq 編號可能非常大,則樹對映是一個不錯的選擇,因為它不需要分配與最大 hwirq 編號一樣大的表。缺點是 hwirq 到 IRQ 編號的查詢取決於表中有多少個條目。

很少有驅動程式需要此對映。

無對映

irq_domain_create_nomap()

當可以在硬體中對 hwirq 編號進行程式設計時,應使用無對映。在這種情況下,最好將 Linux IRQ 編號程式設計到硬體本身中,這樣就不需要對映。呼叫 irq_create_direct_mapping() 將分配一個 Linux IRQ 編號並呼叫 .map() 回撥,以便驅動程式可以將 Linux IRQ 編號程式設計到硬體中。

大多數驅動程式無法使用此對映,並且它現在已在 CONFIG_IRQ_DOMAIN_NOMAP 選項上進行門控。請避免引入此 API 的新使用者。

舊版

irq_domain_create_simple()
irq_domain_create_legacy()

舊版對映是針對已經為 hwirq 分配了一系列 irq_desc 的驅動程式的特殊情況。當無法立即轉換驅動程式以使用線性對映時,將使用它。例如,許多嵌入式系統板支援檔案使用一組 #defines 作為傳遞給 struct device 註冊的 IRQ 編號。在這種情況下,無法動態分配 Linux IRQ 編號,應使用舊版對映。

顧名思義,*_legacy() 函式已被棄用,僅用於簡化對舊平臺的支援。不應新增新使用者。當 *_simple() 函式的使用導致舊版行為時,也是如此。

舊版對映假定已為控制器分配了連續的 IRQ 編號範圍,並且可以透過將固定偏移量新增到 hwirq 編號來計算 IRQ 編號,反之亦然。缺點是它要求中斷控制器管理 IRQ 分配,並且即使未使用,也需要為每個 hwirq 分配一個 irq_desc。

僅當必須支援固定 IRQ 對映時,才應使用舊版對映。例如,ISA 控制器將使用舊版對映來對映 Linux IRQ 0-15,以便現有 ISA 驅動程式獲得正確的 IRQ 編號。

舊版對映的大多數使用者應使用 irq_domain_create_simple(),如果系統提供了 IRQ 範圍,則該函式將僅使用舊版域,否則將使用線性域對映。此呼叫的語義是,如果指定了 IRQ 範圍,則將即時分配描述符,如果未指定範圍,則將回退到 irq_domain_create_linear(),這意味著不會分配 irq 描述符。

簡單域的典型用例是 irqchip 提供程式同時支援動態和靜態 IRQ 分配。

為了避免最終使用線性域並且沒有分配描述符的情況,非常重要的是,使用簡單域的驅動程式在任何 irq_find_mapping() 之前呼叫 irq_create_mapping(),因為後者實際上適用於靜態 IRQ 分配情況。

層次結構 IRQ 域

在某些體系結構上,可能涉及多箇中斷控制器,以便將中斷從裝置傳遞到目標 CPU。讓我們看一下 x86 平臺上的典型中斷傳遞路徑

Device --> IOAPIC -> Interrupt remapping Controller -> Local APIC -> CPU

涉及三個中斷控制器

  1. IOAPIC 控制器

  2. 中斷重對映控制器

  3. 本地 APIC 控制器

為了支援這樣的硬體拓撲並使軟體體系結構與硬體體系結構匹配,為每個中斷控制器構建了一個 irq_domain 資料結構,並將這些 irq_domain 組織成層次結構。構建 irq_domain 層次結構時,靠近裝置的 irq_domain 是子域,靠近 CPU 的 irq_domain 是父域。因此,將為上面的示例構建如下的層次結構

CPU Vector irq_domain (root irq_domain to manage CPU vectors)
        ^
        |
Interrupt Remapping irq_domain (manage irq_remapping entries)
        ^
        |
IOAPIC irq_domain (manage IOAPIC delivery entries/pins)

有四個主要介面可用於層次結構 irq_domain

  1. irq_domain_alloc_irqs():分配 IRQ 描述符和中斷控制器相關資源以傳遞這些中斷。

  2. irq_domain_free_irqs():釋放與這些中斷關聯的 IRQ 描述符和中斷控制器相關資源。

  3. irq_domain_activate_irq():啟用中斷控制器硬體以傳遞中斷。

  4. irq_domain_deactivate_irq():停用中斷控制器硬體以停止傳遞中斷。

支援層次結構 irq_domain 需要以下內容

  1. struct irq_domain 中的 parent 欄位用於維護 irq_domain 層次結構資訊。

  2. struct irq_data 中的 parent_data 欄位用於構建層次結構 irq_data 以匹配層次結構 irq_domain。irq_data 用於儲存 irq_domain 指標和硬體 irq 編號。

  3. struct irq_domain_ops 中的 alloc()free() 和其他回撥用於支援層次結構 irq_domain 操作。

在支援層次結構 irq_domain 和層次結構 irq_data 準備就緒後,為每個中斷控制器構建一個 irq_domain 結構,併為與 IRQ 關聯的每個 irq_domain 分配一個 irq_data 結構。

為了使中斷控制器驅動程式支援層次結構 irq_domain,它需要

  1. 實現 irq_domain_ops.alloc() 和 irq_domain_ops.free()

  2. 可選地,實現 irq_domain_ops.activate() 和 irq_domain_ops.deactivate()。

  3. 可選地,實現 irq_chip 以管理中斷控制器硬體。

  4. 無需實現 irq_domain_ops.map() 和 irq_domain_ops.unmap()。它們與層次結構 irq_domain 不一起使用。

請注意,層次結構 irq_domain 絕不是 x86 特定的,並且被大量用於支援其他體系結構,例如 ARM、ARM64 等。

堆疊 irq_chip

現在,我們可以更進一步來支援堆疊(層次結構)irq_chip。也就是說,一個 irq_chip 與層次結構中的每個 irq_data 相關聯。子 irq_chip 可以透過自身或透過與其父 irq_chip 合作來實現所需的動作。

使用堆疊 irq_chip,中斷控制器驅動程式只需要處理自身管理的硬體,並且可以在需要時向其父 irq_chip 請求服務。因此,我們可以實現更清晰的軟體體系結構。

除錯

透過開啟 CONFIG_GENERIC_IRQ_DEBUGFS,IRQ 子系統的大部分內部結構都會在 debugfs 中公開。

提供的結構和公共函式

本章包含用於 IRQ 域的結構和匯出的核心 API 函式的自動生成文件。

struct irq_fwspec

通用 IRQ 說明符結構

定義:

struct irq_fwspec {
    struct fwnode_handle    *fwnode;
    int param_count;
    u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS];
};

成員

fwnode

指向特定於韌體的描述符的指標

param_count

特定於裝置的引數數量

param

特定於裝置的引數

描述

此結構直接仿照 of_phandle_args,用於傳遞中斷的特定於裝置的描述。

struct irq_domain_ops

irq_domain 物件的方法

定義:

struct irq_domain_ops {
    int (*match)(struct irq_domain *d, struct device_node *node, enum irq_domain_bus_token bus_token);
    int (*select)(struct irq_domain *d, struct irq_fwspec *fwspec, enum irq_domain_bus_token bus_token);
    int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw);
    void (*unmap)(struct irq_domain *d, unsigned int virq);
    int (*xlate)(struct irq_domain *d, struct device_node *node,const u32 *intspec, unsigned int intsize, unsigned long *out_hwirq, unsigned int *out_type);
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY;
    int (*alloc)(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs, void *arg);
    void (*free)(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs);
    int (*activate)(struct irq_domain *d, struct irq_data *irqd, bool reserve);
    void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data);
    int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec, unsigned long *out_hwirq, unsigned int *out_type);
#endif;
#ifdef CONFIG_GENERIC_IRQ_DEBUGFS;
    void (*debug_show)(struct seq_file *m, struct irq_domain *d, struct irq_data *irqd, int ind);
#endif;
};

成員

match

將中斷控制器裝置節點與域匹配,匹配時返回 1

select

匹配中斷控制器 fw 規範。它比 match 更通用,因為它接收完整的 struct irq_fwspec。因此,如果提供了 select,則首選它。匹配時返回 1。

map

建立或更新虛擬 irq 編號和 hw irq 編號之間的對映。對於給定的對映,這隻會被呼叫一次。

unmap

處置此類對映

xlate

給定裝置樹節點和中斷說明符,解碼硬體 irq 編號和 linux irq 型別值。

alloc

virq 開始分配 nr_irqs 箇中斷。

free

virq 開始釋放 nr_irqs 箇中斷。

activate

在 HW 中啟用一箇中斷 (irqd)。如果設定了 reserve,則只保留向量。如果未設定,則分配向量(從 request_irq() 呼叫)。

deactivate

解除一箇中斷 (irqd) 的武裝。

translate

給定 fwspec,解碼硬體 irq 編號 (out_hwirq) 和 linux irq 型別值 (out_type)。這是廣義的 xlate(在 struct irq_fwspec 上),如果提供了,則首選它。

debug_show

對於域,以在 debugfs 中顯示中斷的特定資料。

描述

以下函式由驅動程式提供,並在每次建立新對映或處置舊對映時呼叫。然後,驅動程式可以繼續進行所需的任何內部資料結構管理。它還需要在從 map() 返回時設定 irq_desc。

struct irq_domain

硬體中斷號轉換物件

定義:

struct irq_domain {
    struct list_head                link;
    const char                      *name;
    const struct irq_domain_ops     *ops;
    void *host_data;
    unsigned int                    flags;
    unsigned int                    mapcount;
    struct mutex                    mutex;
    struct irq_domain               *root;
    struct fwnode_handle            *fwnode;
    enum irq_domain_bus_token       bus_token;
    struct irq_domain_chip_generic  *gc;
    struct device                   *dev;
    struct device                   *pm_dev;
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY;
    struct irq_domain               *parent;
#endif;
#ifdef CONFIG_GENERIC_MSI_IRQ;
    const struct msi_parent_ops     *msi_parent_ops;
#endif;
    void (*exit)(struct irq_domain *d);
    irq_hw_number_t hwirq_max;
    unsigned int                    revmap_size;
    struct radix_tree_root          revmap_tree;
    struct irq_data __rcu           *revmap[] ;
};

成員

link

全域性 irq_domain 列表中的元素。

name

中斷域的名稱

ops

指向 irq_domain 方法的指標

host_data

供所有者使用的私有資料指標。irq_domain 核心程式碼不接觸。

flags

每個 irq_domain 的標誌

mapcount

對映的中斷數

mutex

域鎖,分層域使用根域的鎖

root

指向根域的指標,如果是非分層結構,則指向包含結構

fwnode

指向與 irq_domain 關聯的韌體節點的指標。很容易透過 irq_domain_get_of_node 訪問器將其交換為 of_node

bus_token

fwnode 的 device_node 可能用於多個 irq 域。但是與 bus_token 結合使用時,該對在系統中應該是唯一的。

gc

指向通用晶片列表的指標。有一個輔助函式可用於為使用使用此指標的通用晶片庫的中斷控制器驅動程式設定一個或多個通用晶片。

dev

指向例項化 irqdomain 的裝置的指標。使用每個裝置 irq 域時,這不一定與 pm_dev 相同。

pm_dev

指向可用於與 irq 域相關的電源管理目的的裝置的指標。

parent

指向父 irq_domain 以支援層次結構 irq_domain

msi_parent_ops

用於每個裝置域初始化的指向 MSI 父域方法的指標

exit

銷燬域時呼叫的函式

hwirq_max

HW irq 編號的上限。特別是為了避免與保留的 HW irq 發生衝突/故障。可以是 ~0。

revmap_size

線性對映表 revmap 的大小

revmap_tree

用於不適合線性對映的 hwirq 的基數對映樹

revmap

irq_data 指標的線性表

描述

可選元素:Revmap 資料,由 irq 域程式碼在內部使用

struct irq_domain_info

域資訊結構

定義:

struct irq_domain_info {
    struct fwnode_handle                    *fwnode;
    unsigned int                            domain_flags;
    unsigned int                            size;
    irq_hw_number_t hwirq_max;
    int direct_max;
    unsigned int                            hwirq_base;
    unsigned int                            virq_base;
    enum irq_domain_bus_token               bus_token;
    const char                              *name_suffix;
    const struct irq_domain_ops             *ops;
    void *host_data;
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY;
    struct irq_domain                       *parent;
#endif;
    struct irq_domain_chip_generic_info     *dgc_info;
    int (*init)(struct irq_domain *d);
    void (*exit)(struct irq_domain *d);
};

成員

fwnode

中斷控制器的韌體節點

domain_flags

要新增到域標誌的其他標誌

size

線性對映的大小;對於僅基數對映,為 0

hwirq_max

控制器支援的最大中斷數

direct_max

直接對映的最大值;對於無限制,請使用 ~0;對於無直接對映,請使用 0

hwirq_base

第一個硬體中斷號(僅限舊版域)

virq_base

舊版域的第一個 Linux 中斷號,用於在域建立後立即關聯中斷

bus_token

域匯流排令牌

name_suffix

可選名稱字尾,以避免使用相同 fwnode 新增多個域時發生衝突

ops

域操作回撥

host_data

控制器私有資料指標

parent

指向層次結構域中使用的父 irq 域的指標

dgc_info

如果不是 NULL,則用於為域建立通用晶片的 Geneneric 晶片資訊結構指標。

init

建立域時呼叫的函式。允許進行一些額外的域初始化。

exit

銷燬域時呼叫的函式。允許執行一些額外的清理操作。

struct irq_domain *irq_domain_create_linear(struct fwnode_handle *fwnode, unsigned int size, const struct irq_domain_ops *ops, void *host_data)

分配和註冊線性 revmap irq_domain。

引數

struct fwnode_handle *fwnode

指向中斷控制器的 FW 節點的指標。

unsigned int size

域中的中斷數。

const struct irq_domain_ops *ops

map/unmap 域回撥

void *host_data

控制器私有資料指標

返回

新建立的 irq_domain

unsigned int irq_create_mapping(struct irq_domain *domain, irq_hw_number_t hwirq)

將硬體中斷對映到 linux irq 空間

引數

struct irq_domain *domain

擁有此硬體中斷的域,如果為 NULL,則表示預設域

irq_hw_number_t hwirq

該域空間中的硬體 irq 編號

描述

每個硬體中斷只允許一個對映。

如果要指定感應/觸發器,則應在從該呼叫返回的編號上呼叫 set_irq_type()。

返回

Linux irq 編號,如果出錯,則為 0

struct irq_desc *irq_resolve_mapping(struct irq_domain *domain, irq_hw_number_t hwirq)

從 hw irq 編號查詢 linux irq。

引數

struct irq_domain *domain

擁有此硬體中斷的域

irq_hw_number_t hwirq

該域空間中的硬體 irq 編號

返回

中斷描述符

unsigned int irq_find_mapping(struct irq_domain *domain, irq_hw_number_t hwirq)

從 hw irq 編號查詢 linux irq。

引數

struct irq_domain *domain

擁有此硬體中斷的域

irq_hw_number_t hwirq

該域空間中的硬體 irq 編號

返回

Linux irq 編號,如果未找到,則為 0

struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent, unsigned int flags, unsigned int size, struct fwnode_handle *fwnode, const struct irq_domain_ops *ops, void *host_data)

將 irqdomain 新增到層次結構中

引數

struct irq_domain *parent

要與新域關聯的父 irq 域

unsigned int flags

與域關聯的 Irq 域標誌

unsigned int size

域的大小。請參見下文

struct fwnode_handle *fwnode

中斷控制器的可選 fwnode

const struct irq_domain_ops *ops

指向中斷域回撥的指標

void *host_data

控制器私有資料指標

描述

如果 size 為 0,則建立樹域,否則建立線性域。

如果成功,則將父級與新域關聯,並設定域標誌。

返回

指向 IRQ 域的指標,如果失敗,則為 NULL

int irq_domain_alloc_irqs(struct irq_domain *domain, unsigned int nr_irqs, int node, void *arg)

從域分配 IRQ

引數

struct irq_domain *domain

要從中分配的域

unsigned int nr_irqs

要分配的 IRQ 數

int node

用於記憶體分配的 NUMA 節點 ID

void *arg

特定於域的引數

描述

請參見 __irq_domain_alloc_irqs() 的文件。

struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, const char *name, phys_addr_t *pa)

分配適合於標識 irq 域的 fwnode_handle

引數

unsigned int type

irqchip_fwnode 的型別。請參見 linux/irqdomain.h

int id

如果 name != NULL,則為可選的使用者提供的 id

const char *name

可選的使用者提供的域名

phys_addr_t *pa

可選的使用者提供的物理地址

描述

分配一個 struct irqchip_fwid,並返回指向嵌入的 fwnode_handle 的指標(如果失敗,則返回 NULL)。

注意

型別 IRQCHIP_FWNODE_NAMED 和 IRQCHIP_FWNODE_NAMED_ID 僅用於將名稱資訊傳輸到 irqdomain 建立程式碼。該節點未儲存。對於其他型別,指標儲存在 irq 域結構中。

void irq_domain_free_fwnode(struct fwnode_handle *fwnode)

釋放一個非OF支援的 fwnode_handle

引數

struct fwnode_handle *fwnode

要釋放的 fwnode_handle

描述

釋放一個用 irq_domain_alloc_fwnode 分配的 fwnode_handle。

struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)

例項化一個新的 irq 域資料結構

引數

const struct irq_domain_info *info

指向此域資訊的域資訊指標

返回

指向例項化的 irq 域的指標,或一個 ERR_PTR 值。

void irq_domain_remove(struct irq_domain *domain)

移除一個 irq 域。

引數

struct irq_domain *domain

要移除的域

描述

此例程用於移除一個 irq 域。呼叫者必須確保在使用之前,域中的所有對映都已根據 revmap 型別進行處理。

struct irq_domain *irq_domain_create_simple(struct fwnode_handle *fwnode, unsigned int size, unsigned int first_irq, const struct irq_domain_ops *ops, void *host_data)

註冊一個 irq_domain 並可選擇對映一個 irq 範圍

引數

struct fwnode_handle *fwnode

中斷控制器的韌體節點

unsigned int size

對映中的 irq 總數

unsigned int first_irq

分配給域的 irq 塊的第一個數字,傳遞零以動態分配 irq。如果 first_irq 非零,則預先將域中的所有 irq 對映到從 first_irq 開始的 virq。

const struct irq_domain_ops *ops

域回撥

void *host_data

控制器私有資料指標

描述

分配一個 irq_domain,如果 first_irq 為正,則可選擇分配 irq_descs 並將所有 hwirq 對映到從 first_irq 開始的 virq。

此操作旨在實現大多數中斷控制器的預期行為。如果使用裝置樹,則 first_irq 將為 0,並且 irq 會動態地進行對映。但是,如果控制器需要靜態 virq 分配(非 DT 引導),則可以正確設定。

struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec, enum irq_domain_bus_token bus_token)

為給定的 fwspec 查詢域

引數

struct irq_fwspec *fwspec

中斷的 FW 說明符

enum irq_domain_bus_token bus_token

特定於域的資料

void irq_set_default_domain(struct irq_domain *domain)

設定一個“預設” irq 域

引數

struct irq_domain *domain

預設域指標

描述

為了方便起見,可以設定一個“預設”域,每當將 NULL 傳遞給 irq_create_mapping() 時,都會使用它。這使得平臺更容易處理裝置樹中未正確表示的一些硬編碼中斷號。

struct irq_domain *irq_get_default_domain(void)

檢索“預設” irq 域

引數

void

無引數

返回

預設域(如果有)。

描述

現代程式碼永遠不應使用此函式。此函式只應在無法實現 firmware->fwnode 對映的系統上使用(DT 和 ACPI 均提供)。

unsigned int irq_create_direct_mapping(struct irq_domain *domain)

為直接對映分配一個 irq

引數

struct irq_domain *domain

為其分配 irq 的域,或 NULL 表示預設域

描述

此例程用於可以選擇其生成的硬體中斷號的 irq 控制器。在這種情況下,最簡單的方法是將 Linux irq 用作硬體中斷號。它仍然使用線性或基數樹來儲存對映,但 irq 控制器可以透過直接使用 hwirq 來最佳化 revmap 路徑。

unsigned int irq_create_mapping_affinity(struct irq_domain *domain, irq_hw_number_t hwirq, const struct irq_affinity_desc *affinity)

將硬體中斷對映到 linux irq 空間

引數

struct irq_domain *domain

擁有此硬體中斷的域,如果為 NULL,則表示預設域

irq_hw_number_t hwirq

該域空間中的硬體 irq 編號

const struct irq_affinity_desc *affinity

irq 親和性

描述

每個硬體中斷只允許一個對映。返回一個 Linux irq 號碼。如果要指定感應/觸發器,則應在從該呼叫返回的號碼上呼叫 set_irq_type()。

void irq_dispose_mapping(unsigned int virq)

取消對映一箇中斷

引數

unsigned int virq

要取消對映的中斷的 Linux irq 號碼

struct irq_desc *__irq_resolve_mapping(struct irq_domain *domain, irq_hw_number_t hwirq, unsigned int *irq)

從 hw irq 編號查詢 linux irq。

引數

struct irq_domain *domain

擁有此硬體中斷的域

irq_hw_number_t hwirq

該域空間中的硬體 irq 編號

unsigned int *irq

可選指標,用於在需要時返回 Linux irq

描述

返回中斷描述符。

int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr, const u32 *intspec, unsigned int intsize, unsigned long *out_hwirq, unsigned int *out_type)

用於直接單元格繫結的通用 xlate

引數

struct irq_domain *d

參與轉換的中斷域

struct device_node *ctrlr

裝置樹節點,用於轉換其中斷的裝置

const u32 *intspec

來自裝置樹的中斷說明符資料

unsigned int intsize

intspec 中的條目數

unsigned long *out_hwirq

用於儲存硬體中斷號的指標

unsigned int *out_type

用於儲存中斷型別的指標

描述

裝置樹 IRQ 說明符轉換函式,適用於單元格值直接對映到 hwirq 號碼的一個單元格繫結。

int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr, const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_type)

用於直接雙單元格繫結的通用 xlate

引數

struct irq_domain *d

參與轉換的中斷域

struct device_node *ctrlr

裝置樹節點,用於轉換其中斷的裝置

const u32 *intspec

來自裝置樹的中斷說明符資料

unsigned int intsize

intspec 中的條目數

irq_hw_number_t *out_hwirq

用於儲存硬體中斷號的指標

unsigned int *out_type

用於儲存中斷型別的指標

描述

裝置樹 IRQ 說明符轉換函式,適用於單元格值直接對映到 hwirq 號碼和 Linux irq 標誌的雙單元格繫結。

int irq_domain_xlate_twothreecell(struct irq_domain *d, struct device_node *ctrlr, const u32 *intspec, unsigned int intsize, irq_hw_number_t *out_hwirq, unsigned int *out_type)

用於直接雙單元格或三單元格繫結的通用 xlate

引數

struct irq_domain *d

參與轉換的中斷域

struct device_node *ctrlr

裝置樹節點,用於轉換其中斷的裝置

const u32 *intspec

來自裝置樹的中斷說明符資料

unsigned int intsize

intspec 中的條目數

irq_hw_number_t *out_hwirq

用於儲存硬體中斷號的指標

unsigned int *out_type

用於儲存中斷型別的指標

描述

用於雙單元格或三單元格繫結的裝置樹中斷說明符轉換函式,其中單元格值直接對映到硬體中斷號和型別說明符。

int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr, const u32 *intspec, unsigned int intsize, unsigned long *out_hwirq, unsigned int *out_type)

用於單單元格或雙單元格繫結的通用 xlate

引數

struct irq_domain *d

參與轉換的中斷域

struct device_node *ctrlr

裝置樹節點,用於轉換其中斷的裝置

const u32 *intspec

來自裝置樹的中斷說明符資料

unsigned int intsize

intspec 中的條目數

unsigned long *out_hwirq

用於儲存硬體中斷號的指標

unsigned int *out_type

用於儲存中斷型別的指標

描述

裝置樹 IRQ 說明符轉換函式,適用於單元格值直接對映到 hwirq 號碼和 Linux irq 標誌的單單元格或雙單元格繫結。

注意

除非您的中斷控制器明確支援單單元格和雙單元格繫結,否則請勿使用此函式。對於大多數控制器,應使用上面的 _onecell() 或 _twocell() 變體。

int irq_domain_translate_onecell(struct irq_domain *d, struct irq_fwspec *fwspec, unsigned long *out_hwirq, unsigned int *out_type)

用於直接單元格繫結的通用轉換

引數

struct irq_domain *d

參與轉換的中斷域

struct irq_fwspec *fwspec

要轉換的韌體中斷說明符

unsigned long *out_hwirq

用於儲存硬體中斷號的指標

unsigned int *out_type

用於儲存中斷型別的指標

int irq_domain_translate_twocell(struct irq_domain *d, struct irq_fwspec *fwspec, unsigned long *out_hwirq, unsigned int *out_type)

用於直接雙單元格繫結的通用轉換

引數

struct irq_domain *d

參與轉換的中斷域

struct irq_fwspec *fwspec

要轉換的韌體中斷說明符

unsigned long *out_hwirq

用於儲存硬體中斷號的指標

unsigned int *out_type

用於儲存中斷型別的指標

描述

裝置樹 IRQ 說明符轉換函式,適用於單元格值直接對映到 hwirq 號碼和 Linux irq 標誌的雙單元格繫結。

int irq_domain_translate_twothreecell(struct irq_domain *d, struct irq_fwspec *fwspec, unsigned long *out_hwirq, unsigned int *out_type)

用於直接雙單元格或三單元格繫結的通用轉換

引數

struct irq_domain *d

參與轉換的中斷域

struct irq_fwspec *fwspec

要轉換的韌體中斷說明符

unsigned long *out_hwirq

用於儲存硬體中斷號的指標

unsigned int *out_type

用於儲存中斷型別的指標

描述

用於雙單元格或三單元格規範的韌體中斷說明符轉換函式,其中引數值直接對映到硬體中斷號和型別說明符。

void irq_domain_reset_irq_data(struct irq_data *irq_data)

清除 irq_data 中的 hwirq、chip 和 chip_data

引數

struct irq_data *irq_data

指向 irq_data 的指標

int irq_domain_disconnect_hierarchy(struct irq_domain *domain, unsigned int virq)

標記層次結構的第一個未使用的級別

引數

struct irq_domain *domain

要斷開層次結構的 IRQ 域

unsigned int virq

要在其中修剪層次結構的 IRQ 號碼

描述

將屬於 domainvirq 級別標記為已斷開連線。如果 virq 沒有指向 domain 的有效 irq_data,則返回 -EINVAL。

它的唯一用途是能夠修剪此中斷沒有任何實際意義的層次結構級別,並且驅動程式從其 .alloc() 回撥中將其標記為這樣。

struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain, unsigned int virq)

獲取與 virqdomain 關聯的 irq_data

引數

struct irq_domain *domain

要匹配的域

unsigned int virq

要獲取 irq_data 的 IRQ 號碼

int irq_domain_set_hwirq_and_chip(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq, const struct irq_chip *chip, void *chip_data)

domain 設定 virq 的 hwirq 和 irqchip

引數

struct irq_domain *domain

要匹配的中斷域

unsigned int virq

IRQ 號碼

irq_hw_number_t hwirq

hwirq 號碼

const struct irq_chip *chip

關聯的中斷晶片

void *chip_data

關聯的晶片資料

void irq_domain_set_info(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq, const struct irq_chip *chip, void *chip_data, irq_flow_handler_t handler, void *handler_data, const char *handler_name)

domain 中設定 virq 的完整資料

引數

struct irq_domain *domain

要匹配的中斷域

unsigned int virq

IRQ 號碼

irq_hw_number_t hwirq

硬體中斷號

const struct irq_chip *chip

關聯的中斷晶片

void *chip_data

關聯的中斷晶片資料

irq_flow_handler_t handler

中斷流處理程式

void *handler_data

中斷流處理程式資料

const char *handler_name

中斷處理程式名稱

void irq_domain_free_irqs_common(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs)

清除 irq_data 並釋放父項

引數

struct irq_domain *domain

要匹配的中斷域

unsigned int virq

要從其開始的 IRQ 號碼

unsigned int nr_irqs

要釋放的 irq 的數量

int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, unsigned int nr_irqs, int node, void *arg, bool realloc, const struct irq_affinity_desc *affinity)

從域分配 IRQ

引數

struct irq_domain *domain

要從中分配的域

int irq_base

如果 irq_base >= 0,則分配指定的 IRQ 號碼

unsigned int nr_irqs

要分配的 IRQ 數

int node

用於記憶體分配的 NUMA 節點 ID

void *arg

特定於域的引數

bool realloc

如果為 true,則已分配 IRQ 描述符

const struct irq_affinity_desc *affinity

多佇列裝置的可選 irq 親和性掩碼

描述

分配 IRQ 號碼並初始化所有資料結構以支援層次結構 IRQ 域。引數 realloc 主要用於支援舊版 IRQ。返回錯誤程式碼或分配的 IRQ 號碼

設定 IRQ 的整個過程已分為兩個步驟。第一步,__irq_domain_alloc_irqs(),用於分配 IRQ 描述符和所需的硬體資源。第二步,irq_domain_activate_irq(),用於使用預分配的資源對硬體進行程式設計。這樣,當無法分配資源時,更容易回滾。

int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg)

將域推送到層次結構的頂部。

引數

struct irq_domain *domain

要推送的域。

int virq

要將域推送到的 Irq。

void *arg

傳遞給 irq_domain_ops alloc() 函式。

描述

對於已存在的 irqdomain 層次結構(可能透過呼叫 pci_enable_msix() 獲得),將一個附加域新增到處理鏈的頭部。必須在呼叫 request_irq() 之前呼叫。

int irq_domain_pop_irq(struct irq_domain *domain, int virq)

從層次結構的頂部移除域。

引數

struct irq_domain *domain

要移除的域。

int virq

要從中移除域的 Irq。

描述

撤銷對 irq_domain_push_irq() 呼叫的影響。必須在 request_irq() 之前或 free_irq() 之後呼叫。

int irq_domain_alloc_irqs_parent(struct irq_domain *domain, unsigned int irq_base, unsigned int nr_irqs, void *arg)

從父域分配中斷

引數

struct irq_domain *domain

必須分配中斷的域

unsigned int irq_base

基本 IRQ 編號

unsigned int nr_irqs

要分配的 IRQ 數量

void *arg

分配資料(特定於 arch/domain)

void irq_domain_free_irqs_parent(struct irq_domain *domain, unsigned int irq_base, unsigned int nr_irqs)

從父域釋放中斷

引數

struct irq_domain *domain

必須釋放中斷的域

unsigned int irq_base

基本 IRQ 編號

unsigned int nr_irqs

要釋放的 IRQ 數量

提供的內部函式

本章包含內部函式的自動生成文件。

void irq_domain_free_irqs_top(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs)

清除處理程式和處理程式資料,清除 irqdata 並釋放父級

引數

struct irq_domain *domain

要匹配的中斷域

unsigned int virq

要從其開始的 IRQ 號碼

unsigned int nr_irqs

要釋放的 irq 的數量

void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs)

釋放 IRQ 編號和關聯的資料結構

引數

unsigned int virq

基本 IRQ 編號

unsigned int nr_irqs

要釋放的 IRQ 數量

int irq_domain_activate_irq(struct irq_data *irq_data, bool reserve)

遞迴呼叫 domain_ops->activate 以啟用中斷

引數

struct irq_data *irq_data

與中斷關聯的最外層 irq_data

bool reserve

如果設定,則僅保留中斷向量而不是分配一個

描述

這是呼叫 domain_ops->activate 以程式設計中斷控制器的第二步,因此中斷實際上可以傳遞。

void irq_domain_deactivate_irq(struct irq_data *irq_data)

遞迴呼叫 domain_ops->deactivate 以停用中斷

引數

struct irq_data *irq_data

與中斷關聯的最外層 irq_data

描述

它呼叫 domain_ops->deactivate 以程式設計中斷控制器以停用中斷傳遞。