gpio gpiochip0核心錯誤是什麼意思以及如何解決?
我在我的日誌中發現了這個:
kernel: gpio gpiochip0: (gpio_aaeon): tried to insert a GPIO chip with zero lines kernel: gpiochip_add_data_with_key: GPIOs 0..-1 (gpio_aaeon) failed to register, -22 kernel: gpio-aaeon: probe of gpio-aaeon.0 failed with error -22
這是什麼意思,我應該如何解決它?
lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 21.04 Release: 21.04 Codename: hirsute
這些消息是由核心通用 I/O 程式碼產生的,顯然是在嘗試載入此更新檔或其更開發的等效模組引入的模組時。
精簡版:
模組找到它正在尋找的 WMI 程式介面,但忽略了介面報告硬體中沒有可控 GPIO 線的事實。它應該已停止註冊嘗試並拒絕模組安裝並顯示
-ENODEV
錯誤程式碼。您可以通過將gpio-aaeon
模組列入黑名單來刪除消息,即通過創建一個名為 eg 的文件/etc/modprobe.d/no-aaeon-gpio-here.conf
,其內容如下:blacklist gpio-aaeon
您在該核心模組中發現了一個錯誤,並且可能希望將其報告給 Linux GPIO 開發人員。您的硬體似乎為測試
gpio_aaeon
模組提供了一個有趣的“角落案例”,開發人員顯然沒有考慮過。這是可以理解的,因為該模組似乎相當新:我上面連結的更新檔是在今年 5 月下旬發布的。長版:
GPIO 子系統抱怨該
gpio_aaeon
模組試圖註冊一個實際上沒有任何通用 I/O 線來控制的晶片,因此將這樣的晶片註冊到 GPIO 子系統是沒有意義的。註冊發生在模組的探測函式中:
+static int __init aaeon_gpio_probe(struct platform_device *pdev) +{ + int err, i; + int dio_number = 0; + struct aaeon_gpio_data *data; + struct aaeon_gpio_bank *bank; + + /* Prevent other drivers adding this platfom device */ + if (!wmi_has_guid(AAEON_WMI_MGMT_GUID)) { + pr_debug("AAEON Management GUID not found\n"); + return -ENODEV; + } + + dio_number = aaeon_gpio_get_number(); + if (dio_number < 0) + return -ENODEV; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->nr_bank = ARRAY_SIZE(aaeon_gpio_bank); + data->bank = aaeon_gpio_bank; + platform_set_drvdata(pdev, data); + bank = &data->bank[0]; + bank->chip.parent = &pdev->dev; + bank->chip.ngpio = dio_number; + bank->data = data; + err = devm_gpiochip_add_data(&pdev->dev, &bank->chip, bank); + if (err) + pr_debug("Failed to register gpiochip %d: %d\n", i, err); + + return err; +}
由於載入模組的嘗試並沒有簡單地以
-ENODEV
錯誤結束,因此您的系統顯然具有此驅動程序正在尋找的 WMI 管理 API……但是當被查詢時,該 API 實際上表示它沒有什麼可控制的。換句話說,模組可以繼續
dio_number = aaeon_gpio_get_number();
呼叫,最終只是呼叫一個 WMI 方法來獲取一個整數,這顯然是可通過此 API 控制的 GPIO 線數。WMI 方法沒有返回錯誤……但它報告的行數顯然是 0。該函式繼續分配一些記憶體並開始建構 Linux GPIO 子系統所需的結構以註冊 GPIO 線以進行控制。完成後,它會呼叫
devm_gpiochip_add_data()
GPIO 子系統的函式來註冊一個新的 GPIO 晶片……但是 GPIO 子系統會執行一些完整性檢查,並註意到這些結構實際上指定了晶片中有 0 條 GPIO 線要控制。根據Elixir.bootlin.com Linux kernel cross-referencer,這
devm_gpiochip_add_data()
是一個宏,它只呼叫devm_gpiochip_add_data_with_key()
最後兩個參數為空的函式。這反過來又會呼叫gpiochip_add_data_with_key()
函式,這將產生您在第 #628 行看到的第一條錯誤消息。之後的其他消息隨著函式呼叫鏈的展開而產生,因為每個函式都向其呼叫者返回一個錯誤程式碼。
如果返回的值
aaeon_gpio_get_number()
確實是 WMI API 可以控制的 GPIO 線數,那麼測試:+ if (dio_number < 0) + return -ENODEV;
實際上應該是:
+ if (dio_number < 1) + return -ENODEV;
但是如果 WMI API 返回的數字實際上意味著一些微妙的不同,比如“最後一個可控 GPIO 線的從 0 開始的數字”(即值 0 表示“只有一個 GPIO 線 #0,沒有其他”),然後將
dio_number
用作 的值會bank->chip.ngpio
導致一個錯誤,並且模組將錯過所有具有此用於 GPIO 的 WMI API 的系統中的最後一個可控 GPIO 線。因此,無論哪種方式,都需要解決一些問題。