Linux 通用 IRQ 處理

版權:

© 2005-2010: Thomas Gleixner

版權:

© 2005-2006: Ingo Molnar

引言

通用中斷處理層旨在為裝置驅動程式提供完整的中斷處理抽象。它能夠處理所有不同型別的中斷控制器硬體。裝置驅動程式使用通用 API 函式來請求、啟用、停用和釋放中斷。驅動程式無需瞭解任何中斷硬體細節,因此它們可以在不同平臺上使用而無需修改程式碼。

本文件提供給希望在其架構上實現基於通用 IRQ 處理層的中斷子系統的開發人員。

原理

Linux 中中斷處理的原始實現使用了 __do_IRQ() 超級處理程式,它能夠處理各種型別的中斷邏輯。

最初,Russell King 識別了不同型別的處理程式,為 Linux 2.5/2.6 中的 ARM 中斷處理程式實現構建了一個相當通用的集合。他區分了:

  • 電平觸發型別

  • 邊沿觸發型別

  • 簡單型別

在實現過程中,我們識別了另一種型別:

  • 快速 EOI 型別

__do_IRQ() 超級處理程式的 SMP 世界中,識別出另一種型別:

  • 每 CPU 型別

這種高階 IRQ 處理程式的拆分實現允許我們最佳化每種特定中斷型別的處理流程。這減少了特定程式碼路徑中的複雜性,並允許對給定型別進行最佳化處理。

原始的通用 IRQ 實現使用 hw_interrupt_type 結構及其 ->ack->end [等] 回撥函式來區分超級處理程式中的流程控制。這導致了流程邏輯和低階硬體邏輯的混淆,也導致了不必要的程式碼重複:例如,在 i386 中,有 ioapic_level_irqioapic_edge_irq 這兩種 IRQ 型別,它們共享許多低階細節但具有不同的流程處理。

更自然的抽象是“irq 流”和“晶片細節”的清晰分離。

分析一些架構的 IRQ 子系統實現表明,它們中的大多數可以使用一組通用的“irq 流”方法,只需要新增晶片級特定程式碼。這種分離對於需要在 IRQ 流本身而不是晶片細節中進行特定調整的(子)架構也很有價值——因此提供了更透明的 IRQ 子系統設計。

每個中斷描述符都分配有自己的高階流處理程式,通常是通用實現之一。(這種高階流處理程式實現還使得提供解複用處理程式變得簡單,這可以在各種架構上的嵌入式平臺中找到。)

這種分離使通用中斷處理層更加靈活和可擴充套件。例如,一個(子)架構可以為“電平觸發”中斷使用通用 IRQ 流實現,並新增一個(子)架構特定的“邊沿觸發”實現。

為了使向新模型的過渡更容易並防止現有實現的破壞,__do_IRQ() 超級處理程式仍然可用。這導致了暫時的一種二元性。隨著時間的推移,新模型應該在越來越多的架構中使用,因為它能夠實現更小、更乾淨的 IRQ 子系統。它現在已經被棄用三年了,即將被移除。

已知錯誤和假設

無(敲木頭)。

抽象層

中斷程式碼中有三個主要的抽象級別:

  1. 高階驅動程式 API

  2. 高階 IRQ 流處理程式

  3. 晶片級硬體封裝

中斷控制流

每個中斷都由一箇中斷描述符結構 irq_desc 描述。中斷透過一個“無符號整數”數值引用,該數值在描述符結構陣列中選擇相應的中斷描述結構。描述符結構包含狀態資訊以及指向分配給此中斷的中斷流方法和中斷晶片結構的指標。

每當中斷觸發時,低階架構程式碼透過呼叫 desc->handle_irq() 進入通用中斷程式碼。此高階 IRQ 處理函式僅使用由分配的晶片描述符結構引用的 desc->irq_data.chip 原語。

高階驅動程式 API

高階驅動程式 API 包含以下函式:

詳情請參閱自動生成的函式文件。

高階 IRQ 流處理程式

通用層提供了一組預定義的中斷流方法:

中斷流處理程式(無論是預定義的還是特定於架構的)由架構在啟動期間或裝置初始化期間分配給特定的中斷。

預設流實現

輔助函式

輔助函式呼叫晶片原語,並由預設流實現使用。以下輔助函式已實現(簡化摘錄):

default_enable(struct irq_data *data)
{
    desc->irq_data.chip->irq_unmask(data);
}

default_disable(struct irq_data *data)
{
    if (!delay_disable(data))
        desc->irq_data.chip->irq_mask(data);
}

default_ack(struct irq_data *data)
{
    chip->irq_ack(data);
}

default_mask_ack(struct irq_data *data)
{
    if (chip->irq_mask_ack) {
        chip->irq_mask_ack(data);
    } else {
        chip->irq_mask(data);
        chip->irq_ack(data);
    }
}

noop(struct irq_data *data)
{
}

預設流處理程式實現

預設電平 IRQ 流處理程式

handle_level_irq 為電平觸發中斷提供通用實現。

實現以下控制流(簡化摘錄):

desc->irq_data.chip->irq_mask_ack();
handle_irq_event(desc->action);
desc->irq_data.chip->irq_unmask();
預設快速 EOI IRQ 流處理程式

handle_fasteoi_irq 為僅在處理程式結束時需要 EOI 的中斷提供通用實現。

實現以下控制流(簡化摘錄):

handle_irq_event(desc->action);
desc->irq_data.chip->irq_eoi();
預設邊沿 IRQ 流處理程式

handle_edge_irq 為邊沿觸發中斷提供通用實現。

實現以下控制流(簡化摘錄):

if (desc->status & running) {
    desc->irq_data.chip->irq_mask_ack();
    desc->status |= pending | masked;
    return;
}
desc->irq_data.chip->irq_ack();
desc->status |= running;
do {
    if (desc->status & masked)
        desc->irq_data.chip->irq_unmask();
    desc->status &= ~pending;
    handle_irq_event(desc->action);
} while (desc->status & pending);
desc->status &= ~running;
預設簡單 IRQ 流處理程式

handle_simple_irq 為簡單中斷提供通用實現。

注意

簡單流處理程式不呼叫任何處理程式/晶片原語。

實現以下控制流(簡化摘錄):

handle_irq_event(desc->action);
預設每 CPU 流處理程式

handle_percpu_irq 為每 CPU 中斷提供通用實現。

每 CPU 中斷僅在 SMP 上可用,處理程式提供了一個沒有鎖定的簡化版本。

實現以下控制流(簡化摘錄):

if (desc->irq_data.chip->irq_ack)
    desc->irq_data.chip->irq_ack();
handle_irq_event(desc->action);
if (desc->irq_data.chip->irq_eoi)
    desc->irq_data.chip->irq_eoi();
EOI 邊沿 IRQ 流處理程式

handle_edge_eoi_irq 提供了一個邊沿處理程式的異常情況,它僅用於馴服 powerpc/cell 上一個嚴重損壞的 irq 控制器。

不良 IRQ 流處理程式

handle_bad_irq 用於沒有實際處理程式分配的偽中斷。

怪癖和最佳化

通用函式旨在用於“乾淨”的架構和晶片,這些架構和晶片沒有平臺特定的 IRQ 處理怪癖。如果架構需要在“流”級別實現怪癖,則可以透過覆蓋高階 irq 流處理程式來實現。

延遲中斷停用

此每中斷可選功能由 Russell King 在 ARM 中斷實現中引入,當呼叫 disable_irq() 時,它不會在硬體級別遮蔽中斷。中斷保持啟用狀態,並在發生中斷事件時在流處理程式中遮蔽。這可以防止在硬體級別停用中斷時,硬體不儲存邊沿中斷事件而丟失邊沿中斷。當 IRQ_DISABLED 標誌設定時中斷到來時,中斷在硬體級別被遮蔽,並且 IRQ_PENDING 位被設定。當透過 enable_irq() 重新啟用中斷時,會檢查 pending 位,如果設定,則透過硬體或軟體重發機制重新發送中斷。(如果您想使用延遲中斷停用功能並且您的硬體無法重新觸發中斷,則需要啟用 CONFIG_HARDIRQS_SW_RESEND。)延遲中斷停用不可配置。

