Hi all,
I use a mips board cav-octeon3 with 4.1.21 kernel. And there is a pci
ethernet card plugged in the board. When I run command "lspci -vv", the
following information listed:
----------------------------------------------------------------------------------
01:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet
Controller (rev 06)
Subsystem: Intel Corporation PRO/1000 PT Dual Port Server Adapter
Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr-
Stepping- SERR- FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
<TAbort- <MAbort- >SERR- <PERR- INTx-
Interrupt: pin A routed to IRQ 369
Region 0: Memory at 11b00f0000000 (32-bit, non-prefetchable)
[disabled] [size=128K]
Region 1: Memory at 11b00f0020000 (32-bit, non-prefetchable)
[disabled] [size=128K]
Region 2: I/O ports at 1000 [disabled] [size=33]
Region 3: Memory at <unassigned> (32-bit, non-prefetchable)
[disabled] [size=2]
Region 4: Memory at <unassigned> (32-bit, non-prefetchable)
[disabled] [size=2]
Region 5: Memory at <unassigned> (32-bit, non-prefetchable)
[disabled] [size=2]
Expansion ROM at <unassigned> [disabled] [size=2]
Capabilities: [c8] Power Management version 2
Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA
PME(D0+,D1-,D2-,D3hot+,D3cold-)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=1 PME-
Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+
Address: 0000000000000000 Data: 0000
Capabilities: [e0] Express (v1) Endpoint, MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s
<512ns, L1 <64us
ExtTag- AttnBtn- AttnInd- PwrInd- RBE- FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal-
Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr+ FatalErr- UnsuppReq+ AuxPwr-
TransPend-
LnkCap: Port #4, Speed 2.5GT/s, Width x4, ASPM L0s, Exit
Latency L0s <4us, L1 <64us
ClockPM- Surprise- LLActRep- BwNot- ASPMOptComp-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x4, TrErr- Train- SlotClk+
DLActive- BWMgmt- ABWMgmt-
Capabilities: [100 v1] Advanced Error Reporting
UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt-
RxOF- MalfTLP- ECRC- UnsupReq+ ACSViol-
UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt-
RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UESvrt: DLP+ SDES- TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt-
RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
AERCap: First Error Pointer: 14, GenCap- CGenEn- ChkCap- ChkEn-
Capabilities: [140 v1] Device Serial Number 00-15-17-ff-ff-de-15-e8
----------------------------------------------------------------------------------
As we can see, Region 2 has a size of 33, which is obviously wrong,
because the size should be the power of 2. And Region3 to Region5 should
not have existed.
I do some research myself and finally I find that the lspci use the
information from sysfs, which is exported by the function
"resource_show", and the region size is calculated by
"pci_resource_to_user". On mips platform, the micro
HAVE_ARCH_PCI_RESOURCE_TO_USER is defined, so the function
"pci_resource_to_user" in "arch/mips/include/asm/pci.h" is called.
----------------------------------------------------------------------------------
static inline resource_size_t resource_size(const struct resource *res)
{
return res->end - res->start + 1;
}
static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc, resource_size_t *start,
resource_size_t *end)
{
phys_addr_t size = resource_size(rsrc);
*start = fixup_bigphys_addr(rsrc->start, size);
*end = rsrc->start + size;
}
----------------------------------------------------------------------------------
In that function, the "size" is set to "end - start + 1", this is all
right. And "start" is actually set to "rsrc->start".
What confused me is that the "end" is set to "start + size".
If we replace the "size" to "end - start + 1", then the "end" is
actually set to "start + end - start + 1", which is "end + 1".
I think this is the reason why the region size is 33 rather then 32.
I have checked the latest kernel, but the code is still like that. Is
this a feature I don not understand or just a bug.
Thanks,
Rui Wang