This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] Linux/AM5728:对外设进行非32位对齐访问时 PCI RC 出现故障

Guru**** 2558250 points
Other Parts Discussed in Thread: AM5728, TUSB7340

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/598632/linux-am5728-pci-rc-failing-on-non-32-bit-aligned-access-to-peripherals

器件型号:AM5728
主题中讨论的其他器件: TUSB7340

工具/软件:Linux

从 AM5728 RC 对 PCI 交换机进行非32位对齐访问时出现问题。  RC 下方有一个 PEX 8606、开关接头类型未正确拾取。  我最初在 e2e.ti.com/.../597740中对此进行了讨论

说明问题的摘要如下:

Debian@arm:~$ lspci -s 0000:01:00.0 -x

0000:01:00.0 PCI 桥:PLX Technology、Inc. PEX 8606 6通道、6端口 PCI Express Gen 2 (5.0 GT/s)开关(修订版 BA)

00:B5 10 06 86 40 01 10 00 BA 00 04 06 10 00 01 00

10:00 00 20 20 00 00 00 01 02 07 00 F1 01 00

20:F0 ff 00 00 F1 ff 01 00 00 00 00 00 00 00 00 00 00 00

30:00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 01 01 00

 

然后对标头类型执行字节访问:

 

Debian@arm:~$ sudo setpci -s 0001:02:09.0 e.b

00

 

但执行32位访问:

 

Debian@arm:~$ sudo setpci -s 0001:02:09.0 c.l

00010010

 

因此 PCI 设备探测器出现故障,其库存代码如下所示:

 

[1.850281]   PCI 0000:01:00.0:[10b5:8606]类型00类0x060400

[1.850311]   PCI 0000:01:00.0:忽略类0x060400 (与标头类型00不匹配)

 

我们可以修改内核驱动程序代码、但此操作看起来很基本、必须存在其他问题。

