PCIE枚举过程代码实现 ----转载 学习使用

PCIe在调试过程中,经常会出现扫描不到对端EP设备的问题,在问题定位过程中,了解内核中pcie枚举流程至关重要。

PCIe枚举过程一般分为三步:
1.创建根节点
2.扫描根节点下设备
3.为根节点下设备分配资源

那么如何发现设备?
从总线扫描pcie设备的函数pci_scan_child_bus开始分析

unsigned int pci_scan_child_bus(struct pci_bus *bus)
{
unsigned int devfn, pass, max = bus->busn_res.start;
struct pci_dev *dev;

dev_dbg(&bus->dev, "scanning bus\n");

/* Go find them, Rover! */
for (devfn = 0; devfn < 0x100; devfn += 8)
    pci_scan_slot(bus, devfn);

/* Reserve buses for SR-IOV capability. */
max += pci_iov_bus_range(bus);

/*
 * After performing arch-dependent fixup of the bus, look behind
 * all PCI-to-PCI bridges on this bus.
 */
if (!bus->is_added) {
    dev_dbg(&bus->dev, "fixups for bus\n");
    pcibios_fixup_bus(bus);
    bus->is_added = 1;
}

for (pass = 0; pass < 2; pass++)
    list_for_each_entry(dev, &bus->devices, bus_list) {
        if (pci_is_bridge(dev))
            max = pci_scan_bridge(bus, dev, max, pass);
    }

/*
 * Make sure a hotplug bridge has at least the minimum requested
 * number of buses.
 */
if (bus->self && bus->self->is_hotplug_bridge && pci_hotplug_bus_size) {
    if (max - bus->busn_res.start < pci_hotplug_bus_size - 1)
        max = bus->busn_res.start + pci_hotplug_bus_size - 1;
}

/*
 * We've scanned the bus and so we know all about what's on
 * the other side of any bridges that may be on this bus plus
 * any devices.
 *
 * Return how far we've got finding sub-buses.
 */
dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);
return max;

}
EXPORT_SYMBOL_GPL(pci_scan_child_bus);

该函数的核心代码为

for (devfn = 0; devfn < 0x100; devfn += 8)
pci_scan_slot(bus, devfn);

这里的bus变量来源于pci_create_root_bus,也就是创建的根总线的总线号
devfn : 设备和功能号。
这里使用的是穷举法,把所有的dev和function都尝试一次。

pci_scan_slot函数:

int pci_scan_slot(struct pci_bus *bus, int devfn)
{
unsigned fn, nr = 0;
struct pci_dev *dev;

if (only_one_child(bus) && (devfn > 0))
    return 0; /* Already scanned the entire slot */

dev = pci_scan_single_device(bus, devfn);
if (!dev)
    return 0;
if (!dev->is_added)
    nr++;

for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) {
    dev = pci_scan_single_device(bus, devfn + fn);
    if (dev) {
        if (!dev->is_added)
            nr++;
        dev->multifunction = 1;
    }
}

/* only one slot has pcie device */
if (bus->self && nr)
    pcie_aspm_init_link_state(bus->self);

return nr;

}

pci_scan_single_device:

struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
{
struct pci_dev *dev;

dev = pci_get_slot(bus, devfn);
if (dev) {
    pci_dev_put(dev);
    return dev;
}

dev = pci_scan_device(bus, devfn);
if (!dev)
    return NULL;

pci_device_add(dev, bus);

return dev;

}

核心函数为pci_scan_device:

static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
{
struct pci_dev *dev;
u32 l;

if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
    return NULL;

dev = pci_alloc_dev(bus);
if (!dev)
    return NULL;

dev->devfn = devfn;
dev->vendor = l & 0xffff;
dev->device = (l >> 16) & 0xffff;

pci_set_of_node(dev);

if (pci_setup_device(dev)) {
    pci_bus_put(dev->bus);
    kfree(dev);
    return NULL;
}

return dev;

}

while循环里每隔一段时间就会进行一次venderid的配置读写,从上述代码中可以看出,退出循环的原因会有两个

  1. config配置读写失败了 (说明链路不通)
  2. 超时没有得到响应(预留时间为60s,已经非常长了,第一点失败的可能性更大)

