gpio gpiochip0 内核错误意味着什么以及如何解决?

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

答案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 显卡上。一旦我选择了“安全图形”选项,它就可以启动。

相关内容