晶片級硬體封裝

晶片級硬體描述符結構 irq_chip 包含所有直接與晶片相關的功能,這些功能可以被 irq 流實現使用。

  • irq_ack

  • irq_mask_ack - 可選,建議用於效能

  • irq_mask

  • irq_unmask

  • irq_eoi - 可選,EOI 流處理程式必需

  • irq_retrigger - 可選

  • irq_set_type - 可選

  • irq_set_wake - 可選

這些原語嚴格按照其字面意思:ack 表示 ACK,masking 表示遮蔽 IRQ 線等。流處理程式(或多個處理程式)負責使用這些低階功能的基本單元。

__do_IRQ 入口點

原始實現 __do_IRQ() 是所有型別中斷的替代入口點。它不再存在。

此處理程式被證明不適用於所有中斷硬體,因此已使用針對邊沿/電平/簡單/每CPU 中斷的拆分功能重新實現。這不僅是功能最佳化,還縮短了中斷的程式碼路徑。

SMP 上的鎖定

晶片暫存器的鎖定由定義晶片原語的架構負責。每個中斷結構透過 desc->lock 受通用層保護。

通用中斷晶片

為了避免重複的 IRQ 晶片實現,核心提供了可配置的通用中斷晶片實現。開發人員在自己以略微不同的方式實現相同功能之前,應仔細檢查通用晶片是否符合其需求。

void irq_gc_noop(struct irq_data *d)

空操作函式

引數

struct irq_data *d

irq_data

void irq_gc_mask_disable_reg(struct irq_data *d)

透過停用暫存器遮蔽晶片

引數

struct irq_data *d

irq_data

描述

晶片有獨立的啟用/停用暫存器,而不是單個遮蔽暫存器。

void irq_gc_mask_set_bit(struct irq_data *d)

透過在遮蔽暫存器中設定位來遮蔽晶片

引數

struct irq_data *d

irq_data

描述

晶片有一個單一的遮蔽暫存器。該暫存器的值被快取並受 gc->lock 保護。

void irq_gc_mask_clr_bit(struct irq_data *d)

透過在遮蔽暫存器中清除位來遮蔽晶片

引數

struct irq_data *d

irq_data

描述

晶片有一個單一的遮蔽暫存器。該暫存器的值被快取並受 gc->lock 保護。

void irq_gc_unmask_enable_reg(struct irq_data *d)

透過啟用暫存器解除晶片遮蔽

引數

struct irq_data *d

irq_data

描述

晶片有獨立的啟用/停用暫存器,而不是單個遮蔽暫存器。

void irq_gc_ack_set_bit(struct irq_data *d)

透過設定位確認掛起中斷

引數

struct irq_data *d

irq_data

void irq_gc_mask_disable_and_ack_set(struct irq_data *d)

遮蔽並確認掛起中斷

引數

struct irq_data *d

irq_data

描述

irq_mask_ack 方法的通用實現適用於具有獨立啟用/停用暫存器而非單個遮蔽暫存器的晶片,並且掛起中斷透過設定位來確認。

注意

這是目前唯一使用的排列組合。如果需要其他排列組合,應在此處新增類似的通用函式。

int irq_gc_set_wake(struct irq_data *d, unsigned int on)

設定/清除中斷的喚醒位

引數

struct irq_data *d

irq_data

unsigned int on

指示是否應設定或清除喚醒位

描述

對於喚醒掛起功能未在單獨暫存器中配置,且喚醒活動狀態僅儲存在位掩碼中的晶片。

struct irq_chip_generic *irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base, void __iomem *reg_base, irq_flow_handler_t handler)

分配通用晶片並初始化

引數

const char *name

irq 晶片的名稱

int num_ct

與此相關的 irq_chip_type 例項數量

unsigned int irq_base

此晶片的中斷基數

void __iomem *reg_base

暫存器基地址(虛擬)

irq_flow_handler_t handler

與此晶片關聯的預設流處理程式

描述

返回一個已初始化的 irq_chip_generic 結構。晶片預設為主要(索引 0)的 irq_chip_typehandler

int irq_domain_alloc_generic_chips(struct irq_domain *d, const struct irq_domain_chip_generic_info *info)

為 irq 域分配通用晶片

引數

struct irq_domain *d

要分配晶片的 irq 域

const struct irq_domain_chip_generic_info *info

通用晶片資訊

返回

成功返回 0,失敗返回負錯誤碼

void irq_domain_remove_generic_chips(struct irq_domain *d)

從 irq 域中移除通用晶片

引數

struct irq_domain *d

要移除通用晶片的 irq 域

int __irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, int num_ct, const char *name, irq_flow_handler_t handler, unsigned int clr, unsigned int set, enum irq_gc_flags gcflags)

為 irq 域分配通用晶片

引數

struct irq_domain *d

要分配晶片的 irq 域

int irqs_per_chip

每個晶片處理的中斷數量(最大 32)

int num_ct

與此相關的 irq_chip_type 例項數量

const char *name

irq 晶片的名稱

irq_flow_handler_t handler

與這些晶片關聯的預設流處理程式

unsigned int clr

在對映函式中要清除的 IRQ_* 位

unsigned int set

在對映函式中要設定的 IRQ_* 位

enum irq_gc_flags gcflags

通用晶片特定設定標誌

struct irq_chip_generic *irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq)

獲取 hw_irq 的通用晶片指標

引數

struct irq_domain *d

irq 域指標

unsigned int hw_irq

硬體中斷號,相對於中斷域本地

void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, enum irq_gc_flags flags, unsigned int clr, unsigned int set)

使用通用晶片設定一系列中斷

引數

struct irq_chip_generic *gc

包含所有資料的通用 irq 晶片

u32 msk

包含要初始化 irq 的位掩碼,相對於 gc->irq_base

enum irq_gc_flags flags

初始化標誌

unsigned int clr

要清除的 IRQ_* 位

unsigned int set

要設定的 IRQ_* 位

描述

設定從 gc->irq_base 開始最多 32 箇中斷。注意,這將所有中斷初始化為主 irq_chip_type 及其關聯的處理程式。

int irq_setup_alt_chip(struct irq_data *d, unsigned int type)

切換到替代晶片

引數

struct irq_data *d

此中斷的 irq_data

unsigned int type

要初始化的流型別

描述

只能從 chip->irq_set_type() 回撥中呼叫。

void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk, unsigned int clr, unsigned int set)

移除晶片

引數

struct irq_chip_generic *gc

包含所有資料的通用 irq 晶片

u32 msk

包含要初始化 irq 的位掩碼,相對於 gc->irq_base

unsigned int clr

要清除的 IRQ_* 位

unsigned int set

要設定的 IRQ_* 位

描述

移除從 gc->irq_base 開始最多 32 箇中斷。

結構體

本章包含通用 IRQ 層中使用的結構的自動生成文件。

struct irq_common_data

所有 irqchip 共享的每個 irq 資料

定義:

struct irq_common_data {
    unsigned int            __private state_use_accessors;
#ifdef CONFIG_NUMA;
    unsigned int            node;
#endif;
    void *handler_data;
    struct msi_desc         *msi_desc;
#ifdef CONFIG_SMP;
    cpumask_var_t affinity;
#endif;
#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK;
    cpumask_var_t effective_affinity;
#endif;
#ifdef CONFIG_GENERIC_IRQ_IPI;
    unsigned int            ipi_offset;
#endif;
};

成員

state_use_accessors

irq 晶片函式的狀態資訊。使用訪問器函式處理它

node

用於平衡的節點索引

handler_data

用於 irq_chip 方法的每個 IRQ 資料

msi_desc

MSI 描述符

affinity

SMP 上的 IRQ 親和性。如果這是 IPI 相關 irq,則這是可以傳送 IPI 的 CPU 掩碼。

effective_affinity

SMP 上的有效 IRQ 親和性,因為某些 irq 晶片不允許多 CPU 目標。是 affinity 的一個子集。

ipi_offset

affinity 中第一個 IPI 目標 CPU 的偏移量。可選。

struct irq_data

傳遞給晶片函式的每個 irq 晶片資料

定義:

