Skip to contentSkip to conversation

pciutil: Enumerate alternative PCIe bus

PATCH In review Ruud 2 participants 3 messages Oct 7, 2015

Subsystems (2)
lore
Share & tools
lore

Ruud

author
#0 lore raw

PATCH 1/1 pciutil: Enumerate alternative PCIe bus

Start enumerating at a specific bus number, this allows accessing root complexes that do not start a busnumber 0. (e.g. Intel Corporation Xeon E5/Core internal components and root complex on second CPU).

---
 lib/generic.c    |    3 ++-
 lib/i386-ports.c |   11 +++++++++--
 2 files changed, 11 insertions(+), 3 deletions(-)
lib/generic.c +2 -1
index c219592..5ee37f5 100644
@@ -69,9 +69,10 @@ void
 pci_generic_scan(struct pci_access *a)
 {
   byte busmap[256];
+  int basebus = strtol(pci_get_param(a, "i386.basebus"),NULL,16);
 
   memset(busmap, 0, sizeof(busmap));
-  pci_generic_scan_bus(a, busmap, 0);
+  pci_generic_scan_bus(a, busmap, basebus);
 }
 
 int
lib/i386-ports.c +9 -2
index 421bbfd..1c70c58 100644
@@ -32,6 +32,13 @@
 
 static int conf12_io_enabled = -1;		/* -1=haven't tried, 0=failed, 1=succeeded */
 
+static void
+conf12_config(struct pci_access *a)
+{
+  pci_define_param(a, "i386.basebus", "0", "Start busnumber for scanning");
+}
+
+
 static int
 conf12_setup_io(struct pci_access *a)
 {
@@ -261,7 +268,7 @@ conf2_write(struct pci_dev *d, int pos, byte *buf, int len)
 struct pci_methods pm_intel_conf1 = {
   "intel-conf1",
   "Raw I/O port access using Intel conf1 interface",
-  NULL,					/* config */
+  conf12_config,		/* config */
   conf1_detect,
   conf12_init,
   conf12_cleanup,
@@ -277,7 +284,7 @@ struct pci_methods pm_intel_conf1 = {
 struct pci_methods pm_intel_conf2 = {
   "intel-conf2",
   "Raw I/O port access using Intel conf2 interface",
-  NULL,					/* config */
+  conf12_config,		/* config */
   conf2_detect,
   conf12_init,
   conf12_cleanup,
Signature · 1 line
1.7.0.4
#1 lore raw

Hello!

lib/generic.c void · line 72

Quoted 9 lines
lib/generic.c +1 -0
index c219592..5ee37f5 100644
@@ -69,9 +69,10 @@ void
 pci_generic_scan(struct pci_access *a)
 {
   byte busmap[256];
+  int basebus = strtol(pci_get_param(a, "i386.basebus"),NULL,16);

Sorry, but this is utterly wrong. This function is not specific to i386 at all.

I will add a different work-around soon.

(Also, please note that using the i386 access methods on Linux is inherently unsafe as there is no locking between accesses by different processes and by the kernel. There are available only as a last resort when everything else fails.)

Martin

author
#2 lore raw

Hi Martin,

Quoted 2 lines

Sorry, but this is utterly wrong. This function is not specific to i386 at all.

No need to say sorry, you are the expert :)

Quoted 2 lines

I will add a different work-around soon.

Thanks, looking forward to it.

Quoted 4 lines

(Also, please note that using the i386 access methods on Linux is inherently unsafe as there is no locking between accesses by different processes and by the kernel. There are available only as a last resort when everything else fails.)

I know, if you look at my other posts you will see I got some problems in hooking up an external chassis to a server. But I will not bother you with that too much. Problem is that the linux kernel will try to follow the PCIe busnumbering that the BIOS has installed. That leads to problems when the chassis contains about 12 switches that need to fit in the range the bios has set (which of course is too small and also assigns 64bit bars below 4G).

Turning knobs on the PCIe busnumbering seems to confuse the linux kernel quite a bit when it has knowledge of that switch. However when I remove (1 > remove) the switches at the root complex level, they also disappear from the sysfs. This makes it difficult to manipulate (clear) settings using the linux kernel. setpci allows to bypass the kernel, but clearly no locking is implemented on the io ports thus if the kernel decides to access the PCI configuration io ports at the same time as setpci its heading for disaster.

I will keep my fingers crossed for now, I expect the kernel not to do too much PCI config via io once the system is booted.

It would be nice to orchestrate better with the kernel however afaik there is no lowlevel interface at the sysfs level that allows to address devices that are not enumerated (e.g. by directly accessing the MMIO_BASE?) and keeps the kernel "informed". But perhaps I am wrong.

Best regards,

Ruud