有什么想法不一致的访问失败的原因?

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已经提出了可能的解决方法、但这是 PCI 驱动程序中真正的一种方法。  我修改了 kernel/drivers/pci/access.c pci_bus_read_config_##size 以使用以下宏强制进行32位对齐访问:

    #define PCI_OP_READ (size、type、len)\
    int pci_bus_read_config_##size \
    (struct pci_bus *总线、unsigned int devfn、int pos、键入*值)\
    {\
    内部分辨率;\
    无符号长整型标志;\
    u32数据= 0;\
    如果(PCI_##SIZE##_BAD)返回 PCIBIOS_BAD_REGISTER_NUMBER;\
    RAW_SPIN_LOCK_irqsave (&PCI_LOCK、flags);\
    如果((pos 和3))             \
      {                          \
      RES = bus->ops->read (bus、devfn、pos & 0xfffffc、4、&data); \
      数据>=((pos & 0x3)* 8);   \
      }                   \
      其他                  \
    {                   \
      RES = bus->ops->read (bus、devfn、pos、len、&data); \
    }                   \
    *值=(类型)数据;  \
    RAW_SPIN_UNLOCK_irqrestore (&PCI_LOCK、flags);\
    返回 res;       \
    这解决了访问问题,PCI 探测器现在发现了交换机和交换机端口,但导致驱动程序崩溃。  
    最初、我虽然是因为周围的工作、但最终决定调查故障、我在许多地方发现了该问题的参考。  它看起来像 PCI-dra7xx.c 具有相同的错误。  变通方法中出现的错误为:
    [1.863698]   错误:hwirq 0x4对于虚拟来说太大

    在 dra7初始化期间出现、并导致驱动程序崩溃、堆栈跟踪返回 dmesg。

    我发现的与此相关的问题是、它是由于 PCI 中断的编号为1、而不是0、所以 IRQ_domain 设置必须使用+1。  我找到了许多其他 PCI 驱动程序,这些驱动程序已遇到此问题并已得到纠正。

    我们的 PCI-dra7xx.c 代码中的特定区域似乎有相同的错误、因此我更改了:

    dra7xx->IRQ_domain = IRQ_DOMAIN_ADD_LINEAR (PCIe_INTC_node、4、
       &INTx_domain_ops、pp);
    if (!dra7xx->IRQ_domain){
    DEV_ERR (dev、"无法获取 INTx IRQ 域\n");
    返回 PTR_ERR (dra7xx->IRQ_domain);
    返回0;
     
    至:
     
    // PCI 中断线从1开始,而不是零开始,所以需要添加1
    dra7xx->IRQ_domain = IRQ_DOMAIN_ADD_LINEAR (PCIe_INTC_node、4 + 1、
       &INTx_domain_ops、pp);
    if (!dra7xx->IRQ_domain){
    DEV_ERR (dev、"无法获取 INTx IRQ 域\n");
    返回 PTR_ERR (dra7xx->IRQ_domain);
    返回0;
    它修复了崩溃。  但是、这是 PCI 驱动程序中的真正攻击、因此它将帮助我们继续开发、但不是正确的修复。
    如果有人建议为什么会这样做,将不胜感激。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    解决方法提供了交换机的成功探测,但是 setpci 仍然失败:

    Debian@arm:~$ lspci -s 0000:01:00.0 -x
    0000:01:00.0 PCI 桥:PLX Technology、Inc. PEX 8606 6通道、6端口 PCI Express Gen 2 (5.0 GT/s)开关(修订版 BA)
    00:B5 10 06 86 40 01 10 00 BA 00 04 06 10 00 01 00
    10:00 00 20 20 00 00 00 01 02 07 00 F1 01 00
    20:F0 ff 00 00 F1 ff 01 00 00 00 00 00 00 00 00 00 00 00
    30:00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 D8 01 01 00
    Debian@arm:~$ setpci -s 0000:01:00.0 c.l
    00010010
    Debian@arm:~$ setpci -s 0000:01:00.0 e.b
    00
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 Chris:

    感谢您分享解决方案。

    此致、
    帕维尔
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这个问题没有解决、只是一个解决问题的方法。 为什么我们必须破解 Linux PCI 驱动程序才能实现这一目标?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    作为持续问题的另一个示例、我们有一个 TI TUSB7340 PCI 集线器 EP、它具有相同类型的访问问题:

    Debian@arm:~$ sudo setpci -s 0001:07:00.0 e.b
    00
    Debian@arm:~$ sudo setpci -s 0001:07:00.0 c.l
    00000010

    这是有问题的。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 Chris:

    您是否使用 AM572x 定制板? 您是否使用 ti-processor-sdk-linux-am57xx-evm-03.03.00.04?

    此致、
    帕维尔
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我们使用的电路板设计基于 AM572x EVM。

    我们使用的是 TI Linux 内核:

    root@arm:~# uname -a
    Linux arm 4.4.4.49-ti-r89 #22 SMP Mon Jun 5 17:22:45 EDT 2017 armv7l GNU/Linux

    我一直在使用 TI AM572x IDK 来提供 PCI 示例和器件树设置。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Chris Welch66"]root@arm:~# uname -a
    Linux arm 4.4.4.49-ti-r89 #22 SMP Mon Jun 5 17:22:45 EDT 2017 armv7l GNU/Linux

    此内核不是官方的、未经测试。 请尝试使用最新的 PSDK 3.03 (内核4.4.4.41)随附的软件

    此致、
    帕维尔

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我现在正在研究这个问题、应该在今天晚些时候提供结果。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已经重现了支持的 TI SDK ti-processor-sdk-linux-am57xx-evm-03.03.00.04的问题

    扼要重述一下、我们有一个基于 AM5728 EVM 设计的 AM5728板。  我们已将 PCI 拆分为两个 RCS、每个 RCS 具有一个通道。

    每个 PCI RC 下面都有一个 PEX 8606 PCI 开关。

    root@am57xx-EVM:~# uname -a
    Linux am57xx-EVM 4.4.4.1.41-gf9f6f0db2d #6 SMP 抢占 Wed Jun 7 11:00:14 EDT 2017 armv7l GNU/Linux

    此特定电路板上的第一个 PEX 8606存在硬件问题、因此在本示例中、它不会显示在第一个 RC 下。  

    root@am57xx-EVM:~# lspci
    0000:00:00.0 PCI 桥:德州仪器(TI)器件8888 (修订版01)
    0001:00:00.0 PCI 桥:德州仪器(TI)器件8888 (修订版01)
    0001:01:00.0非 VGA 未分类器件:PLX Technology、Inc. PEX 8606 6通道、6端口 PCI Express Gen 2 (5.0 GT/s)开关(修订版 BA)

    如您所见、该列表未显示第二个 PEX 8606上的端口、说明了问题。

    以下是突出显示故障的 dmesg 报告:

    [0.637531] dra7-PCIe 518000.PCIe:PCI 主机桥至总线0001:00
    [0.637543] PCI_BUS 0001:00:根总线资源[bus 00-ff]
    [0.637555] PCI_BUS 0001:00:根总线资源[IO 0x10000-0x1FFF](总线地址[0x0000-0xFFF])
    [0.637564] PCI_bus 0001:00:根总线资源[mem 0x30013000-0x3fffffff]
    [0.637594] PCI 0001:00:00.0:[104C:888]类型01类0x060400
    [0.637632] PCI 0001:00:00.0:寄存器0x10:[MEM 0x00000000-0x000fff]
    [0.637653] PCI 0001:00:00.0:寄存器0x14:[MEM 0x00000000-0x0000FFF]
    [0.637762] PCI 0001:00:00.0:支持 D1
    [0.637772] PCI 0001:00:00.0:D0 D1 D3hot 支持 PME#
    [0.638001] PCI:总线0:禁用快速背对背传输
    [0.638156] PCI 0001:01:00.0:[10b5:8606]类型00类0x060400
    [0.638183] PCI 0001:01:00.0:忽略类0x060400 (与标头类型00不匹配)

    通过对 PEX 8606报头进行字节访问来获取报头类型、该报头类型始终返回零、因为它与32位地址不对齐。  类型实际上为1、但获取正确值的唯一方法是使用32位对齐访问。

    下面说明了使用 setpci 时出现的问题:

    root@am57xx-EVM:~# setpci -s 0001:00.0 e.b
    00

    但是、一个32位访问显示了正确的标头类型:

    root@am57xx-EVM:~# setpci -s 0001:00.0 c.l
    00010010

    使用 Hack to Linux PCI 来强制对齐访问(Hack 先前已发布)、我可以获得一些有限的操作:

    root@am57xx-EVM:~$ lspci
    0000:00:00.0 PCI 桥:德州仪器(TI)器件8888 (修订版01)
    0001:00:00.0 PCI 桥:德州仪器(TI)器件8888 (修订版01)
    0001:01:00.0 PCI 桥:PLX Technology、Inc. PEX 8606 6通道、6端口 PCI Express Gen 2 (5.0 GT/s)开关(修订版 BA)
    0001:02:01.0 PCI 桥接器:PLX Technology、Inc. PEX 8606 6通道、6端口 PCI Express Gen 2 (5.0 GT/s)开关(修订版 BA)
    0001:02:04.0 PCI 桥接器:PLX Technology、Inc. PEX 8606 6通道、6端口 PCI Express Gen 2 (5.0 GT/s)开关(修订版 BA)
    0001:02:05.0 PCI 桥接器:PLX Technology、Inc. PEX 8606 6通道、6端口 PCI Express Gen 2 (5.0 GT/s)开关(修订版 BA)
    0001:02:07.0 PCI 桥接器:PLX Technology、Inc. PEX 8606 6通道、6端口 PCI Express Gen 2 (5.0 GT/s)开关(修订版 BA)
    0001:02:09.0 PCI 桥接器:PLX Technology、Inc. PEX 8606 6通道、6端口 PCI Express Gen 2 (5.0 GT/s)开关(修订版 BA)
    0001:07:00.0 USB 控制器:德州仪器(TI) TUSB73x0超高速 USB 3.0 xHCI 主机控制器(修订版02)

    对交换机的字节访问仍然失败:

    root@am57xx-EVM:~$ setpci -s 0001:01:00.0 e.b
    00
    root@am57xx-EVM::~$ setpci -s 0001:00:00、0 c.l
    00010010

    但是、TUSB7340端点没有问题:

    root@am57xx-EVM:~$ lspci -s 0001:07:00.0 -x
    0001:07:00.0 USB 控制器:德州仪器(TI) TUSB73x0超高速 USB 3.0 xHCI 主机控制器(修订版02)
    00:4C 10 41 82 46 05 10 00 02 30 03 0c 10 00 00
    10:04 00 20 30 00 00 00 04 00 21 30 00 00 00 00 00 00
    20:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    30:00 00 00 40 00 00 00 00 00 00 00 00 00 00 fa 01 00 00

    root@am57xx-EVM:~$ setpci -s 0001:07:00.0 0.b
    4C
    root@am57xx-EVM:~$ setpci -s 0001:07:00.0 1.b
    10.
    root@am57xx-EVM:~$ setpci -s 0001:07:00.0 2.b
    41.
    root@am57xx-EVM:~$ setpci -s 0001:07:00.0 3.b
    82.
    root@am57xx-EVM:~$ setpci -s 0001:07:00.0 4.b
    46.

    请提出任何建议。  谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Chris、

    请查看 AM572x 器件勘误表、i870 PCIe 未对齐读取访问问题

    www.ti.com/.../sprz429k.pdf

    此致、
    帕维尔
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我们的理解是、该勘误表仅适用于 EP 操作、而不适用于 RC。  此外、PCI-DA7xx.c 中还有修复方法(同样仅适用于 EPS):

    /*
    * dra7xx_PCIe_EP_LEGACY_MODE:AM572x/AM571x 勘误表 i870的权变措施
    *@dra7xx:应应用权变措施的 dra7xx 器件
    *
    *将导致对非32位对齐的 PCIe 从端口进行访问
    *错误地映射到 TLP 地址和字节使能字段。 因此、
    *字节和半字不能访问字节偏移量0x1、0x2或
    * 0x3。
    *
    *为避免此问题、请将 PCIe_SS1_AXI2OCP_legacy_mode_enable 设置为1。
    *

    通过在 EP 器件树设置中设置 SYSCON-LEGACY-MODE 激活修复、如本 TI 演示中所示:

    www.linuxplumbersconf.org/.../ep framework.pdf

    考虑到这仅适用于端点操作、并且我们将 PCI 用作 RCS、因此有关此问题的 TI 配置示例仅适用于 EP、因此这似乎不是我们遇到的问题。

    还有其他建议吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Chris、

    根据我的理解、使用 TI PSDK 3.03时、您没有 TUSB7340 EP 的8位访问问题、您只有 PEX 8606 EP 有问题、这是正确的吗? 在这种情况下、问题似乎不在 PCIe RC 驱动程序中、而是在 PEX8606 (第三方 PCIe 端点)中。 因此、可能需要咨询 PEX8606支持团队。

    此致、
    帕维尔
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    不过、正确的是、我们有一个使用基于 i.MX6 ARM 的处理器的类似设计、它不存在此问题。  PEX 8606及其他所有内容均可通过非对齐8位访问进行访问、无需对驱动程序进行任何修改或解决任何问题。

    这意味着 TI 生态系统中的某个东西可能会导致问题的发生。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    对于其他任何人来说、要解决此问题、根本原因是 i870。 尽管它仅将其记录为 EP 问题、但不表示涉及 RC、并且生成的补丁仅用于 EP、但它也是 RC 操作的问题。

    我修改了 i870补丁、以便通过使用 SYSCON-LEGACY-MODE 设置的 RC 器件树配置激活它: SYSCON 传统模式=<&SCM_CONF1 0x14 3>;在 RC 设置中。

    这与原始 TI 代码不同、方法是设置 i870中记录的两个位、其中原始 TI 修复仅设置 PCIe_SS1_AXI2OCP_LEGACY_MODE_ENABLE 位、因为它们使用 SYSCON-LEGACE-MODE =<&SCM_CONF1 0x14 2>;

    下面是有关此问题的另一个帖子、希望将发生勘误文档更新:

    e2e.ti.com/.../2223582

    另一个问题是 i870补丁似乎还没有出现在4.12或4.13内核中。