struct irq_data {
    u32 mask;
    unsigned int            irq;
    irq_hw_number_t hwirq;
    struct irq_common_data  *common;
    struct irq_chip         *chip;
    struct irq_domain       *domain;
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY;
    struct irq_data         *parent_data;
#endif;
    void *chip_data;
};

成員

mask

用於訪問晶片暫存器的預計算位掩碼

irq

中斷號

hwirq

硬體中斷號,相對於中斷域本地

common

指向所有 irqchip 共享的資料

chip

低階中斷硬體訪問

domain

中斷轉換域;負責硬體中斷號和 Linux 中斷號之間的對映。

parent_data

指向父 struct irq_data 的指標,以支援層次結構 irq_domain

chip_data

用於晶片方法的平臺特定每個晶片私有資料,以允許共享晶片實現

struct irq_chip

硬體中斷晶片描述符

定義:

struct irq_chip {
    const char      *name;
    unsigned int    (*irq_startup)(struct irq_data *data);
    void (*irq_shutdown)(struct irq_data *data);
    void (*irq_enable)(struct irq_data *data);
    void (*irq_disable)(struct irq_data *data);
    void (*irq_ack)(struct irq_data *data);
    void (*irq_mask)(struct irq_data *data);
    void (*irq_mask_ack)(struct irq_data *data);
    void (*irq_unmask)(struct irq_data *data);
    void (*irq_eoi)(struct irq_data *data);
    int (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
    int (*irq_retrigger)(struct irq_data *data);
    int (*irq_set_type)(struct irq_data *data, unsigned int flow_type);
    int (*irq_set_wake)(struct irq_data *data, unsigned int on);
    void (*irq_bus_lock)(struct irq_data *data);
    void (*irq_bus_sync_unlock)(struct irq_data *data);
#ifdef CONFIG_DEPRECATED_IRQ_CPU_ONOFFLINE;
    void (*irq_cpu_online)(struct irq_data *data);
    void (*irq_cpu_offline)(struct irq_data *data);
#endif;
    void (*irq_suspend)(struct irq_data *data);
    void (*irq_resume)(struct irq_data *data);
    void (*irq_pm_shutdown)(struct irq_data *data);
    void (*irq_calc_mask)(struct irq_data *data);
    void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
    int (*irq_request_resources)(struct irq_data *data);
    void (*irq_release_resources)(struct irq_data *data);
    void (*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg);
    void (*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg);
    int (*irq_get_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool *state);
    int (*irq_set_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool state);
    int (*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);
    void (*ipi_send_single)(struct irq_data *data, unsigned int cpu);
    void (*ipi_send_mask)(struct irq_data *data, const struct cpumask *dest);
    int (*irq_nmi_setup)(struct irq_data *data);
    void (*irq_nmi_teardown)(struct irq_data *data);
    void (*irq_force_complete_move)(struct irq_data *data);
    unsigned long   flags;
};

成員

name

用於 /proc/interrupts 的名稱

irq_startup

啟動中斷(如果為 NULL,則預設為 ->enable)

irq_shutdown

關閉中斷(如果為 NULL,則預設為 ->disable)

irq_enable

啟用中斷(如果為 NULL,則預設為 chip->unmask)

irq_disable

停用中斷

irq_ack

新中斷的開始

irq_mask

遮蔽中斷源

irq_mask_ack

確認並遮蔽中斷源

irq_unmask

解除中斷源的遮蔽

irq_eoi

中斷結束

irq_set_affinity

在 SMP 機器上設定 CPU 親和性。如果 force 引數為 true,則它告訴驅動程式無條件應用親和性設定。不需要對提供的親和性掩碼進行健全性檢查。這用於 CPU 熱插拔,其中目標 CPU 尚未在 cpu_online_mask 中設定。

irq_retrigger

向 CPU 重新發送 IRQ

irq_set_type

設定 IRQ 的流型別(IRQ_TYPE_LEVEL/等)

irq_set_wake

啟用/停用 IRQ 的電源管理喚醒功能

irq_bus_lock

鎖定對慢速匯流排(i2c)晶片訪問的函式

irq_bus_sync_unlock

同步和解鎖慢速匯流排(i2c)晶片的函式

irq_cpu_online

為輔助 CPU 配置中斷源

irq_cpu_offline

取消配置輔助 CPU 的中斷源

irq_suspend

當安裝了一個或多箇中斷時,從核心程式碼在掛起時為每個晶片呼叫一次的函式

irq_resume

當安裝了一個或多箇中斷時,從核心程式碼在恢復時為每個晶片呼叫一次的函式

irq_pm_shutdown

從核心程式碼在關閉時為每個晶片呼叫一次的函式

irq_calc_mask

可選函式,用於為特殊情況設定 irq_data.mask

irq_print_chip

可選,用於在 show_interrupts 中列印特殊的晶片資訊

irq_request_resources

可選,用於在呼叫與此 irq 相關的任何其他回撥之前請求資源

irq_release_resources

可選,用於釋放透過 irq_request_resources 獲取的資源

irq_compose_msi_msg

可選,用於為 MSI 組合訊息內容

irq_write_msi_msg

可選,用於為 MSI 寫入訊息內容

irq_get_irqchip_state

返回中斷的內部狀態

irq_set_irqchip_state

設定中斷的內部狀態

irq_set_vcpu_affinity

可選,用於在虛擬機器中定位 vCPU

ipi_send_single

向目標 CPU 傳送單個 IPI

ipi_send_mask

向 cpumask 中的目標 CPU 傳送 IPI

irq_nmi_setup

在啟用 NMI 之前從核心程式碼呼叫的函式

irq_nmi_teardown

在停用 NMI 之後從核心程式碼呼叫的函式

irq_force_complete_move

可選函式,用於強制完成掛起的中斷移動

flags

晶片特定標誌

struct irq_chip_regs

結構體 irq_gci 的暫存器偏移

定義:

struct irq_chip_regs {
    unsigned long           enable;
    unsigned long           disable;
    unsigned long           mask;
    unsigned long           ack;
    unsigned long           eoi;
    unsigned long           type;
};

成員

enable

相對於 reg_base 的啟用暫存器偏移

disable

相對於 reg_base 的停用暫存器偏移

mask

相對於 reg_base 的遮蔽暫存器偏移

ack

相對於 reg_base 的確認暫存器偏移

eoi

相對於 reg_base 的 Eoi 暫存器偏移

type

相對於 reg_base 的型別配置暫存器偏移

struct irq_chip_type

流型別的通用中斷晶片例項

定義:

struct irq_chip_type {
    struct irq_chip         chip;
    struct irq_chip_regs    regs;
    irq_flow_handler_t handler;
    u32 type;
    u32 mask_cache_priv;
    u32 *mask_cache;
};

成員

chip

提供回撥的實際中斷晶片

regs

此晶片的暫存器偏移

handler

與此晶片關聯的流處理程式

type

晶片可以處理這些流型別

mask_cache_priv

晶片型別私有的快取遮蔽暫存器

mask_cache

指向快取遮蔽暫存器的指標

描述

當需要為不同的流型別實現不同的功能和暫存器偏移時,一個 irq_generic_chip 可以有多個 irq_chip_type 例項。

struct irq_chip_generic

通用 irq 晶片資料結構

定義:

struct irq_chip_generic {
    raw_spinlock_t lock;
    void __iomem            *reg_base;
    u32 (*reg_readl)(void __iomem *addr);
    void (*reg_writel)(u32 val, void __iomem *addr);
    void (*suspend)(struct irq_chip_generic *gc);
    void (*resume)(struct irq_chip_generic *gc);
    unsigned int            irq_base;
    unsigned int            irq_cnt;
    u32 mask_cache;
    u32 wake_enabled;
    u32 wake_active;
    unsigned int            num_ct;
    void *private;
    unsigned long           installed;
    unsigned long           unused;
    struct irq_domain       *domain;
    struct list_head        list;
    struct irq_chip_type    chip_types[];
};

成員

lock

保護暫存器和快取資料訪問的鎖

reg_base

暫存器基地址(虛擬)

reg_readl

備用 I/O 訪問器(如果為 NULL,則預設為 readl)

reg_writel

備用 I/O 訪問器(如果為 NULL,則預設為 writel)

suspend

當晶片未被使用時,從核心程式碼在掛起時為每個晶片呼叫一次的函式;可用於處理晶片細節,而無需 irq_chip::suspend

resume

當晶片未被使用時,從核心程式碼在恢復時為每個晶片呼叫一次的函式;可用於處理晶片細節,而無需 irq_chip::suspend

irq_base

此晶片的中斷基數

irq_cnt

此晶片處理的中斷數量

mask_cache

所有晶片型別之間共享的快取遮蔽暫存器

wake_enabled

中斷可以從掛起狀態喚醒

wake_active

中斷被標記為從掛起狀態喚醒的源

num_ct

可用 irq_chip_type 例項的數量(通常為 1)

private

用於非通用晶片回撥的私有資料

installed

表示已安裝中斷的位域

unused

表示未使用中斷的位域

domain

irq 域指標

list

例項跟蹤的列表頭

chip_types

中斷 irq_chip_types 陣列

描述

請注意,irq_chip_generic 可以有多個 irq_chip_type 實現,這些實現可以關聯到 irq_chip_generic 例項的特定 irq 線。這允許在我們需要為 irq_chip_generic 例項實現不同的流機制(電平/邊沿)時,共享和保護狀態。

enum irq_gc_flags

通用 irq 晶片的初始化標誌

常量

IRQ_GC_INIT_MASK_CACHE

透過讀取掩碼暫存器初始化 mask_cache

IRQ_GC_INIT_NESTED_LOCK

為需要呼叫父 irq 上的 irq_set_wake() 的 irq 晶片設定鎖類別為巢狀。通常是 GPIO 實現

IRQ_GC_MASK_CACHE_PER_TYPE

掩碼快取是晶片型別私有的

IRQ_GC_NO_MASK

不計算 irq_data->mask

IRQ_GC_BE_IO

使用大端暫存器訪問(預設:小端)

struct irq_domain_chip_generic_info

通用晶片資訊結構

定義:

struct irq_domain_chip_generic_info {
    const char              *name;
    irq_flow_handler_t handler;
    unsigned int            irqs_per_chip;
    unsigned int            num_ct;
    unsigned int            irq_flags_to_clear;
    unsigned int            irq_flags_to_set;
    enum irq_gc_flags       gc_flags;
    int (*init)(struct irq_chip_generic *gc);
    void (*exit)(struct irq_chip_generic *gc);
};

成員

name

通用中斷晶片的名稱

handler

通用中斷晶片使用的中斷處理程式

irqs_per_chip

每個晶片處理的中斷數量(最大 32)

num_ct

與每個晶片關聯的 irq_chip_type 例項數量

irq_flags_to_clear

在對映函式中要清除的 IRQ_* 位

irq_flags_to_set

在對映函式中要設定的 IRQ_* 位

gc_flags

通用晶片特定設定標誌

init

在每個晶片建立時呼叫的函式。允許進行一些額外的晶片初始化。

exit

在每個晶片銷燬時呼叫的函式。允許進行一些晶片清理操作。

struct irqaction

每個中斷動作描述符

定義:

struct irqaction {
    irq_handler_t handler;
    void *dev_id;
    void __percpu           *percpu_dev_id;
    struct irqaction        *next;
    irq_handler_t thread_fn;
    struct task_struct      *thread;
    struct irqaction        *secondary;
    unsigned int            irq;
    unsigned int            flags;
    unsigned long           thread_flags;
    unsigned long           thread_mask;
    const char              *name;
    struct proc_dir_entry   *dir;
};

成員

handler

中斷處理函式

dev_id

用於識別裝置的 cookie

percpu_dev_id

用於識別裝置的 cookie

next

指向共享中斷的下一個 irqaction 的指標

thread_fn

執行緒化中斷的中斷處理函式

thread

執行緒化中斷的執行緒指標

secondary

指向輔助 irqaction 的指標(強制執行緒化)

irq

中斷號

flags

flags(參見上面的 IRQF_*)

thread_flags

thread 相關的標誌

thread_mask

用於跟蹤 thread 活動的位掩碼

name

裝置名稱

dir

指向 proc/irq/NN/name 條目的指標

int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)

