调用 request_mem_region() 失败

Posted

技术标签:

【中文标题】调用 request_mem_region() 失败【英文标题】:call to request_mem_region() fails 【发布时间】:2014-05-29 12:39:05 【问题描述】:

起始地址 0x4806E000(UART4 基地址)已经存在于 /proc/iomem 中,名称为 omap4-uart。

如何禁用已分配的内存区域?

编辑: 即使 request_mem_region 成功,启动过程中的控制台也会显示此消息。

[    0.758514] Serial: 8250/16550 driver, 3 ports, IRQ sharing enabled
[    0.760040] omap_uart.0: ttyO0 at MMIO 0x4806a000 (irq = 104) is a OMAP UART0
[    0.760498] omap_uart.1: ttyO1 at MMIO 0x4806c000 (irq = 105) is a OMAP UART1
[    0.760955] omap_uart.2: ttyO2 at MMIO 0x48020000 (irq = 106) is a OMAP UART2
[    1.778808] console [ttyO2] enabled
[    1.782989] omap_uart omap_uart.3: [UART3]: failure [serial_omap_probe]: -22
[    1.790466] omap_uart: probe of omap_uart.3 failed with error -22

我认为这表明内核仍在尝试配置 uart4 实例? 编辑 2:在软件重置期间,while 循环进入无限循环

/* Pad Configuration */
    unsigned int pad_value = 0xFFF8FFF8;
    l = ioread32(pad_map);
    l &= pad_value;
    iowrite32(l,pad_map);
    printk(KERN_ALERT "pad configured\n");


    /* Software reset */

       printk(KERN_ALERT "reset check bit = %x\n",((serial_in(UART_OMAP_SYSC))));
       serial_out(UART_OMAP_SYSC,swreset);
       printk(KERN_ALERT "reset check bit = %x\n",((serial_in(UART_OMAP_SYSC))));
       readval = serial_in(UART_OMAP_SYSS);
       while((readval & 0x01)== 0);
       printk(KERN_ALERT "software reset completed\n");

【问题讨论】:

这个错误是因为你没有移除UART4和设备驱动omap-serial的关联(又名omap4-uart ) 在设备树中。 “为什么对 ioremap 的调用没有失败?” -- 设备驱动程序是在特权模式下执行的受信任代码。并非每个调用及其参数列表都像来自用户空间的系统调用一样经过验证。设备驱动程序应该编写良好,并执行预期的 Reserve-before-map 协议。 @sawdust:如何去除设备树中UART4与设备驱动omap-serial(又名omap4-uart)的关联? @sawdust:即使在注释掉 DT 的 uart4 实例和在 omap-serial.c 中,uart4 实例的基地址在 /proc/iomem 中也是可见的 “即使在注释掉 DT 的 uart4 实例之后...” -- 你需要实际向我们展示代码或设备树,而不是试图描述你做了什么/proc/iomem 的节点和内容。使用此更新信息编辑您的问题。 @sawdust: omap-serial.h 中的 No ports 从 6 更改为 3 以及 make menuconfig 时调用成功。感谢您的帮助。不需要更改 DT 中的任何内容 【参考方案1】:

我不相信其他驱动程序可以重用内存区域。这会使第一个司机行为不端。这意味着为了让您的驱动程序使用这个内存区域,您应该首先禁用其他驱动程序。

现在您的ioremap() 调用可能不会返回错误。它也有可能看起来工作得很好。这是因为 AFAIK,/proc/iomem 的内容不是来自ioremap() 调用,而是来自request_mem_region() 调用。了解它们的作用很重要:

您应该首先调用request_mem_region 来声明您的驱动程序将使用请求的内存区域(请注意,这不会进行任何内存映射,它只会表明您这样做的意愿)。对于您的设备,某些驱动程序已经这样做了,因此它可能会在需要时使用该区域。但是,它可能没有在声明该区域后立即调用ioremap(),而是会按需调用。

如果上述调用成功,您可以确定没有其他驱动程序将使用该区域。这意味着您可以随时在该地区拨打ioremap()iounmap()

从技术上讲,可以只做第二件事并跳过使用request_mem_region,但这样你的驱动程序就必须一直保持内存映射,以表明你将来可能会使用它。所以你应该很好,总是先保留该地区。

【讨论】:

是否可以从我安装驱动程序之前安装的驱动程序中仅删除 UART4 实例?我正在为 omap-4460 pandaboard 的 uart4 实例编写设备驱动程序。有其他方法吗? @Dino:我不知道这个驱动程序,但是编写一个可以选择禁用自身而不卸载的驱动程序是相当不寻常的。因此,如果此驱动程序作为模块安装,您只需卸载该模块即可。如果它被编译进去,你可能不走运并且可能需要重新编译。这对您来说应该不奇怪,毕竟您想为已经安装了驱动程序的硬件创建驱动程序。 :感谢您的宝贵时间。这是code。在我的情况下,驱动程序已编译并在启动时配置。因此修改驱动程序代码可能会有所帮助。 @Dino:您应该配置内核(即使用make menuconfig)来将此驱动程序编译为模块或根本不编译,而不是更改驱动程序。 SERIAL_OMAP 是这个驱动程序的一个选项,我相信。 :是的,我会试试这个方法并检查一下【参考方案2】:

@迪诺,

如何禁用已分配的内存区域?

解决方案:我认为您可以从内核(menuconfig)禁用UART驱动程序,构建内核映像并检查/proc/iomem,我猜UART4相关实例将被删除。

注意:如果使用设备树概念,则需要在设备树中禁用 UART4 节点“@uart4”。

我想在我的驱动程序代码中使用不同的名称。有可能吗?

解决方案:在您的 LKM 请求内存范围时使用 request_mem_region 和您的驱动程序名称。

顺便说一句:为什么对 ioremap 的调用没有失败?

解决方案:ioremap api 不会失败,因为 api 没有检查 ex:"driver name" 或任何其他检查。

【讨论】:

即使使用 menuconfig 配置后,uart4 实例的基地址在 /proc/iomem 中也是可见的 “我猜 UART4 相关的实例将被移除” -- Menuconfig 只会配置设备驱动程序,不能用于启用/禁用或配置单个设备。这就是 Device Tree(或已弃用的平台板文件)的用途。 @sawdust,真正的 menuconfig 不会禁用/启用单个驱动程序。我的意思是为了测试目的而不是构建 OMAP uart 驱动程序,例如静态的。由于内部 uart 驱动程序仅调用内存范围请求,通过不构建 OMAP uart 相关驱动程序,所有与 uart 驱动程序相关的实例将在“/proc/iomem”下不可见。 @GauthamKantharaju:当 omap-serial.h 中的 No ports 从 6 更改为 3 以及 make menuconfig 时,调用成功。谢谢您的帮助 @GauthamKantharaju:你能回答这个Question

以上是关于调用 request_mem_region() 失败的主要内容,如果未能解决你的问题,请参考以下文章

内核request_mem_region 和 ioremap的理解

内核request_mem_region 和 ioremap的理解

添加 request_mem_region 后,我的驱动程序每次第一次访问都会失败,并显示“忙碌”消息

x64 寄存器使用

失易得恢复-失易得数据恢复软件_恢复效果好

拼多多一面热乎的面经!还是 失算了失算了