ARM: kernel: bios32: implement PCI device resources claiming
Subsystems (3)
PATCH 1/2 ARM: kernel: bios32: implement PCI device resources claiming
The current ARM pcibios layer prevents PCI devices resources enablement if the PCI_PROBE_ONLY global flag is set, since on systems that require immutable PCI BARs set-up (ie probe only) the arm PCI bios layer does not assign resources, hence resources are not really checked (ie claimed) and they do not get assigned a parent, which causes pci_enable_resources to fail in turn.
If the kernel tries to enable the resources for a PCI device through pci_enable_resources, it would fail on PCI_PROBE_ONLY systems since the device resources are not claimed (ie they are not assigned) on those systems and the resource parent is left uninitialized (ie they have a dangling parent pointer).
This behaviour does not conform with the expected kernel behaviour.
When a PCI device and its resources are scanned, the detected PCI resources should be claimed in order to validate their values read from the BARs set-up and should be assigned a parent resource so that the resource hierarchy is initialized.
Resource claiming must be carried out on PCI_PROBE_ONLY systems too, since it is a method for validating resources and it has nothing to do with PCI_PROBE_ONLY flag.
This patch removes the pcibios_enable_device call from the arm bios32 implementation (which means that arm falls back to the generic weak version for its implementation, that correctly enables a device resources) and replaces it with an arm pcibios_add_device implementation, that claims resources for a device, so that the behaviour becomes compliant with the expected PCI device kernel initialization flow.
This way, resources are claimed and enabled on PCI_PROBE_ONLY systems too improving the BAR set-up validation and making the arm kernel PCI behaviour closer to other architectures.
--- arch/arm/kernel/bios32.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
arch/arm/kernel/bios32.c +16 -6
@@ -604,15 +604,25 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res, }/** -* pcibios_enable_device - Enable I/O and memory. -* @dev: PCI device to be enabled +* pcibios_add_device - Initialize device before adding it to PCI bus +* @dev: PCI device to be added */ -int pcibios_enable_device (struct pci_dev *dev,int mask) +int pcibios_add_device (struct pci_dev *dev) { -if (pci_has_flag (PCI_PROBE_ONLY )) -return 0 ; +struct resource *res; +int i; +/* +* Device resources are claimed to validate +* them and initialize their hierarchy structure +*/ +for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { + res = &dev->resource[i]; +if (res->parent || !res->flags) +continue ; +pci_claim_resource (dev, i); + } -return pci_enable_resources (dev, mask); +return 0 ; } int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
Signature · 1 line
2.2.1
PATCH 2/2 ARM64: kernel: pci: implement PCI device resources claiming
When a device is scanned and added to the PCI bus, its resources should be claimed to validate the BARs configuration and to assign them a parent resource so that the resource hierarchy can be sanity checked.
This patch adds code that carries out PCI device resources claiming to the ARM64 pcibios_add_device implementation so that device resources are claimed by the core PCI layer upon PCI device initialization on ARM64 systems.
--- arch/arm64/kernel/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
arch/arm64/kernel/pci.c +10 -0
@@ -43,8 +43,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,*/ int pcibios_add_device (struct pci_dev *dev) { +struct resource *res; +int i; + dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 ); +for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { + res = &dev->resource[i]; +if (res->parent || !res->flags) +continue ; +pci_claim_resource (dev, i); + } +return 0 ; }
Signature · 1 line
2.2.1
PATCH 2/2 ARM64: kernel: pci: implement PCI device resources claiming
Quoted 33 lines · Lorenzo Pieralisi
When a device is scanned and added to the PCI bus, its resources should be claimed to validate the BARs configuration and to assign them a parent resource so that the resource hierarchy can be sanity checked.
This patch adds code that carries out PCI device resources claiming to the ARM64
pcibios_add_deviceimplementation so that device resources are claimed by the core PCI layer upon PCI device initialization on ARM64 systems.Signed-off-by Lorenzo Pieralisi <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Will Deacon <[email protected]>Cc Liviu Dudau <[email protected]>Cc Bjorn Helgaas <[email protected]>--- arch/arm64/kernel/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+)arch/arm64/kernel/pci.c +3
-0@@ -43,8 +43,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,*/ int pcibios_add_device (struct pci_dev *dev) { +struct resource *res; +int i; + dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 );
arch/arm64/kernel/pci.c resource_size_t pcibios_align_resource(void *data, const struct resource *res, · line 60
Quoted 10 lines
arch/arm64/kernel/pci.c +7
-0+for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { + res = &dev->resource[i]; +if (res->parent || !res->flags) +continue ; +pci_claim_resource (dev, i); + } +return 0 ; }
Lorenzo/Bjorn,
I have tested this patch on top of Jayachandran's V2 patch series
(http://www.spinics.net/lists/linux-pci/msg40811.html) on AMD Seattle (w/ PROBE_ONLY and non-PROBE_ONLY mode), and your changes here works with additional changes below.
It seems that when booting w/ PROBE_ONLY case, we need to call pci_read_bridge_bases() at some point before claiming the resources of devices underneath the bridge. This is needed to determine the bridge bases (i.e. bridge io, mmio and mmio_pref bases), and update bridge resources accordingly.
---- BEGIN PATCH -----
arch/arm64/kernel/pci.c +5 -0
@@ -48,6 +48,11 @@ int pcibios_add_device(struct pci_dev *dev) dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 ); +if (pci_has_flag (PCI_PROBE_ONLY ) && + !pci_is_root_bus (dev->bus) && + !pci_bridge_bases_is_read (dev->bus)) +pci_read_bridge_bases (dev->bus); +for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { res = &dev->resource[i];if (res->parent || !res->flags)
drivers/pci/probe.c +0 -0
@@ -447,6 +447,13 @@ static void pci_read_bridge_mmio_pref(struct
pci_bus *child)
}
}
+bool pci_bridge_bases_is_read(struct pci_bus *bus) +{
+ return (bus->resource[0]->start || + bus->resource[1]->start ||
+ bus->resource[2]->start);
+}
+
void pci_read_bridge_bases(struct pci_bus *child)
{
struct pci_dev *dev = child->self;include/linux/pci.h +0 -0
@@ -798,6 +798,7 @@ void pci_device_add(struct pci_dev *dev, struct
pci_bus *bus);
unsigned int pci_scan_child_bus(struct pci_bus *bus); void pci_bus_add_device(struct pci_dev *dev);
void pci_read_bridge_bases(struct pci_bus *child);
+bool pci_bridge_bases_is_read(struct pci_bus *bus);
struct resource *pci_find_parent_resource(const struct pci_dev *dev,
struct resource *res);
u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin);
---- END PATCH -----
I'm not sure if this is the best place to be reading the bridge bases. I guess we should be able to do this when adding bridge devices.
Thanks,
Suravee
PATCH 2/2 ARM64: kernel: pci: implement PCI device resources claiming
Hi Suravee,
Quoted 52 lines · Suravee Suthikulanit
Quoted 33 lines · Lorenzo Pieralisi
When a device is scanned and added to the PCI bus, its resources should be claimed to validate the BARs configuration and to assign them a parent resource so that the resource hierarchy can be sanity checked.
This patch adds code that carries out PCI device resources claiming to the ARM64
pcibios_add_deviceimplementation so that device resources are claimed by the core PCI layer upon PCI device initialization on ARM64 systems.Signed-off-by Lorenzo Pieralisi <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Will Deacon <[email protected]>Cc Liviu Dudau <[email protected]>Cc Bjorn Helgaas <[email protected]>--- arch/arm64/kernel/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+)arch/arm64/kernel/pci.c +3
-0@@ -43,8 +43,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,*/ int pcibios_add_device (struct pci_dev *dev) { +struct resource *res; +int i; + dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 );arch/arm64/kernel/pci.c resource_size_t pcibios_align_resource(void *data, const struct resource *res, · line 60
Quoted 10 lines
arch/arm64/kernel/pci.c +7
-0+for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { + res = &dev->resource[i]; +if (res->parent || !res->flags) +continue ; +pci_claim_resource (dev, i); + } +return 0 ; }Lorenzo/Bjorn,
I have tested this patch on top of Jayachandran's V2 patch series
(http://www.spinics.net/lists/linux-pci/msg40811.html) on AMD Seattle (w/PROBE_ONLYand non-PROBE_ONLY mode), and your changes here works with additional changes below.
Quoted 5 lines
It seems that when booting w/
PROBE_ONLYcase, we need to callpci_read_bridge_bases()at some point before claiming the resources of devices underneath the bridge. This is needed to determine the bridge bases (i.e. bridge io, mmio andmmio_prefbases), and update bridge resources accordingly.
Thanks for testing, I will give it a go on Seattle, if you can drop the log you get on PROBE_ONLY (without your patch below) that would be great so that I can have a look at the issue.
Thanks,
Lorenzo
Quoted 59 lines
---- BEGIN PATCH -----
arch/arm64/kernel/pci.c +5
-0@@ -48,6 +48,11 @@ int pcibios_add_device(struct pci_dev *dev) dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 ); +if (pci_has_flag (PCI_PROBE_ONLY ) && + !pci_is_root_bus (dev->bus) && + !pci_bridge_bases_is_read (dev->bus)) +pci_read_bridge_bases (dev->bus); +for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { res = &dev->resource[i];if (res->parent || !res->flags)drivers/pci/probe.c +7
-0@@ -447,6 +447,13 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) } } +bool pci_bridge_bases_is_read (struct pci_bus *bus) +{ +return (bus->resource[0 ]->start || + bus->resource[1 ]->start || + bus->resource[2 ]->start); +} +void pci_read_bridge_bases (struct pci_bus *child) {struct pci_dev *dev = child->self;include/linux/pci.h +1
-0@@ -798,6 +798,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);unsigned int pci_scan_child_bus (struct pci_bus *bus);void pci_bus_add_device (struct pci_dev *dev);void pci_read_bridge_bases (struct pci_bus *child); +bool pci_bridge_bases_is_read (struct pci_bus *bus);struct resource *pci_find_parent_resource (const struct pci_dev *dev,struct resource *res);u8
pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin);
---- END PATCH -----I'm not sure if this is the best place to be reading the bridge bases. I guess we should be able to do this when adding bridge devices.
Thanks,
Suravee
PATCH 2/2 ARM64: kernel: pci: implement PCI device resources claiming
Quoted 12 lines · Lorenzo Pieralisi
Quoted 12 lines
Lorenzo/Bjorn,
Quoted 11 lines
I have tested this patch on top of Jayachandran's V2 patch series
(http://www.spinics.net/lists/linux-pci/msg40811.html) on AMD Seattle (w/PROBE_ONLYand non-PROBE_ONLY mode), and your changes here works with additional changes below.It seems that when booting w/
PROBE_ONLYcase, we need to callpci_read_bridge_bases()at some point before claiming the resources of devices underneath the bridge. This is needed to determine the bridge bases (i.e. bridge io, mmio andmmio_prefbases), and update bridge resources accordingly.
Quoted 7 lines
Thanks for testing, I will give it a go on Seattle, if you can drop the log you get on
PROBE_ONLY(without your patch below) that would be great so that I can have a look at the issue.Thanks,
Lorenzo
Lorenzo,
Here is the log w/ PROBE_ONLY and w/o the changes I proposed:
# dmesg
.....
PCI host bridge /smb/pcie at f0000000 ranges:
IO 0xefff0000..0xefffffff -> 0x00000000
MEM 0x40000000..0xbfffffff -> 0x40000000
MEM 0x100000000..0x7fffffffff -> 0x100000000
pci-host-generic f0000000.pcie: PCI host bridge to bus 0000:00
pci_bus 0000:00: root bus resource [bus 00-7f]
pci_bus 0000:00: root bus resource [io 0x0000-0xffff]
pci_bus 0000:00: root bus resource [mem 0x40000000-0xbfffffff]
pci_bus 0000:00: root bus resource [mem 0x100000000-0x7fffffffff]
pci 0000:00:00.0: of_irq_parse_pci() failed with rc=-19
pci 0000:00:02.0: of_irq_parse_pci() failed with rc=-19
pci 0000:01:00.0: can't claim BAR 0 [mem 0xbfe80000-0xbfefffff 64bit
pref]: no compatible bridge window
pci 0000:01:00.0: can't claim BAR 2 [io 0x0020-0x003f]: no compatible
bridge window
pci 0000:01:00.0: can't claim BAR 4 [mem 0xbff04000-0xbff07fff 64bit
pref]: no compatible bridge window
pci 0000:01:00.1: can't claim BAR 0 [mem 0xbfe00000-0xbfe7ffff 64bit
pref]: no compatible bridge window
pci 0000:01:00.1: can't claim BAR 2 [io 0x0000-0x001f]: no compatible
bridge window
pci 0000:01:00.1: can't claim BAR 4 [mem 0xbff00000-0xbff03fff 64bit
pref]: no compatible bridge window
.....# dmesg | grep ixgbe [ 7.189232] ixgbe: Intel(R) 10 Gigabit PCI Express Network Driver - version 4.0.1-k [ 7.195580] ixgbe: Copyright (c) 1999-2014 Intel Corporation. [ 7.195638] ixgbe 0000:01:00.0: can't enable device: BAR 0 [mem size 0x00080000 64bit pref] not assigned [ 7.195645] ixgbe: probe of 0000:01:00.0 failed with error -22 [ 7.195660] ixgbe 0000:01:00.1: can't enable device: BAR 0 [mem size 0x00080000 64bit pref] not assigned [ 7.195664] ixgbe: probe of 0000:01:00.1 failed with error -22
Also, here is the bridge configuration. Please note that the change I added tries to setup the bridge resource with information in _Prefetchable memory behind_ region.
# lspci -vvv -s 0:2.1
00:02.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 1a02
(prog-if 00 [Normal decode])
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-
Latency: 0
Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
I/O behind bridge: 00fff000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge:
00000000bfe00000-00000000bfffffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort-
<TAbort- <MAbort+ <SERR- <PERR-
BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
Capabilities: [50] Power Management version 3
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA
PME(D0+,D1-,D2-,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [58] Express (v2) Root Port (Slot+), MSI 00
DevCap: MaxPayload 512 bytes, PhantFunc 0
ExtTag+ RBE+
DevCtl: Report errors: Correctable- Non-Fatal- Fatal-
Unsupported-
RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 512 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq-
AuxPwr- TransPend-
LnkCap: Port #0, Speed 5GT/s, Width x8, ASPM L0s L1,
Exit Latency L0s <512ns, L1 <64us
ClockPM- Surprise- LLActRep+ BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk+
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 5GT/s, Width x4, TrErr- Train- SlotClk+
DLActive+ BWMgmt- ABWMgmt-
SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd-
HotPlug- Surprise-
Slot #0, PowerLimit 0.000W; Interlock- NoCompl+
SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt-
HPIrq- LinkChg-
Control: AttnInd Unknown, PwrInd Unknown,
Power- Interlock-
SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt-
PresDet+ Interlock-
Changed: MRL- PresDet- LinkState-
RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal-
PMEIntEna- CRSVisible+
RootCap: CRSVisible-
RootSta: PME ReqID 0000, PMEStatus- PMEPending-
DevCap2: Completion Timeout: Range ABCD, TimeoutDis+,
LTR-, OBFF Not Supported ARIFwd+
DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-,
LTR-, OBFF Disabled ARIFwd+
LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance-
SpeedDis-
Transmit Margin: Normal Operating Range,
EnterModifiedCompliance- ComplianceSOS-
Compliance De-emphasis: -6dB
LnkSta2: Current De-emphasis Level: -6dB,
EqualizationComplete-, EqualizationPhase1-
EqualizationPhase2-, EqualizationPhase3-,
LinkEqualizationRequest-
Capabilities: [a0] MSI: Enable- Count=1/1 Maskable- 64bit+
Address: 0000000000000000 Data: 0000
Capabilities: [c0] Subsystem: Advanced Micro Devices, Inc.
[AMD] Device 1234
Capabilities: [c8] HyperTransport: MSI Mapping Enable+ Fixed+
Capabilities: [100 v1] Vendor Specific Information: ID=0001
Rev=1 Len=010 <?>
Capabilities: [270 v1] #19Thanks,
Suravee
PATCH 2/2 ARM64: kernel: pci: implement PCI device resources claiming
In reply to Suravee SuthikulanitQuoted 64 lines · Suravee Suthikulanit
Quoted 33 lines · Lorenzo Pieralisi
When a device is scanned and added to the PCI bus, its resources should be claimed to validate the BARs configuration and to assign them a parent resource so that the resource hierarchy can be sanity checked.
This patch adds code that carries out PCI device resources claiming to the ARM64
pcibios_add_deviceimplementation so that device resources are claimed by the core PCI layer upon PCI device initialization on ARM64 systems.Signed-off-by Lorenzo Pieralisi <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Will Deacon <[email protected]>Cc Liviu Dudau <[email protected]>Cc Bjorn Helgaas <[email protected]>--- arch/arm64/kernel/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+)arch/arm64/kernel/pci.c +3
-0@@ -43,8 +43,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,*/ int pcibios_add_device (struct pci_dev *dev) { +struct resource *res; +int i; + dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 );arch/arm64/kernel/pci.c resource_size_t pcibios_align_resource(void *data, const struct resource *res, · line 60
Quoted 10 lines
arch/arm64/kernel/pci.c +7
-0+for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { + res = &dev->resource[i]; +if (res->parent || !res->flags) +continue ; +pci_claim_resource (dev, i); + } +return 0 ; }Lorenzo/Bjorn,
I have tested this patch on top of Jayachandran's V2 patch series
(http://www.spinics.net/lists/linux-pci/msg40811.html) on AMD Seattle (w/PROBE_ONLYand non-PROBE_ONLY mode), and your changes here works with additional changes below.It seems that when booting w/
PROBE_ONLYcase, we need to callpci_read_bridge_bases()at some point before claiming the resources of devices underneath the bridge. This is needed to determine the bridge bases (i.e. bridge io, mmio andmmio_prefbases), and update bridge resources accordingly.---- BEGIN PATCH -----
arch/arm64/kernel/pci.c +0
-0
arch/arm64/kernel/pci.c int pcibios_add_device(struct pci_dev *dev) · line 51
Quoted 4 lines
arch/arm64/kernel/pci.c +1
-0@@ -48,6 +48,11 @@ int pcibios_add_device(struct pci_dev *dev) dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 ); + if (pci_has_flag(PCI_PROBE_ONLY) &&
Does it really matter if PCI_PROBE_ONLY is set ?
arch/arm64/kernel/pci.c int pcibios_add_device(struct pci_dev *dev) · line 52
Quoted 1 line
arch/arm64/kernel/pci.c +1
-0+ !pci_is_root_bus(dev->bus) &&
This check is useless, since pci_read_bridge_bases checks that already.
arch/arm64/kernel/pci.c int pcibios_add_device(struct pci_dev *dev) · line 55
Quoted 3 lines
arch/arm64/kernel/pci.c +3
-0+ !pci_bridge_bases_is_read(dev->bus)) +pci_read_bridge_bases (dev->bus); +
Ok. Most of the archs do that in pcibios_fixup_bus, I would like to understand:
1) Should we do it on PCI_PROBE_ONLY only
2) Can we move this to generic code - ie pci_scan_child_bus (I guess answer is no, because there are corner cases I am not aware of)
If I add it to arm64 (in pcibios_fixup_bus) I have to add it to arm too, more arch specific code that has nothing arch specific in it so I am not really keen on that.
Comments appreciated.
Lorenzo
Quoted 45 lines
arch/arm64/kernel/pci.c +0
-0for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { res = &dev->resource[i];if (res->parent || !res->flags)drivers/pci/probe.c +7
-0@@ -447,6 +447,13 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) } } +bool pci_bridge_bases_is_read (struct pci_bus *bus) +{ +return (bus->resource[0 ]->start || + bus->resource[1 ]->start || + bus->resource[2 ]->start); +} +void pci_read_bridge_bases (struct pci_bus *child) {struct pci_dev *dev = child->self;include/linux/pci.h +1
-0@@ -798,6 +798,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);unsigned int pci_scan_child_bus (struct pci_bus *bus);void pci_bus_add_device (struct pci_dev *dev);void pci_read_bridge_bases (struct pci_bus *child); +bool pci_bridge_bases_is_read (struct pci_bus *bus);struct resource *pci_find_parent_resource (const struct pci_dev *dev,struct resource *res);u8
pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin);
---- END PATCH -----I'm not sure if this is the best place to be reading the bridge bases. I guess we should be able to do this when adding bridge devices.
Thanks,
Suravee
Bjorn Helgaas
maintainerPATCH 2/2 ARM64: kernel: pci: implement PCI device resources claiming
Quoted 80 lines · Lorenzo Pieralisi
Quoted 64 lines · Suravee Suthikulanit
Quoted 33 lines · Lorenzo Pieralisi
When a device is scanned and added to the PCI bus, its resources should be claimed to validate the BARs configuration and to assign them a parent resource so that the resource hierarchy can be sanity checked.
This patch adds code that carries out PCI device resources claiming to the ARM64
pcibios_add_deviceimplementation so that device resources are claimed by the core PCI layer upon PCI device initialization on ARM64 systems.Signed-off-by Lorenzo Pieralisi <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Will Deacon <[email protected]>Cc Liviu Dudau <[email protected]>Cc Bjorn Helgaas <[email protected]>--- arch/arm64/kernel/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+)arch/arm64/kernel/pci.c +3
-0@@ -43,8 +43,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,*/ int pcibios_add_device (struct pci_dev *dev) { +struct resource *res; +int i; + dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 );arch/arm64/kernel/pci.c resource_size_t pcibios_align_resource(void *data, const struct resource *res, · line 60
Quoted 10 lines
arch/arm64/kernel/pci.c +7
-0+for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { + res = &dev->resource[i]; +if (res->parent || !res->flags) +continue ; +pci_claim_resource (dev, i); + } +return 0 ; }Lorenzo/Bjorn,
I have tested this patch on top of Jayachandran's V2 patch series
(http://www.spinics.net/lists/linux-pci/msg40811.html) on AMD Seattle (w/PROBE_ONLYand non-PROBE_ONLY mode), and your changes here works with additional changes below.It seems that when booting w/
PROBE_ONLYcase, we need to callpci_read_bridge_bases()at some point before claiming the resources of devices underneath the bridge. This is needed to determine the bridge bases (i.e. bridge io, mmio andmmio_prefbases), and update bridge resources accordingly.---- BEGIN PATCH -----
arch/arm64/kernel/pci.c +0
-0arch/arm64/kernel/pci.c int pcibios_add_device(struct pci_dev *dev) · line 51
Quoted 4 lines
arch/arm64/kernel/pci.c +1
-0@@ -48,6 +48,11 @@ int pcibios_add_device(struct pci_dev *dev) dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 ); + if (pci_has_flag(PCI_PROBE_ONLY) &&Does it really matter if
PCI_PROBE_ONLYis set ?arch/arm64/kernel/pci.c int pcibios_add_device(struct pci_dev *dev) · line 52
Quoted 1 line
arch/arm64/kernel/pci.c +1
-0+ !pci_is_root_bus(dev->bus) &&This check is useless, since
pci_read_bridge_baseschecks that already.arch/arm64/kernel/pci.c int pcibios_add_device(struct pci_dev *dev) · line 55
Quoted 3 lines
arch/arm64/kernel/pci.c +3
-0+ !pci_bridge_bases_is_read(dev->bus)) +pci_read_bridge_bases (dev->bus); +
Quoted 6 lines
Ok. Most of the archs do that in
pcibios_fixup_bus, I would like to understand:1) Should we do it on
PCI_PROBE_ONLYonly
2) Can we move this to generic code - iepci_scan_child_bus(I guess answer is no, because there are corner cases I am not aware of)
In my opinion, we should call pci_read_bridge_bases() in all cases, regardless of PCI_PROBE_ONLY. pci_read_bridge_bases() doesn't *change* anything in the hardware; it only reads what's there. (It should attempt writes to learn whether I/O and prefetchable memory apertures are implemented, but those should be done as in pci_bridge_check_ranges(), where the original value is restored.)
I also think this should be done in generic code, since there's nothing architecture-specific about bridge operation.
I've been hoping to get rid of pcibios_fixup_bus() completely for years, and doing pci_read_bridge_bases() in generic code would be a big step.
No doubt there are corner cases we'll trip over, but I'm not aware of them yet.
Quoted 53 lines
If I add it to arm64 (in
pcibios_fixup_bus) I have to add it to arm too, more arch specific code that has nothing arch specific in it so I am not really keen on that.Comments appreciated.
Lorenzo
Quoted 45 lines
arch/arm64/kernel/pci.c +0
-0for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { res = &dev->resource[i];if (res->parent || !res->flags)drivers/pci/probe.c +7
-0@@ -447,6 +447,13 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) } } +bool pci_bridge_bases_is_read (struct pci_bus *bus) +{ +return (bus->resource[0 ]->start || + bus->resource[1 ]->start || + bus->resource[2 ]->start); +} +void pci_read_bridge_bases (struct pci_bus *child) {struct pci_dev *dev = child->self;include/linux/pci.h +1
-0@@ -798,6 +798,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);unsigned int pci_scan_child_bus (struct pci_bus *bus);void pci_bus_add_device (struct pci_dev *dev);void pci_read_bridge_bases (struct pci_bus *child); +bool pci_bridge_bases_is_read (struct pci_bus *bus);struct resource *pci_find_parent_resource (const struct pci_dev *dev,struct resource *res);u8
pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin);
---- END PATCH -----I'm not sure if this is the best place to be reading the bridge bases. I guess we should be able to do this when adding bridge devices.
Thanks,
Suravee
PATCH 2/2 ARM64: kernel: pci: implement PCI device resources claiming
On Wed, May 20, 2015 at 02:02:52PM +0100, Bjorn Helgaas wrote:
[...]
Quoted 30 lines
Quoted 16 lines
arch/arm64/kernel/pci.c int pcibios_add_device(struct pci_dev *dev) · line 51
Quoted 5 lines
arch/arm64/kernel/pci.c +1
-0@@ -48,6 +48,11 @@ int pcibios_add_device(struct pci_dev *dev) dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 ); + if (pci_has_flag(PCI_PROBE_ONLY) &&Does it really matter if
PCI_PROBE_ONLYis set ?arch/arm64/kernel/pci.c int pcibios_add_device(struct pci_dev *dev) · line 52
Quoted 1 line
arch/arm64/kernel/pci.c +1
-0+ !pci_is_root_bus(dev->bus) &&This check is useless, since
pci_read_bridge_baseschecks that already.arch/arm64/kernel/pci.c int pcibios_add_device(struct pci_dev *dev) · line 55
Quoted 3 lines
arch/arm64/kernel/pci.c +3
-0+ !pci_bridge_bases_is_read(dev->bus)) +pci_read_bridge_bases (dev->bus); +Quoted 6 lines
Ok. Most of the archs do that in
pcibios_fixup_bus, I would like to understand:1) Should we do it on
PCI_PROBE_ONLYonly
2) Can we move this to generic code - iepci_scan_child_bus(I guess answer is no, because there are corner cases I am not aware of)In my opinion, we should call
pci_read_bridge_bases()in all cases, regardless ofPCI_PROBE_ONLY.pci_read_bridge_bases()doesn't *change* anything in the hardware; it only reads what's there. (It should attempt writes to learn whether I/O and prefetchable memory apertures are implemented, but those should be done as inpci_bridge_check_ranges(), where the original value is restored.)
Quoted 6 lines
I also think this should be done in generic code, since there's nothing architecture-specific about bridge operation.
I've been hoping to get rid of
pcibios_fixup_bus()completely for years, and doingpci_read_bridge_bases()in generic code would be a big step.
I put together a patch to move it to pci_scan_child_bus, and to remove it from almost all archs pcibios_fixup_bus implementations, let's see how it goes.
Quoted 2 lines
No doubt there are corner cases we'll trip over, but I'm not aware of them yet.
Let's find out :), posting tomorrow.
Thanks,
Lorenzo
Bjorn Helgaas
maintainerPATCH 2/2 ARM64: kernel: pci: implement PCI device resources claiming
In reply to Lorenzo PieralisiHi Lorenzo,
Quoted 10 lines · Lorenzo Pieralisi
When a device is scanned and added to the PCI bus, its resources should be claimed to validate the BARs configuration and to assign them a parent resource so that the resource hierarchy can be sanity checked.
This patch adds code that carries out PCI device resources claiming to the ARM64
pcibios_add_deviceimplementation so that device resources are claimed by the core PCI layer upon PCI device initialization on ARM64 systems.
Quoted 5 lines
Signed-off-by Lorenzo Pieralisi <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Will Deacon <[email protected]>Cc Liviu Dudau <[email protected]>Cc Bjorn Helgaas <[email protected]>
Seems like Suravee proposed a tweak? Can you post a v2 with that incorporated if necessary?
Bjorn
Quoted 30 lines
--- arch/arm64/kernel/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+)arch/arm64/kernel/pci.c +10
-0@@ -43,8 +43,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,*/ int pcibios_add_device (struct pci_dev *dev) { +struct resource *res; +int i; + dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 ); +for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { + res = &dev->resource[i]; +if (res->parent || !res->flags) +continue ; +pci_claim_resource (dev, i); + } +return 0 ; }Signature · 1 line
2.2.1
PATCH 2/2 ARM64: kernel: pci: implement PCI device resources claiming
Hi Bjorn,
Quoted 13 lines · Bjorn Helgaas
Hi Lorenzo,
Quoted 10 lines · Lorenzo Pieralisi
When a device is scanned and added to the PCI bus, its resources should be claimed to validate the BARs configuration and to assign them a parent resource so that the resource hierarchy can be sanity checked.
This patch adds code that carries out PCI device resources claiming to the ARM64
pcibios_add_deviceimplementation so that device resources are claimed by the core PCI layer upon PCI device initialization on ARM64 systems.
Quoted 8 lines
Quoted 5 lines
Signed-off-by Lorenzo Pieralisi <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Will Deacon <[email protected]>Cc Liviu Dudau <[email protected]>Cc Bjorn Helgaas <[email protected]>Seems like Suravee proposed a tweak? Can you post a v2 with that incorporated if necessary?
I can post a v2, but I am not happy about that tweak, I want to understand why pci_read_bridge_bases has to be executed only on PCI_PROBE_ONLY systems and why it can't be done in generic code in the first place - ie pci_scan_child_bus(), I guess as I mentioned that in some archs this can trigger regressions, if you have an opinion please let me know, when we agree I will drop a v2 on the lists.
Thanks,
Lorenzo
Quoted 33 lines
Bjorn
Quoted 30 lines
--- arch/arm64/kernel/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+)arch/arm64/kernel/pci.c +10
-0@@ -43,8 +43,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,*/ int pcibios_add_device (struct pci_dev *dev) { +struct resource *res; +int i; + dev->irq =of_irq_parse_and_map_pci (dev,0 ,0 ); +for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { + res = &dev->resource[i]; +if (res->parent || !res->flags) +continue ; +pci_claim_resource (dev, i); + } +return 0 ; }Signature · 1 line
2.2.1