我在日志中发现了这一点:
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
答案1
这些消息是由内核通用 I/O 代码生成的,显然是在尝试加载由该补丁或其更成熟的等效补丁。
简洁版本:
该模块找到了它正在寻找的 WMI 编程接口,但忽略了该接口报告硬件中没有可控 GPIO 线路的事实。它应该停止注册尝试并拒绝模块安装并显示-ENODEV
错误代码。您可以通过将模块列入黑名单来删除消息gpio-aaeon
,即创建一个名为eg的文件,/etc/modprobe.d/no-aaeon-gpio-here.conf
其中包含以下内容:
blacklist gpio-aaeon
您在该内核模块中发现了一个错误,并且可能想要向 Linux GPIO 开发人员报告。您的硬件似乎为测试gpio_aaeon
模块提供了一个有趣的“极端情况”,开发人员显然没有考虑到这一点。这是可以理解的,因为该模块似乎相当新:我上面链接的补丁是在今年五月下旬发布的。
长版:
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 内核交叉引用器,devm_gpiochip_add_data()
是一个宏,它仅调用devm_gpiochip_add_data_with_key()
最后两个参数为 NULL 的函数。反过来,这又称为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 线。
所以无论哪种方式,都有一些事情需要解决。
答案2
我在尝试从 U 盘安装 Xubuntu 20.04 时遇到了这些相同的错误消息。我在华硕 ROG STRIX R550-F 主板上使用 Ryzen 5600X。问题出在 nVidia 显卡上。一旦我选择了“安全图形”选项,它就可以启动。