赞
踩
CRS全称是configuration retry status,单纯从名称上看应该是和配置访问有一定的关系,感觉又是在retry。那CRS到底是用来做什么的?其实很简单,当pcie设备还没有准备好响应配置请求时(比如自己的FW还在初始化中),如果其他设备(host)对该设备发起配置访问,将会收到状态CRS的completion包。如果此时抓trace的话,将会发现completion 包的status就是010的。
既然设备还没有准备好,返回了CRS的completion包,那么芯片和软件应该怎么处理这种情况呢?协议有下面的说明
(1)当CRS software visibility 没有使能的情况下,(即这种情况是需要硬件(RC)重发配置请求):
RC需要重发一个新的配置请求(一般芯片有一些芯片特有的reg,可以配置硬件进行重发的时间间隔和重发次数)。
(2)当CRS software visibility使能的情况,(即这种情况是需要软件(linux host driver)重发配置请求):
a.如果是对配置空间的VendorID字段进行的配置读请求,对于Vendorid字段,RC需要返回0001h的的返回值,对于其他字段需要返回全1。
b.对于配置写请求或者配置读请求,RC必须重新发送新的请求(这个就要求软件要重发了)。
既然协议规定了可以把CRS的处理给软件,那么哪些reg可以通知芯片,软件来接管处理CRS,不需要硬件重发配置请求?答案就是配置空间的CRS software visibility enable bit。
配置空间的root control reg的CRS software visibility enable bit为1时,会把CRS的completion包的处理交给软件接管。
linux kernel会把根据是否支持CRS Software Visibility这种cap来使能CRS Software Visibility bit。
那么如果使能了CRS Software Visibility,软件会进行怎么样的操作呢,下面是linux kernel对于CRS的处理:
bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l, int crs_timeout) { int delay = 1; if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l)) return false; --------(1)读取配置空间的vendorid和deviceid /* some broken boards return 0 or ~0 if a slot is empty: */ if (*l == 0xffffffff || *l == 0x00000000 || *l == 0x0000ffff || *l == 0xffff0000) return false; --------(2)判断寄存器是否是全1或者全0,低16bit是vendorid,高16bit是deviceid,如果是全1或者0,可能是slot下面没有接东西 /* * Configuration Request Retry Status. Some root ports return the * actual device ID instead of the synthetic ID (0xFFFF) required * by the PCIe spec. Ignore the device ID and only check for * (vendor id == 1). */ while ((*l & 0xffff) == 0x0001) { -------------(3)判断vendorid是否0x0001,如果为0x0001则对端设备返回了CRS的completion if (!crs_timeout) return false; msleep(delay);-------(4)延时1ms delay *= 2;-------(5)每次返回CRS的completion包后,延时时间会变成2倍。 if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))--------(5)重发配置读请求访问vendorid return false; /* Card hasn't responded in 60 seconds? Must be stuck. */ if (delay > crs_timeout) { printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not responding\n", pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); return false; } } return true; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。