SMP PPI中斷使用

lethe1203發表於2024-04-01
SPI作為共享中斷,直接使用request_irq等函式註冊中斷處理函式即可
對於SMP系統PPI中斷來說,就需要為每個core都註冊一箇中斷處理函式,相關處理函式如下:
int smp_call_function(void (*func)(void *info), void *info, int retry, int wait);

// 引數說明
func 引數是指向要執行的函式的指標。
info 引數是一個可選的引數指標,可以傳遞給被呼叫的函式。
retry 引數指定了在發生錯誤時重試的次數。如果為 0,則不會重試。
wait 引數指示是否等待所有 CPU 完成函式的執行。如果為 0,則該函式立即返回,不等待所有 CPU 完成執行。如果為非零,則該函式會等待所有 CPU 完成執行。


int smp_call_function_single(int cpu, void (*func)(void *info), void *info, int retry, int wait);

// 引數說明
cpu 引數是要執行函式的 CPU 核心編號。
func 引數是指向要執行的函式的指標。
info 引數是一個可選的引數指標,可以傳遞給被呼叫的函式。
retry 引數指定了在發生錯誤時重試的次數。如果為 0,則不會重試。
wait 引數指示是否等待指定 CPU 完成函式的執行。如果為 0,則該函式立即返回,不等待 CPU 完成執行。如果為非零,則該函式會等待指定 CPU 完成執行。


int request_percpu_irq(unsigned int irq,
                        irq_handler_t handler,
                        const char *devname,
                        void *dev_id);

// 引數說明
irq:要請求的中斷號。
handler:中斷處理函式,當中斷事件發生時被呼叫。
devname:與中斷相關聯的裝置的名稱,用於除錯和記錄目的。
dev_id:傳遞給中斷處理函式的裝置識別符號。

使用demo如下:
#include <linux/interrupt.h>
#include <linux/smp.h>

#define IRQ_NUM_BASE 10        // PPI中斷號,irq而非hwirq

// 中斷處理函式
static irqreturn_t my_interrupt_handler(int irq, void *dev_id)
{
    // 中斷事件發生時執行的處理程式碼
    return IRQ_HANDLED;
}

// 在指定 CPU 上註冊基於 CPU 的中斷
static int register_percpu_irq_on_cpu(void *info)
{
    int cpu = smp_processor_id();
    int irq_num = IRQ_NUM_BASE + cpu;
    int ret;

    // 請求分配一個基於 CPU 的中斷
    ret = request_percpu_irq(irq_num, my_interrupt_handler, "my_device", NULL);
    if (ret) {
        printk(KERN_ERR "Failed to request percpu IRQ %d on CPU %d: %d\n", irq_num, cpu, ret);
        return ret;
    }

    printk(KERN_INFO "Successfully requested percpu IRQ %d on CPU %d\n", irq_num, cpu);
    return 0;
}

// 初始化模組
int init_module(void)
{
    int ret;

    // 在每個 CPU 核心上註冊基於 CPU 的中斷
    ret = smp_call_function(register_percpu_irq_on_cpu, NULL, 1);
    if (ret) {
        printk(KERN_ERR "Failed to register percpu IRQ on all CPUs: %d\n", ret);
        return ret;
    }

    printk(KERN_INFO "Module initialized\n");
    return 0;
}

// 清理模組
void cleanup_module(void)
{
    int cpu;

    // 釋放在每個 CPU 核心上註冊的中斷資源
    for_each_possible_cpu(cpu) {
        free_percpu_irq(IRQ_NUM_BASE + cpu, NULL);
    }

    printk(KERN_INFO "Module unloaded\n");
}

相關文章