為中斷線新增處理程式

引數

unsigned int irq

要分配的中斷線

irq_handler_t handler

中斷髮生時要呼叫的函式。執行緒化中斷的主處理程式。如果為 NULL,則安裝預設的主處理程式。

unsigned long flags

處理標誌

const char *name

生成此中斷的裝置名稱

void *dev

傳遞給處理函式的 cookie

描述

此呼叫分配中斷並建立處理程式;有關詳細資訊,請參閱 request_threaded_irq() 的文件。

struct irq_affinity_notify

IRQ 親和性更改通知的上下文

定義:

struct irq_affinity_notify {
    unsigned int irq;
    struct kref kref;
    struct work_struct work;
    void (*notify)(struct irq_affinity_notify *, const cpumask_t *mask);
    void (*release)(struct kref *ref);
};

成員

irq

通知適用的中斷

kref

引用計數,供內部使用

work

工作項,供內部使用

notify

更改時要呼叫的函式。這將在程序上下文中呼叫。

release

釋放時要呼叫的函式。這將在程序上下文中呼叫。一旦註冊,結構只能在此函式被呼叫或之後才能釋放。

struct irq_affinity

自動 irq 親和性分配的描述

定義:

struct irq_affinity {
    unsigned int    pre_vectors;
    unsigned int    post_vectors;
    unsigned int    nr_sets;
    unsigned int    set_size[IRQ_AFFINITY_MAX_SETS];
    void (*calc_sets)(struct irq_affinity *, unsigned int nvecs);
    void *priv;
};

成員

pre_vectors

不要將親和性應用於 MSI(-X) 向量空間開頭的 pre_vectors

post_vectors

不要將親和性應用於 MSI(-X) 向量空間末尾的 post_vectors

nr_sets

需要親和性擴散的中斷集數量

set_size

儲存每個中斷集大小的陣列

calc_sets

計算中斷集數量和大小的回撥函式

priv

calc_sets 使用的私有資料,通常是指向驅動程式/裝置特定資料的指標。

struct irq_affinity_desc

中斷親和性描述符

定義:

struct irq_affinity_desc {
    struct cpumask  mask;
    unsigned int    is_managed : 1;
};

成員

mask

用於儲存親和性分配的 cpumask

is_managed

如果中斷由內部管理,則為 1

int irq_update_affinity_hint(unsigned int irq, const struct cpumask *m)

更新親和性提示

引數

unsigned int irq

要更新的中斷

const struct cpumask *m

cpumask 指標(NULL 表示清除提示)

描述

更新親和性提示,但不更改中斷的親和性。

int irq_set_affinity_and_hint(unsigned int irq, const struct cpumask *m)

更新親和性提示並將提供的 cpumask 應用於中斷

引數

unsigned int irq

要更新的中斷

const struct cpumask *m

cpumask 指標(NULL 表示清除提示)

描述

更新親和性提示,如果 m 不為 NULL,則將其應用於該中斷的親和性。

提供的公共函式

本章包含已匯出核心 API 函式的自動生成文件。

bool synchronize_hardirq(unsigned int irq)

等待掛起的硬 IRQ 處理程式(在其他 CPU 上)

引數

unsigned int irq

要等待的中斷號

描述

此函式在返回之前等待此中斷的任何掛起硬 IRQ 處理程式完成。如果您在持有 IRQ 處理程式可能需要的資源時使用此函式,則會發生死鎖。它不考慮相關的執行緒化處理程式。

請勿在關閉場景中使用此功能,在這些場景中您必須確保所有部分(硬中斷和執行緒化處理程式)都已完成。

此函式可以——小心地——從 IRQ 上下文呼叫。

它不檢查中斷是否在硬體級別正在進行中但尚未服務,因為這可能會在停用中斷且中斷的目標 CPU 是當前 CPU 時導致死鎖。

返回

如果執行緒化處理程式處於活動狀態,則為 false。

void synchronize_irq(unsigned int irq)

等待掛起的 IRQ 處理程式(在其他 CPU 上)

引數

unsigned int irq

要等待的中斷號

描述

