linux中斷子系統 irq desc的建立

2021-12-29 20:41:11 字數 3755 閱讀 6157

irq_desc的**主要在kernel/irq/irqdesc.c中

linux4.6.3

irq_desc在核心中有兩種組織方式,這是根據巨集config_sparse_irq是否定義來決定的,這兩種方式分別是:

(1)radix-tree方式,這是以基數樹的方式來組織irq_desc

(2)陣列的方式 ,前面的文章介紹irq結構時,就是用此方式舉例的,在系統初始化的時候會定義乙個全域性陣列,詳細見下面**,nr_irqs就代表總共的irq數量

struct irq_desc irq_desc[nr_irqs] __cacheline_aligned_in_smp =

};我們最終的目標是建立hwirq和virq的對映,上面兩種方式代表兩種不同的對映方式,陣列簡單就是線性對映,而基數樹具體在這裡不說了。

irq_desc建立完後,要做的就是初始化,在核心中有兩方面會涉及到irq_desc的初始化,乙個是在申請中斷的時候(主要是初始化irq_desc->action),另乙個是在驅動初始化的時候,本文重點就在這裡

#define irq_alloc_descs(irq, from, cnt, node) \

__irq_alloc_descs(irq, from, cnt, node, this_module)

#define irq_alloc_desc(node) \

irq_alloc_descs(-1, 0, 1, node)

#define irq_alloc_desc_at(at, node) \

irq_alloc_descs(at, at, 1, node)

#define irq_alloc_desc_from(from, node) \

irq_alloc_descs(-1, from, 1, node)

#define irq_alloc_descs_from(from, cnt, node) \

irq_alloc_descs(-1, from, cnt, node)

從上面可以看出最終都是呼叫到函式__irq_alloc_descs,此函式最終會呼叫到函式alloc_descs,從第一節我們知道irq_desc組織方式有兩種,那麼alloc_descs會有兩個介面,下面分別介紹:

static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,

struct module *owner)

return start;

}struct irq_desc *irq_to_desc(unsigned int irq)

static int alloc_descs(unsigned int start, unsigned int cnt, int node,

struct module *owner)

return start;

err:

for (i--; i >= 0; i--)

free_desc(start + i);

mutex_lock(&sparse_irq_lock);

bitmap_clear(allocated_irqs, start, cnt);

mutex_unlock(&sparse_irq_lock);

return -enomem;

}static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)

各個驅動中斷的配置在dt中(dt參考我的文章裝置樹的解釋),dt初始化中斷的乙個簡易流程如下圖

走到of_irq_to_resource就脫離了dt過程,正式進入到本節的主題,函式呼叫流程圖如下:

這些沒什麼說的,只是乙個引數解析過程,重要的是下面這些函式

a: 找到匹配的irq_domain,irq_domain會在中斷控制器註冊的時候加入b: 判斷irq_domain是否是hierarchy,不同的型別需要不同的操作,從圖中可以看出雖然呼叫函式不一樣,但是具體要執行的步驟是一樣的:

(1)搜尋hwirq是否已經被對映到virq,如果是直接返回

(2)如果沒有得到virq,那麼把hwirq對映到virq

(3)呼叫irq_domain的相關函式初始化irq_desc

上面的簡化分析不能說明問題,下面通過**來仔細分析,只分析不是hierarchy的情況:

一、先分析函式irq_find_mapping

unsigned int irq_find_mapping(struct irq_domain *domain,

irq_hw_number_t hwirq)

/* check if the hwirq is in the linear revmap. */

if (hwirq < domain->revmap_size)

return domain->linear_revmap[hwirq];-----------------線性對映返回

rcu_read_lock();

data = radix_tree_lookup(&domain->revmap_tree, hwirq);

rcu_read_unlock();

return data ? data->irq : 0;-----------------------------基數樹對映返回

}--------------linear_revmap或者revmap_tree的建立是在中斷控制器註冊的時候初始化的

二、再分析函式irq_domain_alloc_descs

int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,

int node)

else

return virq;

}三、最後分析函式irq_domain_associate

int irq_domain_associate(struct irq_domain *domain, unsigned int virq,

irq_hw_number_t hwirq)

irq_data->domain = null;

irq_data->hwirq = 0;

mutex_unlock(&irq_domain_mutex);

return ret;

}/* if not already assigned, give the domain the chip's name */

if (!domain->name && irq_data->chip)

domain->name = irq_data->chip->name;

}if (hwirq < domain->revmap_size) else

mutex_unlock(&irq_domain_mutex);

irq_clear_status_flags(virq, irq_norequest);

return 0;

}

Linux中斷子系統

linux kernel的中斷子系統之 一 一 前言 乙個合格的linux驅動工程師需要對kernel中的中斷子系統有深刻的理解,只有這樣,在寫具體driver的時候才能 1 正確的使用linux kernel提供的的api,例如最著名的request threaded irq request ir...

linux中斷子系統

參考引用 wowotech 乙個很好的linux技術部落格。一 概述 目的kernel管理硬體裝置的方式 輪詢 中斷。中斷效率高且反應快於輪詢,因為它利用了硬體本身執行指令前會做的 中斷電訊號週期輪詢 分類中斷分為同步 synchronous 和非同步 asynchronous 同步也稱為異常,由c...

中斷子系統

linux kernel的中斷子系統之 一 綜述 linux kernel的中斷子系統之 二 irq domain介紹 linux kernel的中斷子系統之 三 irq number和中斷描述符 linux kernel的中斷子系統之 四 high level irq event handler ...