所以扫描不到对端设备时:
1.确认建链是否成功,建链失败,肯定扫描不到对端
2.确认对端的配置空间是否可写(对端的pcie模块是否处于解复位状态)
3.确认type0,type1,iatu等参数配置是否正确,如果正确了,确认配置访问的地址空间大小是否足够。
————————————————
版权声明:本文为CSDN博主「Hober_yao」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yhb1047818384/java/article/details/71076371

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: "pcie-xxx-02-x-d-th-footprint"是一个电子元件的标准尺寸。 首先,"pcie"表示这个尺寸是适用于PCI Express(PCIe)接口的元件。PCIe是一种计算机总线标准,用于连接电脑主板和外部设备。 接下来,"xxx"表示这个尺寸所适用的规范和版本。具体规范取决于硬件制造商和应用需求,可能是PCIe 3.0、PCIe 4.0等。 "02"表示这个尺寸的版本或修订号,通常代表了硬件标准的更新或改进。 "x"可能指的是特定尺寸的变量,可以是不同封装类型、连接器数量、针脚数目等。 "d"可能代表了器件的密度,指的是在给定的面积上有多少个引脚或连接器。 "th"表示这个尺寸是一个表面贴装型(SMT)元件,需要通过焊接技术安装在电路板上。 最后,"footprint"指的是元件的物理布局和尺寸。电子元件的脚位位置、尺寸以及间距将会按照这个标准来设计和制造。 因此,"pcie-xxx-02-x-d-th-footprint"可以被理解为一个符合PCI Express接口、特定规范和版本、特定封装类型和形状的表面贴装型电子元件的标准尺寸。这个标准尺寸指导了电路板设计师在设计和布局电路板时需要遵循的硬件规范。 ### 回答2: PCIE-XXX-02-X-D-TH是一种电子元件的封装底座或插座类型,用于安装PCI Express(PCIe)接口的电子设备上。 首先,"PCIE"代表了Peripheral Component Interconnection Express,即外设互连快速总线的缩写,它是一种高速数据传输接口标准,广泛应用于计算机、服务器、图形卡等设备。 "XXX"是具体的型号代码,代表了该电子元件的特定型号及规格。 "02"表示该元件有多个版本或系列,而"-X"代表了一个保密或未公开的特殊版本。 "D"表示该底座或插座是双排连接的,即拥有两个并列的排针或排孔。 "TH"代表Through-Hole,表示这个底座或插座是通过插针固定在电路板上的,而不是表面贴装(Surface Mount)类型。 "footprint"是指底座或插座在电路板上占据的物理空间,也可理解为底座的尺寸和布局。这个尺寸和布局信息对于设计师来说非常重要,因为它决定了元件在电路板上的布局和连线方式,也影响到整个电路的性能和稳定性。 总结来说,PCIE-XXX-02-X-D-TH-footprint表示了一种特定型号的PCIe插座,它采用双排连接,通过插针固定在电路板上,具有特定的尺寸和布局。这个信息对于电子设备的设计和生产非常关键,因为它决定了PCIe接口设备在电路板上的安装方式和连接方式。 ### 回答3: "pcie-xxx-02-x-d-th-footprint" 是一个针对 PCIe 槽位的规格标识。 PCIE 是指 PCI Express,是一种用于电脑主板上插槽的通信接口标准,用于连接外部设备,如显卡、硬盘等等。它提供了高带宽和高速度的数据传输。 而 "xxx-02-x-d-th-footprint" 用于描述 PCI Express 插槽的特征和尺寸。这个标识中的每个部分代表了具体的规格: - "xxx" 指的是 PCIe 插槽的物理尺寸和定位,例如 x1、x4、x8 或 x16 等; - "02" 指的是 PCI 版本。PCIe 标准有多个版本,每个版本之间有所不同; - "x" 是插槽的数量和布局,表示该插槽是通过 CPU 来提供扩展能力还是通过北桥芯片来提供扩展能力。例如,x1 指的是插槽数量为1, x16 指的是插槽数量为16; - "d" 是标识插槽的驱动能力,表示 PCIe 插槽能够提供的功率; - "th" 指的是插槽的连接方式,例如 "th" 可以代表固定直插插座,而 "mgc-th" 可以代表通过柔性连接器连接。 通过这样的规格标识,用户、制造商和设计师可以准确了解 PCIe 插槽的尺寸、版本、驱动能力和连接方式,以便选择合适的设备和进行正确的设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值