此函式在返回之前等待此中斷的任何掛起 IRQ 處理程式完成。如果您在持有 IRQ 處理程式可能需要的資源時使用此函式,則會發生死鎖。

只能從可搶佔程式碼中呼叫,因為當中斷執行緒與 irq 關聯時,它可能會休眠。

它(當 irq 晶片支援該方法時)可選地確保中斷在任何 CPU 上都沒有掛起並等待服務。

int irq_can_set_affinity(unsigned int irq)

檢查給定 irq 的親和性是否可以設定

引數

unsigned int irq

要檢查的中斷

bool irq_can_set_affinity_usr(unsigned int irq)

檢查是否可以從使用者空間設定 irq 的親和性

引數

unsigned int irq

要檢查的中斷

描述

與上面的 irq_can_set_affinity() 類似,但額外檢查 AFFINITY_MANAGED 標誌。

void irq_set_thread_affinity(struct irq_desc *desc)

通知 irq 執行緒調整親和性

引數

struct irq_desc *desc

親和性已更改的 irq 描述符

描述

只需設定 IRQTF_AFFINITY 並將親和性設定委託給中斷執行緒本身。我們不能在此處呼叫 set_cpus_allowed_ptr(),因為我們持有 desc->lock,並且此程式碼可以從硬中斷上下文呼叫。

int irq_update_affinity_desc(unsigned int irq, struct irq_affinity_desc *affinity)

更新中斷的親和性管理

引數

unsigned int irq

要更新的中斷號

struct irq_affinity_desc *affinity

指向親和性描述符的指標

描述

此介面可用於配置已分配中斷的親和性管理。

在何時使用它存在某些限制——嘗試在核心配置為通用 IRQ 保留模式(在 config GENERIC_IRQ_RESERVATION_MODE 中)時使用它將失敗,因為它可能與託管/非託管中斷計數衝突。此外,嘗試在已啟動或已配置為託管的中斷上使用它也將失敗,因為這些意味著無效的初始狀態或重複初始化。

int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)

設定給定 irq 的 irq 親和性

引數

unsigned int irq

要設定親和性的中斷

const struct cpumask *cpumask

cpumask

描述

如果 cpumask 不包含線上 CPU,則失敗

int irq_force_affinity(unsigned int irq, const struct cpumask *cpumask)

強制給定 irq 的 irq 親和性

引數

unsigned int irq

要設定親和性的中斷

const struct cpumask *cpumask

cpumask

描述

與 irq_set_affinity 相同,但不檢查掩碼與線上 CPU 的匹配。

僅用於低階 CPU 熱插拔程式碼,我們需要在 CPU 上線之前使每個 CPU 中斷具有親和性。

int irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify)

控制 IRQ 親和性更改通知

引數

unsigned int irq

要啟用/停用通知的中斷

struct irq_affinity_notify *notify

通知上下文,或 NULL 以停用通知。函式指標必須已初始化;其他欄位將由此函式初始化。

描述

必須在程序上下文中呼叫。通知只能在 IRQ 分配後啟用,並且必須在使用 free_irq() 釋放 IRQ 之前停用。

int irq_set_vcpu_affinity(unsigned int irq, void *vcpu_info)

設定中斷的 vcpu 親和性

引數

unsigned int irq

要設定親和性的中斷號

void *vcpu_info

vCPU 特定資料或指向 percpu_devid 中斷的 vCPU 特定資料每CPU 陣列的指標

描述

此函式使用 vCPU 特定資料來設定 irq 的 vCPU 親和性。vCPU 特定資料從外部傳遞,例如 KVM。一個示例程式碼路徑如下:KVM -> IOMMU -> irq_set_vcpu_affinity()

void disable_irq_nosync(unsigned int irq)

停用 irq 而不等待

引數

unsigned int irq

要停用的中斷

描述

停用選定的中斷線。停用和啟用是巢狀的。與 disable_irq() 不同,此函式在返回之前不確保 IRQ 處理程式的現有例項已完成。

此函式可以在 IRQ 上下文呼叫。

void disable_irq(unsigned int irq)

停用 irq 並等待完成

引數

unsigned int irq

要停用的中斷

描述

停用選定的中斷線。啟用和停用是巢狀的。

此函式在返回之前等待此中斷的任何掛起 IRQ 處理程式完成。如果您在持有 IRQ 處理程式可能需要的資源時使用此函式,則會發生死鎖。

只能從可搶佔程式碼中呼叫,因為當中斷執行緒與 irq 關聯時,它可能會休眠。

bool disable_hardirq(unsigned int irq)

停用 irq 並等待硬中斷完成

引數

unsigned int irq

要停用的中斷

描述

停用選定的中斷線。啟用和停用是巢狀的。

此函式在返回之前等待此中斷的任何掛起硬 IRQ 處理程式完成。如果您在持有硬 IRQ 處理程式可能需要的資源時使用此函式,則會發生死鎖。

當用於從原子上下文樂觀地停用中斷時,必須檢查返回值。

此函式可以——小心地——從 IRQ 上下文呼叫。

返回

如果執行緒化處理程式處於活動狀態,則為 false。

void disable_nmi_nosync(unsigned int irq)

停用 nmi 而不等待

引數

unsigned int irq

要停用的中斷

描述

停用選定的中斷線。停用和啟用是巢狀的。

要停用的中斷必須透過 request_nmi 請求。與 disable_nmi() 不同,此函式在返回之前不確保 IRQ 處理程式的現有例項已完成。

void enable_irq(unsigned int irq)

啟用 irq 處理

引數

unsigned int irq

要啟用的中斷

描述

撤銷一次 disable_irq() 呼叫的效果。如果這與最後一次停用匹配,則重新啟用此 IRQ 線上中斷的處理。

此函式僅當 desc->irq_data.chip->bus_lockdesc->chip->bus_sync_unlock 為 NULL 時才能從 IRQ 上下文呼叫!

void enable_nmi(unsigned int irq)

啟用 nmi 處理

引數

unsigned int irq

要啟用的中斷

描述

要啟用的中斷必須透過 request_nmi 請求。撤銷一次 disable_nmi() 呼叫的效果。如果這與最後一次停用匹配,則重新啟用此 IRQ 線上中斷的處理。

int irq_set_irq_wake(unsigned int irq, unsigned int on)

控制 irq 電源管理喚醒

引數

unsigned int irq

要控制的中斷

unsigned int on

啟用/停用電源管理喚醒

描述

啟用/停用電源管理喚醒模式,該模式預設停用。啟用和停用必須匹配,就像它們與非喚醒模式支援匹配一樣。

喚醒模式允許此 IRQ 將系統從“掛起到 RAM”等睡眠狀態喚醒。

注意

irq 啟用/停用狀態與 irq 喚醒的啟用/停用狀態完全正交。一個 irq 可以透過 disable_irq() 停用,但只要 irq 啟用了喚醒功能,它仍然可以喚醒系統。如果這不成立,則需要調查底層 irq 晶片和相關驅動程式。

void irq_wake_thread(unsigned int irq, void *dev_id)

喚醒由 dev_id 標識的動作的 irq 執行緒

引數

unsigned int irq

中斷線

void *dev_id

應喚醒其執行緒的裝置標識

const void *free_irq(unsigned int irq, void *dev_id)

釋放用 request_irq 分配的中斷

引數

unsigned int irq

要釋放的中斷線

void *dev_id

要釋放的裝置標識

描述

移除中斷處理程式。處理程式被移除,如果中斷線不再被任何驅動程式使用,則將其停用。在共享 IRQ 上,呼叫者必須確保在呼叫此函式之前,它所驅動的卡上的中斷已停用。函式在針對此 IRQ 的任何正在執行的中斷完成之前不會返回。

此函式不得從中斷上下文呼叫。

返回傳遞給 request_irqdevname 引數。

int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long irqflags, const char *devname, void *dev_id)

分配中斷線

引數

unsigned int irq

要分配的中斷線

irq_handler_t handler

中斷髮生時要呼叫的函式。執行緒化中斷的主處理程式。如果 handler 為 NULL 且 thread_fn 不為 NULL,則安裝預設的主處理程式。

irq_handler_t thread_fn

從 irq 處理程式執行緒呼叫的函式。如果為 NULL,則不建立 irq 執行緒。

unsigned long irqflags

中斷型別標誌

const char *devname

宣告此裝置的 ASCII 名稱

void *dev_id

傳遞迴處理函式的一個 cookie

描述

此呼叫分配中斷資源並啟用中斷線和 IRQ 處理。從呼叫此函式的那一刻起,您的處理函式可能會被呼叫。由於您的處理函式必須清除板卡引發的任何中斷,因此您必須注意以正確的順序初始化硬體和設定中斷處理程式。

如果您想為您的裝置設定執行緒化 irq 處理程式,則需要提供 handlerthread_fnhandler 仍然在硬中斷上下文中呼叫,並且必須檢查中斷是否源自裝置。如果是,它需要停用裝置上的中斷並返回 IRQ_WAKE_THREAD,這將喚醒處理程式執行緒並執行 thread_fn。這種分離的處理程式設計對於支援共享中斷是必要的。

dev_id 必須全域性唯一。通常,裝置資料結構的地址用作 cookie。由於處理程式會收到此值,因此使用它是有意義的。

如果您的中斷是共享的,則必須傳遞一個非 NULL 的 dev_id,因為在釋放中斷時需要它。

標誌

IRQF_SHARED 中斷是共享的 IRQF_TRIGGER_* 指定活動邊沿或電平 IRQF_ONESHOT 在中斷線被遮蔽的情況下執行 thread_fn

int request_any_context_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev_id)

分配中斷線

引數

unsigned int irq

要分配的中斷線

irq_handler_t handler

當 IRQ 發生時呼叫的函式。用於執行緒化中斷的執行緒化處理程式。

unsigned long flags

中斷型別標誌

const char *name

宣告此裝置的 ASCII 名稱

void *dev_id

傳遞迴處理函式的一個 cookie

描述

此呼叫分配中斷資源,並啟用中斷線和 IRQ 處理。它根據上下文選擇硬中斷(hardirq)或執行緒化處理方法。

返回

失敗時,返回負值。成功時,返回 IRQC_IS_HARDIRQ 或 IRQC_IS_NESTED。

int request_nmi(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *name, void *dev_id)

分配一條用於 NMI 遞送的中斷線

引數

unsigned int irq

要分配的中斷線

irq_handler_t handler

當 IRQ 發生時呼叫的函式。用於執行緒化中斷的執行緒化處理程式。

unsigned long irqflags

中斷型別標誌

const char *name

宣告此裝置的 ASCII 名稱

void *dev_id

傳遞迴處理函式的一個 cookie

描述

此呼叫分配中斷資源,並啟用中斷線和 IRQ 處理。它將 IRQ 線設定為作為 NMI 處理。

遞送 NMI 的中斷線不能共享,且 IRQ 處理不能執行緒化。

請求用於 NMI 遞送的中斷線必須生成每個 CPU 的中斷,並且自動啟用設定必須被停用。

dev_id 必須全域性唯一。通常,裝置資料結構的地址用作 cookie。由於處理程式會收到此值,因此使用它是有意義的。

如果中斷線不能用於遞送 NMI,函式將失敗並返回負值。

bool irq_percpu_is_enabled(unsigned int irq)

檢查每個 CPU 中斷是否已啟用

引數

unsigned int irq

要檢查的 Linux irq 號

描述

必須從不可遷移的上下文呼叫。返回當前 CPU 上每個 CPU 中斷的啟用狀態。

void free_percpu_irq(unsigned int irq, void __percpu *dev_id)

釋放用 request_percpu_irq 分配的中斷

引數

unsigned int irq

要釋放的中斷線

void __percpu *dev_id

要釋放的裝置標識

描述

移除一個每個 CPU 中斷處理程式。處理程式被移除,但中斷線並未停用。在呼叫此函式之前,必須在每個 CPU 上完成此操作。該函式只有在所有為此 IRQ 正在執行的中斷完成後才會返回。

此函式不得從中斷上下文呼叫。

int setup_percpu_irq(unsigned int irq, struct irqaction *act)

設定一個每個 CPU 中斷

引數

unsigned int irq

要設定的中斷線

struct irqaction *act

中斷的 irqaction

描述

用於在早期啟動過程中靜態設定每個 CPU 中斷。

int __request_percpu_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *devname, void __percpu *dev_id)

分配一個每個 CPU 中斷線

引數

unsigned int irq

要分配的中斷線

irq_handler_t handler

當 IRQ 發生時呼叫的函式。

unsigned long flags

中斷型別標誌(僅 IRQF_TIMER)

const char *devname

宣告此裝置的 ASCII 名稱

void __percpu *dev_id

傳遞迴處理函式的每個 CPU cookie

描述

此呼叫分配中斷資源並在本地 CPU 上啟用中斷。如果中斷需要在其他 CPU 上啟用,則必須在每個 CPU 上使用 enable_percpu_irq() 完成此操作。

dev_id 必須全域性唯一。它是一個每個 CPU 變數,並且處理程式會使用被中斷 CPU 的該變數例項來呼叫。

int request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name, void __percpu *dev_id)

分配一個用於 NMI 遞送的每個 CPU 中斷線

引數

unsigned int irq

要分配的中斷線

irq_handler_t handler

當 IRQ 發生時呼叫的函式。

const char *name

宣告此裝置的 ASCII 名稱

void __percpu *dev_id

傳遞迴處理函式的每個 CPU cookie

描述

此呼叫為每個 CPU NMI 分配中斷資源。每個 CPU NMI 必須在透過 enable_percpu_nmi() 在同一 CPU 上啟用之前,透過呼叫 prepare_percpu_nmi() 在每個 CPU 上進行設定。

dev_id 必須全域性唯一。它是一個每個 CPU 變數,並且處理程式會使用被中斷 CPU 的該變數例項來呼叫。

請求用於 NMI 遞送的中斷線應該停用自動啟用設定。

如果中斷線不能用於遞送 NMI,函式將失敗並返回負值。

int prepare_percpu_nmi(unsigned int irq)

執行 NMI 遞送的 CPU 本地設定

引數

unsigned int irq

要準備用於 NMI 遞送的中斷線

描述

此呼叫準備一條中斷線,以便在當前 CPU 上遞送 NMI,在此中斷線透過 enable_percpu_nmi() 啟用之前。

作為 CPU 本地操作,應從不可搶佔的上下文呼叫此函式。

如果中斷線不能用於遞送 NMI,函式將失敗並返回負值。

void teardown_percpu_nmi(unsigned int irq)

撤銷 IRQ 線的 NMI 設定

引數

unsigned int irq

應移除 CPU 本地 NMI 配置的中斷線

描述

此呼叫撤銷了由 prepare_percpu_nmi() 完成的設定。

IRQ 線不應為當前 CPU 啟用。作為 CPU 本地操作,應從不可搶佔的上下文呼叫此函式。

int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool *state)

返回中斷的 irqchip 狀態。

引數

unsigned int irq

轉發到虛擬機器的中斷線

enum irqchip_irq_state which

呼叫者想要了解的 IRQCHIP_STATE_* 之一

bool *state

一個布林指標,用於儲存狀態

描述

此呼叫拍攝中斷的內部 irqchip 狀態快照,將與階段 which 對應的位返回到 state 中。

如果中斷控制器具有每個 CPU 暫存器,則應停用搶佔來呼叫此函式。

int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool val)

設定轉發中斷的狀態。

引數

unsigned int irq

轉發到虛擬機器的中斷線

enum irqchip_irq_state which

要恢復的狀態(IRQCHIP_STATE_* 之一)

bool val

對應於 which 的值

描述

此呼叫根據 which 的值,設定中斷的內部 irqchip 狀態。

如果中斷控制器具有每個 CPU 暫存器,則應停用遷移來呼叫此函式。

bool irq_has_action(unsigned int irq)

檢查中斷是否已請求

引數

unsigned int irq

Linux irq 號

返回

當前狀態的快照

bool irq_check_status_bit(unsigned int irq, unsigned int bitmask)

檢查 irq 描述符狀態中的位是否已設定

引數

unsigned int irq

Linux irq 號

unsigned int bitmask

要評估的位掩碼

返回

