[PATCH v0 00/13] PCI: Static Enumeration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Background
----------

On many architectures, PCI devices are enumerated by the BIOS prior to
the kernel booting. This is a problem if a PCI device is powered on
after the PCI subsystem has scanned the various root complexes. Whereas
PCI Hotplug devices have memory ranges reserved for them ahead of time,
no such facility exists for bridges or other endpoints.

Proposed in the upcoming patches is a mechanism similar to "static
enumeration". Via the kcmdline, the user can forcibly set secondary and
subordinate values for buses, overriding any values that the BIOS may
have set. This allows newly discovered bridges to fit into an existing
PCI tree, without causing conflicting numbers nor renumbering existing
bridges.

Next, the patches allow the user to forcibly set the memory behind a
bridge, again overriding any values the BIOS had set. This is needed to
reserve space for newly discovered endpoints' MMIO regions. The patches
employ a first-fit algorithm to pack those new MMIO BARs into the
reserved space.


Configuration
-------------

The kcmdline syntax for static enumeration is as follows:

  pci=enum=<args1>;<args2...>

Where each <arg> has the form:

  <device>@<option><option2...>

Where <device> is a PCI device described by:

  <domain>:<bus>:<slot>.<func>

And <option> is any combination of:

  B<secondary>-<subordinate>  - force secondary and subordinate bus numbers
  M<start>-<stop>  - set memory behind a bridge

All values are in hexadecimal.


Testing
-------

These patches have been tested on an x86 system that boots directly from
NVRAM. After booting to a command line, additional PCI devices were
powered. Next, a rescan was forced by echoing 1 to /sys/bus/pci/rescan;
the kernel found the new bridges and devices.


Issues
------

There are three known limitations to these patches:
  1. This only works with 32-bit PCI devices; it does not handle 64-bit
     addresses.
  2. It only works with non pre-fetched memory regions.
  3. The root filesystem must be on a non-PCI device. Reenumeration
     occurs during system initialization, prior to loading any devices.
     If an initrd normally mounts the real root filesystem from a PCI
     device, that device's addresses could change as a result of
     enumeration.


FAQs
----

Q1: Doesn't PCI Hotplug already solve this problem?
A1: From what I can tell, the existing PCI Hotplug infrastructure only
    works with PCI endpoints; it has no way to handle hot adding a
    bridge, and then later on hot adding an endpoint.

    Static enumeration can also be used in cases where the memory
    behind a bridge needs to be changed due to faulty hardware.

Q2: Why do bus numbers need to be reenumerated?
A2: Consider a bus "A", with secondary bus number 1), has two child
    buses, "B" and "C". Suppose that "B" has no grandchild buses, so
    let its bus range is [2-2]. Likewise, "C" also has no grandchild
    buses, so its bus range is [3-3]. Therefore, "A"'s bus range is
    [1-3]. Let a new bridge "D" be hot added under "B". This bridge's
    bus needs to be within its parent's bus range, but "B" has no
    space for it. If "B" were to be dynamically resized to [2-3], then
    "C"'s bus number would now be invalid.

    Any existing process that was talking to devices on "C" would need
    to be handle this sudden change in enumeration. Changes ripple
    throughout the PCI tree, as that "A" would also need to be resized.
    Obviously, this has lots of issues.

    An alternative approach, and one taken in the patches here, is to
    pre-reserve bus numbers ahead of time. If prior to user processes
    running, the kernel reads the static enumeration profile and
    changes "B"'s range to [2-3]. It can then automatically adjust "C"
    to [4-4] and thus "A" to [1-4]. Now, when bus "D" becomes active,
    it can claim bus range [3-3] without affecting any other bus.

Q3: Wouldn't the same argument of reenumerating bus numbers also apply
    to the memory window behind bridges?
A3: Yes, it would. The later patches handle this.

Q4: Why create another kernel parameter, when "pci=hpmemsize=" already
    exists?
A4: "hpmemsize" sets all bridges' memory; it does not set individual
    bridge sizes. It also does not set bus numbers.

Q5: Why use kernel parameters to specify the static enumeration profile?
A5: Because resources are allocated prior to loading drivers,
    enumeration changes must occur in drivers/pci/probe.c. The kernel
    can only access the profile from a location that does not require
    any device drivers. As such, the kernel command line fulfills these
    requirements. An additional advantage of the command line is the
    ease of disabling a profile in case of misconfiguration.

Jason Tang (13):
      PCI: Set bus's device name later
      PCI: Use child bus's number instead of max
      PCI: Add Kconfig option PCI_STATIC_ENUMERATION
      PCI: Track subordinate values in struct pci_bus
      PCI: Specify static enumeration on kcmdline
      PCI: Set secondary and subordinate bus numbers
      PCI: Calculate child's bus number based upon enumeration
      PCI: Statically specify bus memory regions
      PCI: Adjust upstream bridge memories to match static enumeration
      PCI: Invalidate resources conflicting with bridge memories
      PCI: Reassign device's MMIO BARs
      PCI: Keep searching upstream for enclosing bus
      PCI: Don't adjust settings for statically enumerated devices

 Documentation/kernel-parameters.txt |   11 +
 drivers/pci/Kconfig                 |   12 +
 drivers/pci/Makefile                |    2 +
 drivers/pci/pci.c                   |    2 +
 drivers/pci/pci.h                   |   43 +++
 drivers/pci/pci_static_enum.c       |  559 +++++++++++++++++++++++++++++++++++
 drivers/pci/probe.c                 |   45 ++-
 include/linux/pci.h                 |    7 +
 8 files changed, 675 insertions(+), 6 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux