2011-03-21 54 views
2

我正在編寫一個設備驅動程序來處理PCIe卡的中斷,該PCIe卡當前適用於在IRQ線路上引發的任何中斷向量。處理多箇中斷源/向量的Linux設備驅動程序

但它有幾個類型可以引發,由Vector寄存器標記。所以現在我需要閱讀矢量信息,並且是一個有點聰明...
所以,做我: -

1 /有獨立開發的節點/dev/int1/dev/int2等爲每個中斷類型,只是文件,讓int1是矢量類型A等?
1.1 /由於每個文件/字符設備將有它自己的minor號碼,當打開時,我會知道哪個是哪個。 我想。
1.2/ldd3似乎演示了這種方法。

2 /有一個節點/dev/int(正如我現在所做的)並且有多個進程掛在同一個read方法? 聽起來更好?!
2.1 /然後只喚醒正確的過程...?
2.2 /我使用單獨的wait_queue_head_t wait_queue s嗎?還是不同的flag /測試條件?

read方法: -

wait_event_interruptible(wait_queue, flag); 

在處理程序不是真正的代碼!: -

int vector = read_vector(); 
    if vector = A then 
     wake_up_interruptible(wait_queue, flag) 
     return IRQ_HANDLED; 
    else 
     return IRQ_NONE/IRQ_RETVAL? 

編輯:從人民的意見說明: -
1)我的用戶空間代碼mmap的所有的PCIe固件寄存器
2)用戶空間代碼有幾個線程,每個線程在設備驅動程序設備節點上執行阻塞read,然後在發生中斷時從固件返回數據。我需要根據中斷類型喚醒正確的線程。

回答

2

我不確定我是否正確理解你對Vector寄存器的意思(指向某些文檔的指針會幫助我精確地處理你的情況)。

無論如何,任何PCI設備都會獲得唯一的中斷號(由BIOS或x86之外的其他體系結構上的一些固件提供)。你只需要在你的驅動程序中註冊這個中斷。我真的不明白

priv->name = DRV_NAME; 
err = request_irq(pdev->irq, your_irqhandler, IRQF_SHARED, priv->name, 
      pdev); 
if (err) { 
    dev_err(&pdev->dev, "cannot request IRQ\n"); 
    goto err_out_unmap; 
} 

的另一件事就是爲什麼您會在中斷導出爲一個開發節點:中斷當然需要留在你的驅動/內核代碼的東西。但我想在這裏你想導出一個設備,然後在用戶空間訪問。我只是發現/dev/int不是一個好的命名。如果你的不同中斷源提供對不同硬件資源的訪問(即使在同一個PCI板上),我會選擇1),每個設備都有一個wait_queue。否則,我會選擇2)

由於您的中斷來自同一個物理設備,所以如果您選擇了選項1)或選項2),則必須共享中斷線,並且必須讀取矢量在你的中斷處理程序中定義了哪個硬件資源引發了中斷。

對於選項1),這將是這樣的:

static irqreturn_t pex_irqhandler(int irq, void *dev) { 
    struct pci_dev *pdev = dev; 
    int result; 

    result = pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &myirq); 

    if (result) { 
     int vector = read_vector(); 
     if (vector == A) { 
       set_flagA(flag); 
     } else if (vector == B) { 
       set_flagB(flag); 
     } 
     wake_up_interruptible(wait_queue, flag); 
     return IRQ_HANDLED; 
    } else { 
     return IRQ_NONE; 
} 

對於選項2,這將是類似的,但你必須只有一個,如果條款(相應的矢量值),在每個不同的中斷處理程序,您將請求每個節點。

+0

抱歉,文檔是專有/自定義固件。但內存映射包含一個源矢量,所以我知道哪種類型已被引發。謝謝,我有'request_irq'代碼位的工作,我的驅動程序掛起這個單一的IRQ,但PCIe卡引發不同的中斷,我們都知道,所有的中斷都引發同一個IRQ線。 – 2011-03-22 10:57:42