如果 bitmask 中的任一位被設定,則為 True

int irq_set_chip(unsigned int irq, const struct irq_chip *chip)

設定 irq 的 irq 晶片

引數

unsigned int irq

irq 號

const struct irq_chip *chip

指向 irq 晶片描述結構的指標

int irq_set_irq_type(unsigned int irq, unsigned int type)

設定 irq 的 irq 觸發型別

引數

unsigned int irq

irq 號

unsigned int type

IRQ_TYPE_{LEVEL,EDGE}_* 值 - 參見 include/linux/irq.h

int irq_set_handler_data(unsigned int irq, void *data)

設定 irq 的 irq 處理程式資料

引數

unsigned int irq

中斷號

void *data

指向中斷特定資料的指標

描述

設定 irq 的硬體 irq 控制器資料

int irq_set_chip_data(unsigned int irq, void *data)

設定 irq 的 irq 晶片資料

引數

unsigned int irq

中斷號

void *data

指向晶片特定資料的指標

描述

設定 irq 的硬體 irq 晶片資料

void handle_nested_irq(unsigned int irq)

從 irq 執行緒處理巢狀 irq

引數

unsigned int irq

中斷號

描述

處理巢狀到執行緒化中斷處理程式中的中斷。處理函式在呼叫執行緒的上下文中被呼叫。

void handle_simple_irq(struct irq_desc *desc)

簡單和軟體解碼的 IRQ。

引數

struct irq_desc *desc

此 irq 的中斷描述結構

描述

簡單中斷要麼從解複用中斷處理程式傳送,要麼來自硬體,其中不需要中斷硬體控制。

注意

如果需要,呼叫者應處理確認、清除、遮蔽和解除遮蔽問題。

void handle_untracked_irq(struct irq_desc *desc)

簡單和軟體解碼的 IRQ。

引數

struct irq_desc *desc

此 irq 的中斷描述結構

描述

未跟蹤中斷從解複用中斷處理程式傳送,當解複用器不知道是其多路複用 irq 域中的哪個裝置生成了中斷時。透過此處處理的 IRQ 不受統計跟蹤、隨機性或虛假中斷檢測的影響。

注意

與 handle_simple_irq 類似,如果需要,呼叫者應處理確認、清除、遮蔽和解除遮蔽問題。

void handle_level_irq(struct irq_desc *desc)

電平觸發 irq 處理程式

引數

struct irq_desc *desc

此 irq 的中斷描述結構

描述

電平觸發中斷在硬體線保持活動電平期間一直處於活動狀態。這可能需要遮蔽中斷,並在相關處理程式確認裝置後解除遮蔽,以便中斷線返回非活動狀態。

void handle_fasteoi_irq(struct irq_desc *desc)

透明控制器的 irq 處理程式

引數

struct irq_desc *desc

此 irq 的中斷描述結構

描述

只會向晶片發出一個回撥:當中斷被服務後呼叫 ->eoi()。這支援現代形式的中斷處理程式,這些處理程式以透明方式在硬體中處理流詳細資訊。

void handle_fasteoi_nmi(struct irq_desc *desc)

NMI 中斷線的 irq 處理程式

引數

struct irq_desc *desc

此 irq 的中斷描述結構

一個簡單的 NMI 安全處理程式,考慮了 request_nmi 的限制。

只會向晶片發出一個回撥:當中斷被服務後呼叫 ->eoi()。這支援現代形式的中斷處理程式,這些處理程式以透明方式在硬體中處理流詳細資訊。

void handle_edge_irq(struct irq_desc *desc)

邊沿觸發 IRQ 處理程式

引數

struct irq_desc *desc

此 irq 的中斷描述結構

描述

中斷髮生在硬體訊號的下降沿和/或上升沿。發生的中斷被鎖存到 irq 控制器硬體中,並且必須透過確認才能重新啟用。確認後,即使在第一個中斷被相關事件處理程式處理之前,同一源上也可能發生另一箇中斷。如果發生這種情況,可能需要根據控制器硬體停用(遮蔽)中斷。這需要在一個迴圈中重新啟用中斷,該迴圈處理在處理程式執行時到達的中斷。如果所有待處理中斷都已處理,則退出迴圈。

void handle_fasteoi_ack_irq(struct irq_desc *desc)

堆疊在透明控制器上的邊沿層級 irq 處理程式

引數

struct irq_desc *desc

此 irq 的中斷描述結構

描述

類似於 handle_fasteoi_irq(),但用於需要呼叫其 ->irq_ack() 函式的 irq_chip 的層級。

void handle_fasteoi_mask_irq(struct irq_desc *desc)

堆疊在透明控制器上的電平層級 irq 處理程式

引數

struct irq_desc *desc

此 irq 的中斷描述結構

描述

類似於 handle_fasteoi_irq(),但用於需要呼叫其 ->irq_mask_ack() 函式的 irq_chip 的層級。

int irq_chip_set_parent_state(struct irq_data *data, enum irqchip_irq_state which, bool val)

設定父中斷的狀態。

引數

struct irq_data *data

指向中斷特定資料的指標

enum irqchip_irq_state which

要恢復的狀態(IRQCHIP_STATE_* 之一)

bool val

對應於 which 的值

描述

如果底層 irqchip 未實現,則有條件成功。

int irq_chip_get_parent_state(struct irq_data *data, enum irqchip_irq_state which, bool *state)

獲取父中斷的狀態。

引數

struct irq_data *data

指向中斷特定資料的指標

enum irqchip_irq_state which

呼叫者想要了解的 IRQCHIP_STATE_* 之一

bool *state

一個布林指標,用於儲存狀態

描述

如果底層 irqchip 未實現,則有條件成功。

void irq_chip_enable_parent(struct irq_data *data)

啟用父中斷(如果為 NULL,則預設為解除遮蔽)

引數

struct irq_data *data

指向中斷特定資料的指標

void irq_chip_disable_parent(struct irq_data *data)

停用父中斷(如果為 NULL,則預設為遮蔽)

引數

struct irq_data *data

指向中斷特定資料的指標

void irq_chip_ack_parent(struct irq_data *data)

確認父中斷

引數

struct irq_data *data

指向中斷特定資料的指標

void irq_chip_mask_parent(struct irq_data *data)

遮蔽父中斷

引數

struct irq_data *data

指向中斷特定資料的指標

void irq_chip_mask_ack_parent(struct irq_data *data)

遮蔽並確認父中斷

引數

struct irq_data *data

指向中斷特定資料的指標

void irq_chip_unmask_parent(struct irq_data *data)

解除遮蔽父中斷

引數

struct irq_data *data

指向中斷特定資料的指標

void irq_chip_eoi_parent(struct irq_data *data)

在父中斷上呼叫 EOI

引數

struct irq_data *data

指向中斷特定資料的指標

int irq_chip_set_affinity_parent(struct irq_data *data, const struct cpumask *dest, bool force)

設定父中斷的親和性

引數

struct irq_data *data

指向中斷特定資料的指標

const struct cpumask *dest

要設定的親和性掩碼

bool force

強制設定的標誌(停用線上檢查)

描述

有條件,因為底層父晶片可能未實現它。

int irq_chip_set_type_parent(struct irq_data *data, unsigned int type)

在父中斷上設定 IRQ 型別

引數

struct irq_data *data

指向中斷特定資料的指標

unsigned int type

IRQ_TYPE_{LEVEL,EDGE}_* 值 - 參見 include/linux/irq.h

描述

有條件,因為底層父晶片可能未實現它。

int irq_chip_retrigger_hierarchy(struct irq_data *data)

在硬體中重新觸發中斷

引數

struct irq_data *data

指向中斷特定資料的指標

描述

遍歷中斷的域層級,並檢查是否存在硬體重新觸發函式。如果存在,則呼叫它。

int irq_chip_set_vcpu_affinity_parent(struct irq_data *data, void *vcpu_info)

設定父中斷的 vcpu 親和性

引數

struct irq_data *data

指向中斷特定資料的指標

void *vcpu_info

vcpu 親和性資訊

int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on)

在父中斷上設定/重置喚醒

引數

struct irq_data *data

指向中斷特定資料的指標

unsigned int on

是否設定或重置此 irq 的喚醒功能

