mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
PCI changes for the v3.18 merge window:
Enumeration
- Check Vendor ID only for Config Request Retry Status (Rajat Jain)
- Enable Config Request Retry Status when supported (Rajat Jain)
- Add generic domain handling (Catalin Marinas)
- Generate uppercase hex for modalias interface class (Ricardo Ribalda Delgado)
Resource management
- Add missing MEM_64 mask in pci_assign_unassigned_bridge_resources() (Yinghai Lu)
- Increase IBM ipr SAS Crocodile BARs to at least system page size (Douglas Lehr)
PCI device hotplug
- Prevent NULL dereference during pciehp probe (Andreas Noever)
- Move _HPP & _HPX handling into core (Bjorn Helgaas)
- Apply _HPP to PCIe devices as well as PCI (Bjorn Helgaas)
- Apply _HPP/_HPX to display devices (Bjorn Helgaas)
- Preserve SERR & PARITY settings when applying _HPP/_HPX (Bjorn Helgaas)
- Preserve MPS and MRRS settings when applying _HPP/_HPX (Bjorn Helgaas)
- Apply _HPP/_HPX to all devices, not just hot-added ones (Bjorn Helgaas)
- Fix wait time in pciehp timeout message (Yinghai Lu)
- Add more pciehp Slot Control debug output (Yinghai Lu)
- Stop disabling pciehp notifications during init (Yinghai Lu)
MSI
- Remove arch_msi_check_device() (Alexander Gordeev)
- Rename pci_msi_check_device() to pci_msi_supported() (Alexander Gordeev)
- Move D0 check into pci_msi_check_device() (Alexander Gordeev)
- Remove unused kobject from struct msi_desc (Yijing Wang)
- Remove "pos" from the struct msi_desc msi_attrib (Yijing Wang)
- Add "msi_bus" sysfs MSI/MSI-X control for endpoints (Yijing Wang)
- Use __get_cached_msi_msg() instead of get_cached_msi_msg() (Yijing Wang)
- Use __read_msi_msg() instead of read_msi_msg() (Yijing Wang)
- Use __write_msi_msg() instead of write_msi_msg() (Yijing Wang)
Power management
- Drop unused runtime PM support code for PCIe ports (Rafael J. Wysocki)
- Allow PCI devices to be put into D3cold during system suspend (Rafael J. Wysocki)
AER
- Add additional AER error strings (Gong Chen)
- Make <linux/aer.h> standalone includable (Thierry Reding)
Virtualization
- Add ACS quirk for Solarflare SFC9120 & SFC9140 (Alex Williamson)
- Add ACS quirk for Intel 10G NICs (Alex Williamson)
- Add ACS quirk for AMD A88X southbridge (Marti Raudsepp)
- Remove unused pci_find_upstream_pcie_bridge(), pci_get_dma_source() (Alex Williamson)
- Add device flag helpers (Ethan Zhao)
- Assume all Mellanox devices have broken INTx masking (Gavin Shan)
Generic host bridge driver
- Fix ioport_map() for !CONFIG_GENERIC_IOMAP (Liviu Dudau)
- Add pci_register_io_range() and pci_pio_to_address() (Liviu Dudau)
- Define PCI_IOBASE as the base of virtual PCI IO space (Liviu Dudau)
- Fix the conversion of IO ranges into IO resources (Liviu Dudau)
- Add pci_get_new_domain_nr() and of_get_pci_domain_nr() (Liviu Dudau)
- Add support for parsing PCI host bridge resources from DT (Liviu Dudau)
- Add pci_remap_iospace() to map bus I/O resources (Liviu Dudau)
- Add arm64 architectural support for PCI (Liviu Dudau)
APM X-Gene
- Add APM X-Gene PCIe driver (Tanmay Inamdar)
- Add arm64 DT APM X-Gene PCIe device tree nodes (Tanmay Inamdar)
Freescale i.MX6
- Probe in module_init(), not fs_initcall() (Lucas Stach)
- Delay enabling reference clock for SS until it stabilizes (Tim Harvey)
Marvell MVEBU
- Fix uninitialized variable in mvebu_get_tgt_attr() (Thomas Petazzoni)
NVIDIA Tegra
- Make sure the PCIe PLL is really reset (Eric Yuen)
- Add error path tegra_msi_teardown_irq() cleanup (Jisheng Zhang)
- Fix extended configuration space mapping (Peter Daifuku)
- Implement resource hierarchy (Thierry Reding)
- Clear CLKREQ# enable on port disable (Thierry Reding)
- Add Tegra124 support (Thierry Reding)
ST Microelectronics SPEAr13xx
- Pass config resource through reg property (Pratyush Anand)
Synopsys DesignWare
- Use NULL instead of false (Fabio Estevam)
- Parse bus-range property from devicetree (Lucas Stach)
- Use pci_create_root_bus() instead of pci_scan_root_bus() (Lucas Stach)
- Remove pci_assign_unassigned_resources() (Lucas Stach)
- Check private_data validity in single place (Lucas Stach)
- Setup and clear exactly one MSI at a time (Lucas Stach)
- Remove open-coded bitmap operations (Lucas Stach)
- Fix configuration base address when using 'reg' (Minghuan Lian)
- Fix IO resource end address calculation (Minghuan Lian)
- Rename get_msi_data() to get_msi_addr() (Minghuan Lian)
- Add get_msi_data() to pcie_host_ops (Minghuan Lian)
- Add support for v3.65 hardware (Murali Karicheri)
- Fold struct pcie_port_info into struct pcie_port (Pratyush Anand)
TI Keystone
- Add TI Keystone PCIe driver (Murali Karicheri)
- Limit MRSS for all downstream devices (Murali Karicheri)
- Assume controller is already in RC mode (Murali Karicheri)
- Set device ID based on SoC to support multiple ports (Murali Karicheri)
Xilinx AXI
- Add Xilinx AXI PCIe driver (Srikanth Thokala)
- Fix xilinx_pcie_assign_msi() return value test (Dan Carpenter)
Miscellaneous
- Clean up whitespace (Quentin Lambert)
- Remove assignments from "if" conditions (Quentin Lambert)
- Move PCI_VENDOR_ID_VMWARE to pci_ids.h (Francesco Ruggeri)
- x86: Mark DMI tables as initialization data (Mathias Krause)
- x86: Move __init annotation to the correct place (Mathias Krause)
- x86: Mark constants of pci_mmcfg_nvidia_mcp55() as __initconst (Mathias Krause)
- x86: Constify pci_mmcfg_probes[] array (Mathias Krause)
- x86: Mark PCI BIOS initialization code as such (Mathias Krause)
- Parenthesize PCI_DEVID and PCI_VPD_LRDT_ID parameters (Megan Kamiya)
- Remove unnecessary variable in pci_add_dynid() (Tobias Klauser)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQIcBAABAgAGBQJUNWmJAAoJEFmIoMA60/r8GncP/3uHRoBrnaF6pv+S1l1p3Fs/
l1kKH91/IuAAU7VJX8pkNybFqx02topWmiVVXAzqvD01PcRLGCLjPbWl5h+y5/Ja
CHZH33AwHAmm0kt4BrOSOeHTLJhAigly2zV3P4F8jRIgyaeMoGZ6Ko4tkQUpm21k
+ohrOd4cxYkmzzCjKwsZZhKnyRNpae8FmTk3VQBPuN8DbhvFPrqo5/+GeAdSZTdS
HZHpfl2HL4095aY7uBVsZqNkjQyl6SnWwjkjLnuI8q3qA3BLgDZE/Jr8F/MNuW1V
y01JIjerFWMDFyBIkpg7moYnODy6oP3KvczwYdKGmqsJja+0MQvYhLTwD+R/yTQS
SewJA0mL3T3EJEfnFYkCiaIX27xIwk/FxHfaKPN91xgx/QM7xCVZNrU2/dXjhoX1
GqLKxOEaFHhWWTyT5Dj27I0ZcElzFZ3tIwvrHfs8y22oAuAlsAypaUgvUwRfL4CO
hOj4ITZa0t041sYWqxCoGAA9Fdp8HMzNKKS5F4mhADz4Ad9v6uPCNv/s/RoxVsbm
jhZOtPYJ0/iCA+kNVX563S8Z3VpfPI+7bBjcj2WKdzW+IlICvOKT+kvwL2Tv/rE7
w0hrNsbkgGsYbPldMx7LwCavsUtYFuNj0zoU6vkhP2jk6O2Tn5VXDmjrXH0v3iHI
v03vlUtre0bQ26fzDyLQ
=4Zv1
-----END PGP SIGNATURE-----
Merge tag 'pci-v3.18-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
"The interesting things here are:
- Turn on Config Request Retry Status Software Visibility. This
caused hangs last time, but we included a fix this time.
- Rework PCI device configuration to use _HPP/_HPX more aggressively
- Allow PCI devices to be put into D3cold during system suspend
- Add arm64 PCI support
- Add APM X-Gene host bridge driver
- Add TI Keystone host bridge driver
- Add Xilinx AXI host bridge driver
More detailed summary:
Enumeration
- Check Vendor ID only for Config Request Retry Status (Rajat Jain)
- Enable Config Request Retry Status when supported (Rajat Jain)
- Add generic domain handling (Catalin Marinas)
- Generate uppercase hex for modalias interface class (Ricardo Ribalda Delgado)
Resource management
- Add missing MEM_64 mask in pci_assign_unassigned_bridge_resources() (Yinghai Lu)
- Increase IBM ipr SAS Crocodile BARs to at least system page size (Douglas Lehr)
PCI device hotplug
- Prevent NULL dereference during pciehp probe (Andreas Noever)
- Move _HPP & _HPX handling into core (Bjorn Helgaas)
- Apply _HPP to PCIe devices as well as PCI (Bjorn Helgaas)
- Apply _HPP/_HPX to display devices (Bjorn Helgaas)
- Preserve SERR & PARITY settings when applying _HPP/_HPX (Bjorn Helgaas)
- Preserve MPS and MRRS settings when applying _HPP/_HPX (Bjorn Helgaas)
- Apply _HPP/_HPX to all devices, not just hot-added ones (Bjorn Helgaas)
- Fix wait time in pciehp timeout message (Yinghai Lu)
- Add more pciehp Slot Control debug output (Yinghai Lu)
- Stop disabling pciehp notifications during init (Yinghai Lu)
MSI
- Remove arch_msi_check_device() (Alexander Gordeev)
- Rename pci_msi_check_device() to pci_msi_supported() (Alexander Gordeev)
- Move D0 check into pci_msi_check_device() (Alexander Gordeev)
- Remove unused kobject from struct msi_desc (Yijing Wang)
- Remove "pos" from the struct msi_desc msi_attrib (Yijing Wang)
- Add "msi_bus" sysfs MSI/MSI-X control for endpoints (Yijing Wang)
- Use __get_cached_msi_msg() instead of get_cached_msi_msg() (Yijing Wang)
- Use __read_msi_msg() instead of read_msi_msg() (Yijing Wang)
- Use __write_msi_msg() instead of write_msi_msg() (Yijing Wang)
Power management
- Drop unused runtime PM support code for PCIe ports (Rafael J. Wysocki)
- Allow PCI devices to be put into D3cold during system suspend (Rafael J. Wysocki)
AER
- Add additional AER error strings (Gong Chen)
- Make <linux/aer.h> standalone includable (Thierry Reding)
Virtualization
- Add ACS quirk for Solarflare SFC9120 & SFC9140 (Alex Williamson)
- Add ACS quirk for Intel 10G NICs (Alex Williamson)
- Add ACS quirk for AMD A88X southbridge (Marti Raudsepp)
- Remove unused pci_find_upstream_pcie_bridge(), pci_get_dma_source() (Alex Williamson)
- Add device flag helpers (Ethan Zhao)
- Assume all Mellanox devices have broken INTx masking (Gavin Shan)
Generic host bridge driver
- Fix ioport_map() for !CONFIG_GENERIC_IOMAP (Liviu Dudau)
- Add pci_register_io_range() and pci_pio_to_address() (Liviu Dudau)
- Define PCI_IOBASE as the base of virtual PCI IO space (Liviu Dudau)
- Fix the conversion of IO ranges into IO resources (Liviu Dudau)
- Add pci_get_new_domain_nr() and of_get_pci_domain_nr() (Liviu Dudau)
- Add support for parsing PCI host bridge resources from DT (Liviu Dudau)
- Add pci_remap_iospace() to map bus I/O resources (Liviu Dudau)
- Add arm64 architectural support for PCI (Liviu Dudau)
APM X-Gene
- Add APM X-Gene PCIe driver (Tanmay Inamdar)
- Add arm64 DT APM X-Gene PCIe device tree nodes (Tanmay Inamdar)
Freescale i.MX6
- Probe in module_init(), not fs_initcall() (Lucas Stach)
- Delay enabling reference clock for SS until it stabilizes (Tim Harvey)
Marvell MVEBU
- Fix uninitialized variable in mvebu_get_tgt_attr() (Thomas Petazzoni)
NVIDIA Tegra
- Make sure the PCIe PLL is really reset (Eric Yuen)
- Add error path tegra_msi_teardown_irq() cleanup (Jisheng Zhang)
- Fix extended configuration space mapping (Peter Daifuku)
- Implement resource hierarchy (Thierry Reding)
- Clear CLKREQ# enable on port disable (Thierry Reding)
- Add Tegra124 support (Thierry Reding)
ST Microelectronics SPEAr13xx
- Pass config resource through reg property (Pratyush Anand)
Synopsys DesignWare
- Use NULL instead of false (Fabio Estevam)
- Parse bus-range property from devicetree (Lucas Stach)
- Use pci_create_root_bus() instead of pci_scan_root_bus() (Lucas Stach)
- Remove pci_assign_unassigned_resources() (Lucas Stach)
- Check private_data validity in single place (Lucas Stach)
- Setup and clear exactly one MSI at a time (Lucas Stach)
- Remove open-coded bitmap operations (Lucas Stach)
- Fix configuration base address when using 'reg' (Minghuan Lian)
- Fix IO resource end address calculation (Minghuan Lian)
- Rename get_msi_data() to get_msi_addr() (Minghuan Lian)
- Add get_msi_data() to pcie_host_ops (Minghuan Lian)
- Add support for v3.65 hardware (Murali Karicheri)
- Fold struct pcie_port_info into struct pcie_port (Pratyush Anand)
TI Keystone
- Add TI Keystone PCIe driver (Murali Karicheri)
- Limit MRSS for all downstream devices (Murali Karicheri)
- Assume controller is already in RC mode (Murali Karicheri)
- Set device ID based on SoC to support multiple ports (Murali Karicheri)
Xilinx AXI
- Add Xilinx AXI PCIe driver (Srikanth Thokala)
- Fix xilinx_pcie_assign_msi() return value test (Dan Carpenter)
Miscellaneous
- Clean up whitespace (Quentin Lambert)
- Remove assignments from "if" conditions (Quentin Lambert)
- Move PCI_VENDOR_ID_VMWARE to pci_ids.h (Francesco Ruggeri)
- x86: Mark DMI tables as initialization data (Mathias Krause)
- x86: Move __init annotation to the correct place (Mathias Krause)
- x86: Mark constants of pci_mmcfg_nvidia_mcp55() as __initconst (Mathias Krause)
- x86: Constify pci_mmcfg_probes[] array (Mathias Krause)
- x86: Mark PCI BIOS initialization code as such (Mathias Krause)
- Parenthesize PCI_DEVID and PCI_VPD_LRDT_ID parameters (Megan Kamiya)
- Remove unnecessary variable in pci_add_dynid() (Tobias Klauser)"
* tag 'pci-v3.18-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (109 commits)
arm64: dts: Add APM X-Gene PCIe device tree nodes
PCI: Add ACS quirk for AMD A88X southbridge devices
PCI: xgene: Add APM X-Gene PCIe driver
PCI: designware: Remove open-coded bitmap operations
PCI/MSI: Remove unnecessary temporary variable
PCI/MSI: Use __write_msi_msg() instead of write_msi_msg()
MSI/powerpc: Use __read_msi_msg() instead of read_msi_msg()
PCI/MSI: Use __get_cached_msi_msg() instead of get_cached_msi_msg()
PCI/MSI: Add "msi_bus" sysfs MSI/MSI-X control for endpoints
PCI/MSI: Remove "pos" from the struct msi_desc msi_attrib
PCI/MSI: Remove unused kobject from struct msi_desc
PCI/MSI: Rename pci_msi_check_device() to pci_msi_supported()
PCI/MSI: Move D0 check into pci_msi_check_device()
PCI/MSI: Remove arch_msi_check_device()
irqchip: armada-370-xp: Remove arch_msi_check_device()
PCI/MSI/PPC: Remove arch_msi_check_device()
arm64: Add architectural support for PCI
PCI: Add pci_remap_iospace() to map bus I/O resources
of/pci: Add support for parsing PCI host bridge resources from DT
of/pci: Add pci_get_new_domain_nr() and of_get_pci_domain_nr()
...
Conflicts:
arch/arm64/boot/dts/apm-storm.dtsi
This commit is contained in:
commit
80213c03c4
111 changed files with 4911 additions and 1333 deletions
|
|
@ -5,6 +5,8 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pci_regs.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
/* Max address size we deal with */
|
||||
|
|
@ -293,6 +295,51 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
|
||||
|
||||
/*
|
||||
* of_pci_range_to_resource - Create a resource from an of_pci_range
|
||||
* @range: the PCI range that describes the resource
|
||||
* @np: device node where the range belongs to
|
||||
* @res: pointer to a valid resource that will be updated to
|
||||
* reflect the values contained in the range.
|
||||
*
|
||||
* Returns EINVAL if the range cannot be converted to resource.
|
||||
*
|
||||
* Note that if the range is an IO range, the resource will be converted
|
||||
* using pci_address_to_pio() which can fail if it is called too early or
|
||||
* if the range cannot be matched to any host bridge IO space (our case here).
|
||||
* To guard against that we try to register the IO range first.
|
||||
* If that fails we know that pci_address_to_pio() will do too.
|
||||
*/
|
||||
int of_pci_range_to_resource(struct of_pci_range *range,
|
||||
struct device_node *np, struct resource *res)
|
||||
{
|
||||
int err;
|
||||
res->flags = range->flags;
|
||||
res->parent = res->child = res->sibling = NULL;
|
||||
res->name = np->full_name;
|
||||
|
||||
if (res->flags & IORESOURCE_IO) {
|
||||
unsigned long port;
|
||||
err = pci_register_io_range(range->cpu_addr, range->size);
|
||||
if (err)
|
||||
goto invalid_range;
|
||||
port = pci_address_to_pio(range->cpu_addr);
|
||||
if (port == (unsigned long)-1) {
|
||||
err = -EINVAL;
|
||||
goto invalid_range;
|
||||
}
|
||||
res->start = port;
|
||||
} else {
|
||||
res->start = range->cpu_addr;
|
||||
}
|
||||
res->end = res->start + range->size - 1;
|
||||
return 0;
|
||||
|
||||
invalid_range:
|
||||
res->start = (resource_size_t)OF_BAD_ADDR;
|
||||
res->end = (resource_size_t)OF_BAD_ADDR;
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/*
|
||||
|
|
@ -601,12 +648,119 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
|
|||
}
|
||||
EXPORT_SYMBOL(of_get_address);
|
||||
|
||||
#ifdef PCI_IOBASE
|
||||
struct io_range {
|
||||
struct list_head list;
|
||||
phys_addr_t start;
|
||||
resource_size_t size;
|
||||
};
|
||||
|
||||
static LIST_HEAD(io_range_list);
|
||||
static DEFINE_SPINLOCK(io_range_lock);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Record the PCI IO range (expressed as CPU physical address + size).
|
||||
* Return a negative value if an error has occured, zero otherwise
|
||||
*/
|
||||
int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
#ifdef PCI_IOBASE
|
||||
struct io_range *range;
|
||||
resource_size_t allocated_size = 0;
|
||||
|
||||
/* check if the range hasn't been previously recorded */
|
||||
spin_lock(&io_range_lock);
|
||||
list_for_each_entry(range, &io_range_list, list) {
|
||||
if (addr >= range->start && addr + size <= range->start + size) {
|
||||
/* range already registered, bail out */
|
||||
goto end_register;
|
||||
}
|
||||
allocated_size += range->size;
|
||||
}
|
||||
|
||||
/* range not registed yet, check for available space */
|
||||
if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
|
||||
/* if it's too big check if 64K space can be reserved */
|
||||
if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
|
||||
err = -E2BIG;
|
||||
goto end_register;
|
||||
}
|
||||
|
||||
size = SZ_64K;
|
||||
pr_warn("Requested IO range too big, new size set to 64K\n");
|
||||
}
|
||||
|
||||
/* add the range to the list */
|
||||
range = kzalloc(sizeof(*range), GFP_KERNEL);
|
||||
if (!range) {
|
||||
err = -ENOMEM;
|
||||
goto end_register;
|
||||
}
|
||||
|
||||
range->start = addr;
|
||||
range->size = size;
|
||||
|
||||
list_add_tail(&range->list, &io_range_list);
|
||||
|
||||
end_register:
|
||||
spin_unlock(&io_range_lock);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
phys_addr_t pci_pio_to_address(unsigned long pio)
|
||||
{
|
||||
phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
|
||||
|
||||
#ifdef PCI_IOBASE
|
||||
struct io_range *range;
|
||||
resource_size_t allocated_size = 0;
|
||||
|
||||
if (pio > IO_SPACE_LIMIT)
|
||||
return address;
|
||||
|
||||
spin_lock(&io_range_lock);
|
||||
list_for_each_entry(range, &io_range_list, list) {
|
||||
if (pio >= allocated_size && pio < allocated_size + range->size) {
|
||||
address = range->start + pio - allocated_size;
|
||||
break;
|
||||
}
|
||||
allocated_size += range->size;
|
||||
}
|
||||
spin_unlock(&io_range_lock);
|
||||
#endif
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
unsigned long __weak pci_address_to_pio(phys_addr_t address)
|
||||
{
|
||||
#ifdef PCI_IOBASE
|
||||
struct io_range *res;
|
||||
resource_size_t offset = 0;
|
||||
unsigned long addr = -1;
|
||||
|
||||
spin_lock(&io_range_lock);
|
||||
list_for_each_entry(res, &io_range_list, list) {
|
||||
if (address >= res->start && address < res->start + res->size) {
|
||||
addr = res->start - address + offset;
|
||||
break;
|
||||
}
|
||||
offset += res->size;
|
||||
}
|
||||
spin_unlock(&io_range_lock);
|
||||
|
||||
return addr;
|
||||
#else
|
||||
if (address > IO_SPACE_LIMIT)
|
||||
return (unsigned long)-1;
|
||||
|
||||
return (unsigned long) address;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int __of_address_to_resource(struct device_node *dev,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static inline int __of_pci_pci_compare(struct device_node *node,
|
||||
unsigned int data)
|
||||
|
|
@ -89,6 +91,146 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
|
||||
|
||||
/**
|
||||
* This function will try to obtain the host bridge domain number by
|
||||
* finding a property called "linux,pci-domain" of the given device node.
|
||||
*
|
||||
* @node: device tree node with the domain information
|
||||
*
|
||||
* Returns the associated domain number from DT in the range [0-0xffff], or
|
||||
* a negative value if the required property is not found.
|
||||
*/
|
||||
int of_get_pci_domain_nr(struct device_node *node)
|
||||
{
|
||||
const __be32 *value;
|
||||
int len;
|
||||
u16 domain;
|
||||
|
||||
value = of_get_property(node, "linux,pci-domain", &len);
|
||||
if (!value || len < sizeof(*value))
|
||||
return -EINVAL;
|
||||
|
||||
domain = (u16)be32_to_cpup(value);
|
||||
|
||||
return domain;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
|
||||
|
||||
#if defined(CONFIG_OF_ADDRESS)
|
||||
/**
|
||||
* of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
|
||||
* @dev: device node of the host bridge having the range property
|
||||
* @busno: bus number associated with the bridge root bus
|
||||
* @bus_max: maximum number of buses for this bridge
|
||||
* @resources: list where the range of resources will be added after DT parsing
|
||||
* @io_base: pointer to a variable that will contain on return the physical
|
||||
* address for the start of the I/O range. Can be NULL if the caller doesn't
|
||||
* expect IO ranges to be present in the device tree.
|
||||
*
|
||||
* It is the caller's job to free the @resources list.
|
||||
*
|
||||
* This function will parse the "ranges" property of a PCI host bridge device
|
||||
* node and setup the resource mapping based on its content. It is expected
|
||||
* that the property conforms with the Power ePAPR document.
|
||||
*
|
||||
* It returns zero if the range parsing has been successful or a standard error
|
||||
* value if it failed.
|
||||
*/
|
||||
int of_pci_get_host_bridge_resources(struct device_node *dev,
|
||||
unsigned char busno, unsigned char bus_max,
|
||||
struct list_head *resources, resource_size_t *io_base)
|
||||
{
|
||||
struct resource *res;
|
||||
struct resource *bus_range;
|
||||
struct of_pci_range range;
|
||||
struct of_pci_range_parser parser;
|
||||
char range_type[4];
|
||||
int err;
|
||||
|
||||
if (io_base)
|
||||
*io_base = (resource_size_t)OF_BAD_ADDR;
|
||||
|
||||
bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
|
||||
if (!bus_range)
|
||||
return -ENOMEM;
|
||||
|
||||
pr_info("PCI host bridge %s ranges:\n", dev->full_name);
|
||||
|
||||
err = of_pci_parse_bus_range(dev, bus_range);
|
||||
if (err) {
|
||||
bus_range->start = busno;
|
||||
bus_range->end = bus_max;
|
||||
bus_range->flags = IORESOURCE_BUS;
|
||||
pr_info(" No bus range found for %s, using %pR\n",
|
||||
dev->full_name, bus_range);
|
||||
} else {
|
||||
if (bus_range->end > bus_range->start + bus_max)
|
||||
bus_range->end = bus_range->start + bus_max;
|
||||
}
|
||||
pci_add_resource(resources, bus_range);
|
||||
|
||||
/* Check for ranges property */
|
||||
err = of_pci_range_parser_init(&parser, dev);
|
||||
if (err)
|
||||
goto parse_failed;
|
||||
|
||||
pr_debug("Parsing ranges property...\n");
|
||||
for_each_of_pci_range(&parser, &range) {
|
||||
/* Read next ranges element */
|
||||
if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
|
||||
snprintf(range_type, 4, " IO");
|
||||
else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
|
||||
snprintf(range_type, 4, "MEM");
|
||||
else
|
||||
snprintf(range_type, 4, "err");
|
||||
pr_info(" %s %#010llx..%#010llx -> %#010llx\n", range_type,
|
||||
range.cpu_addr, range.cpu_addr + range.size - 1,
|
||||
range.pci_addr);
|
||||
|
||||
/*
|
||||
* If we failed translation or got a zero-sized region
|
||||
* then skip this range
|
||||
*/
|
||||
if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
|
||||
continue;
|
||||
|
||||
res = kzalloc(sizeof(struct resource), GFP_KERNEL);
|
||||
if (!res) {
|
||||
err = -ENOMEM;
|
||||
goto parse_failed;
|
||||
}
|
||||
|
||||
err = of_pci_range_to_resource(&range, dev, res);
|
||||
if (err)
|
||||
goto conversion_failed;
|
||||
|
||||
if (resource_type(res) == IORESOURCE_IO) {
|
||||
if (!io_base) {
|
||||
pr_err("I/O range found for %s. Please provide an io_base pointer to save CPU base address\n",
|
||||
dev->full_name);
|
||||
err = -EINVAL;
|
||||
goto conversion_failed;
|
||||
}
|
||||
if (*io_base != (resource_size_t)OF_BAD_ADDR)
|
||||
pr_warn("More than one I/O resource converted for %s. CPU base address for old range lost!\n",
|
||||
dev->full_name);
|
||||
*io_base = range.cpu_addr;
|
||||
}
|
||||
|
||||
pci_add_resource_offset(resources, res, res->start - range.pci_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
conversion_failed:
|
||||
kfree(res);
|
||||
parse_failed:
|
||||
pci_free_resource_list(resources);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
|
||||
#endif /* CONFIG_OF_ADDRESS */
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
|
||||
static LIST_HEAD(of_pci_msi_chip_list);
|
||||
|
|
|
|||
Loading…
Reference in a new issue