+0

我沒有導出_interrupts_ per-sa,我公開了一個用於使用用戶空間的設備節點,因爲我可能不清楚,我更新了我的Q,另請參閱我的其他評論回覆。而'int'這個名字只是這裏的一個僞名。是的,你必須閱讀_vector_。 _(但沒有意義侮辱,但你的選擇1代碼看起來非常像我的僞代碼在我的Q !?(但是是實際的代碼!))_ – 2011-03-22 11:06:37

+0

不要擔心,我不覺得侮辱,沒有處理irq的10種方法。這個例子的意思是你可以擁有一個單獨的irq處理程序,它可以獲取向量中所有可能的源,或者許多共享這個中斷的irq處理程序,它們都可以在向量中尋址一個irq源。對於版本1),您將擁有一個擁有多個隊列的設備,對於版本2),每個隊列都有多個設備。從你編輯的問題,我會說選項2可能看起來更簡單,更清潔。 – Longfield 2011-03-22 12:43:41

1

如果你有不同的香奈兒,你可以read()從,那麼你應該肯定使用不同的次要號碼。想象一下,你有一個四個串口的卡,你肯定會想要四個/dev/ttySx
但您的設備是否適合此型號?

+0

我喜歡串口的類比,我可能會走這條路,確保卡固件處理併發! _can of worms_ – 2011-03-22 11:13:36

1

首先,我假設你並沒有試圖讓你的代碼進入主線內核。如果你是,期待一個有力的討論最好的方式來做到這一點。如果你正在爲用戶空間主要由mmap驅動的卡寫一個簡單的中斷處理驅動程序,有很多方法可以解決這個問題。

如果您使用多個設備節點(選項1),則還可以實施poll,以便單個應用程序可以打開多個設備節點並等待選擇的中斷。次要號碼足以將他們分開。如果每個矢量都有一個喚醒隊列,則只能喚醒相關的偵聽器。您需要在成功poll後鎖定向量,以確保read成功。

如果您使用單個設備節點(選項2),則需要添加一些額外的魔術,以便線程可以註冊他們對特定中斷向量的興趣。你可以用ioctl來做到這一點,或者讓線程write中斷向量到設備。每個線程都應打開設備節點以獲取其自己的文件描述符。然後,您可以將請求的向量列表與每個打開的文件描述符相關聯。作爲獎勵,您可以讓應用程序從設備中獲取中斷向量,以便知道發生了哪個中斷。

您需要考慮如何清除中斷。中斷處理程序需要刪除中斷,然後存儲結果,以便將其傳遞給用戶空間。您可能會發現kfifo對此有用,而不是等待隊列。如果每個打開的文件描述符都有一個fifo,則可以將中斷通知分發給每個偵聽應用程序。

+0

nope,不提交任何內容,只需爲內置卡寫一個定製的PCIe驅動程序,並且是的,PCIe卡上的所有寄存器在用戶空間應用程序中都是mmap。我喜歡帶'write'的單節點,我想我必須添加一個'ioctl',正如你所說的,非常漂亮。我不需要傳遞中斷結果,只需發佈​​正確的阻塞'read'(我做了'copy_to_user'並返回一些數據)。 _(我已經通過一些說明更新了我的Q)_ – 2011-03-22 10:50:44

+0

我不認爲我需要'輪詢',因爲用戶空間應用程序對每個節點都有一個線程,它在'read'處打開'pe​​nds/blocks'。 – 2011-03-22 11:17:07

+0

我已經在這樣的一些設備上工作過。如果您希望單獨的線程監視不同的中斷,則需要多個設備節點,或者爲每個線程打開單個設備節點並獲取其自己的文件描述符。你是否需要排隊並計數中斷,或者每個「讀取」塊是否阻塞,直到下一個中​​斷爲止? – 2011-03-22 12:45:14

相關問題