描述

有條件,因為底層父晶片可能未實現它。

int irq_chip_request_resources_parent(struct irq_data *data)

在父中斷上請求資源

引數

struct irq_data *data

指向中斷特定資料的指標

void irq_chip_release_resources_parent(struct irq_data *data)

釋放父中斷上的資源

引數

struct irq_data *data

指向中斷特定資料的指標

提供的內部函式

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

unsigned int irq_get_nr_irqs(void)

系統支援的中斷數量。

引數

void

無引數

unsigned int irq_set_nr_irqs(unsigned int nr)

設定系統支援的中斷數量。

引數

unsigned int nr

新的中斷數量。

返回

nr.

int generic_handle_irq(unsigned int irq)

為特定 irq 呼叫處理程式

引數

unsigned int irq

要處理的 irq 號

返回

成功時為 0,如果轉換失敗則為 -EINVAL

此函式必須在 IRQ 上下文中呼叫,並初始化 irq 暫存器。

int generic_handle_irq_safe(unsigned int irq)

從任何上下文為特定 irq 呼叫處理程式。

引數

unsigned int irq

要處理的 irq 號

返回

成功時為 0,錯誤時為負值。

描述

此函式可以從任何上下文(IRQ 或程序上下文)呼叫。如果未從 IRQ 上下文呼叫,並且 irq 已被標記為僅強制 IRQ 上下文,它將報告錯誤。

int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwirq)

為屬於某個域的硬體 irq 呼叫處理程式。

引數

struct irq_domain *domain

執行查詢的域

unsigned int hwirq

要轉換為邏輯值的硬體 irq 號

返回

成功時為 0,如果轉換失敗則為 -EINVAL

此函式必須在 IRQ 上下文中呼叫,並初始化 irq 暫存器。

int generic_handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq)

為屬於某個域的硬體 NMI 呼叫處理程式。

引數

struct irq_domain *domain

執行查詢的域

unsigned int hwirq

要轉換為邏輯值的硬體 irq 號

返回

成功時為 0,如果轉換失敗則為 -EINVAL

此函式必須在 NMI 上下文中呼叫,並初始化 irq 暫存器。

void irq_free_descs(unsigned int from, unsigned int cnt)

釋放 irq 描述符

引數

unsigned int from

描述符範圍的起始

unsigned int cnt

要釋放的連續 irq 數量

int __ref __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, struct module *owner, const struct irq_affinity_desc *affinity)

分配並初始化一個 irq 描述符範圍

引數

int irq

如果 irq >= 0,則為特定 irq 號分配

unsigned int from

從此 irq 號開始搜尋

unsigned int cnt

要分配的連續 irq 數量。

int node

優先分配 irq 描述符的節點

struct module *owner

擁有模組(可為 NULL)

const struct irq_affinity_desc *affinity

可選的指向大小為 cnt 的親和性掩碼陣列的指標,該陣列提示 irq 描述符應分配到何處以及使用哪些預設親和性

描述

返回第一個 irq 號或錯誤程式碼

unsigned int irq_get_next_irq(unsigned int offset)

獲取下一個已分配的 irq 號

引數

unsigned int offset

從何處開始搜尋

描述

返回偏移量後的下一個 irq 號,如果未找到則返回 nr_irqs。

unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)

獲取 CPU 上中斷的統計資訊

引數

unsigned int irq

中斷號

int cpu

CPU 號

描述

返回自啟動以來 cpuirq 的中斷計數總和。呼叫者必須確保中斷不會併發移除。

unsigned int kstat_irqs_usr(unsigned int irq)

從執行緒上下文獲取中斷的統計資訊

引數

unsigned int irq

中斷號

描述

返回自啟動以來所有 CPU 上 irq 的中斷計數總和。

它使用 rcu 保護訪問,因為中斷描述符的併發移除在 delayed_free_desc()/irq_kobj_release() 之前會觀察到一個 rcu 寬限期。

void handle_bad_irq(struct irq_desc *desc)

處理虛假和未處理的 irq

引數

struct irq_desc *desc

中斷的描述

描述

處理虛假和未處理的 IRQ。它還會列印一條除錯訊息。

void noinstr generic_handle_arch_irq(struct pt_regs *regs)

針對不自行進行入口計數的架構的根 irq 處理程式

引數

struct pt_regs *regs

來自低階處理程式碼的暫存器檔案

int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset, struct msi_desc *entry)

在偏移量處為 irq 設定 MSI 描述符資料

引數

unsigned int irq_base

中斷號基址

unsigned int irq_offset

中斷號偏移量

struct msi_desc *entry

指向 MSI 描述符資料的指標

描述

在偏移量處為 irq 設定 MSI 描述符條目

int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)

為 irq 設定 MSI 描述符資料

引數

unsigned int irq

中斷號

struct msi_desc *entry

指向 MSI 描述符資料的指標

描述

為 irq 設定 MSI 描述符條目

void irq_disable(struct irq_desc *desc)

將中斷標記為停用

引數

struct irq_desc *desc

應該被停用的 irq 描述符

描述

如果晶片未實現 irq_disable 回撥,我們採用延遲停用方法。這意味著我們標記中斷為停用,但讓硬體保持未遮蔽狀態。這是一個最佳化,因為我們避免了在標記為停用後沒有中斷髮生的常見情況下的硬體訪問。如果發生中斷,則中斷流處理程式會在硬體級別遮蔽該線路並將其標記為待處理。

如果中斷晶片未實現 irq_disable 回撥,驅動程式可以透過呼叫“irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY)”來停用特定 irq 線的延遲方法。這可用於在某些情況下無法在裝置級別停用中斷,而必須使用 disable_irq[_nosync] 的裝置。

void handle_percpu_irq(struct irq_desc *desc)

每個 CPU 本地 irq 處理程式

引數

struct irq_desc *desc

此 irq 的中斷描述結構

SMP 機器上不需要鎖定要求的每個 CPU 中斷

void handle_percpu_devid_irq(struct irq_desc *desc)

帶有每個 CPU dev_id 的每個 CPU 本地 irq 處理程式

引數

struct irq_desc *desc

此 irq 的中斷描述結構

描述

SMP 機器上不需要鎖定要求的每個 CPU 中斷。與上面 handle_percpu_irq() 相同,但有以下額外功能

action->percpu_dev_id 是指向每個 CPU 變數的指標,這些變數包含呼叫此處理程式的 CPU 的實際裝置 ID

void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc)

帶有每個 CPU dev_id 的每個 CPU 本地 NMI 處理程式

引數

struct irq_desc *desc

此 irq 的中斷描述結構

描述

類似於 handle_fasteoi_nmi,但將 dev_id cookie 作為每個 CPU 指標處理。

void irq_cpu_online(void)

呼叫所有 irq_cpu_online 函式。

引數

void

無引數

描述

遍歷所有 irq,併為每個 irq 呼叫 chip.irq_cpu_online()

void irq_cpu_offline(void)

呼叫所有 irq_cpu_offline 函式。

引數

void

無引數

描述

遍歷所有 irq,併為每個 irq 呼叫 chip.irq_cpu_offline()

int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)

為 irq 晶片合成 MSI 訊息

引數

struct irq_data *data

指向中斷特定資料的指標

struct msi_msg *msg

指向 MSI 訊息的指標

描述

對於分層域,我們找到層級中第一個實現 irq_compose_msi_msg 回撥的晶片。對於非分層域,我們使用頂層晶片。

int irq_chip_pm_get(struct irq_data *data)

啟用 IRQ 晶片的電源

引數

struct irq_data *data

指向中斷特定資料的指標

描述

啟用中斷資料結構引用的 IRQ 晶片的電源。

int irq_chip_pm_put(struct irq_data *data)

停用 IRQ 晶片的電源

引數

struct irq_data *data

指向中斷特定資料的指標

描述

停用中斷資料結構引用的 IRQ 晶片的電源。請注意,只有在所有已呼叫 irq_chip_pm_get() 的 IRQ 都呼叫此函式後,電源才會被停用。

鳴謝

以下人員對本文件做出了貢獻

  1. Thomas Gleixner tglx@linutronix.de

  2. Ingo Molnar mingo@elte.hu