PCI changes for the v3.15 merge window:

Enumeration
     - Increment max correctly in pci_scan_bridge() (Andreas Noever)
     - Clarify the "scan anyway" comment in pci_scan_bridge() (Andreas Noever)
     - Assign CardBus bus number only during the second pass (Andreas Noever)
     - Use request_resource_conflict() instead of insert_ for bus numbers (Andreas Noever)
     - Make sure bus number resources stay within their parents bounds (Andreas Noever)
     - Remove pci_fixup_parent_subordinate_busnr() (Andreas Noever)
     - Check for child busses which use more bus numbers than allocated (Andreas Noever)
     - Don't scan random busses in pci_scan_bridge() (Andreas Noever)
     - x86: Drop pcibios_scan_root() check for bus already scanned (Bjorn Helgaas)
     - x86: Use pcibios_scan_root() instead of pci_scan_bus_with_sysdata() (Bjorn Helgaas)
     - x86: Use pcibios_scan_root() instead of pci_scan_bus_on_node() (Bjorn Helgaas)
     - x86: Merge pci_scan_bus_on_node() into pcibios_scan_root() (Bjorn Helgaas)
     - x86: Drop return value of pcibios_scan_root() (Bjorn Helgaas)
 
   NUMA
     - x86: Add x86_pci_root_bus_node() to look up NUMA node from PCI bus (Bjorn Helgaas)
     - x86: Use x86_pci_root_bus_node() instead of get_mp_bus_to_node() (Bjorn Helgaas)
     - x86: Remove mp_bus_to_node[], set_mp_bus_to_node(), get_mp_bus_to_node() (Bjorn Helgaas)
     - x86: Use NUMA_NO_NODE, not -1, for unknown node (Bjorn Helgaas)
     - x86: Remove acpi_get_pxm() usage (Bjorn Helgaas)
     - ia64: Use NUMA_NO_NODE, not MAX_NUMNODES, for unknown node (Bjorn Helgaas)
     - ia64: Remove acpi_get_pxm() usage (Bjorn Helgaas)
     - ACPI: Fix acpi_get_node() prototype (Bjorn Helgaas)
 
   Resource management
     - i2o: Fix and refactor PCI space allocation (Bjorn Helgaas)
     - Add resource_contains() (Bjorn Helgaas)
     - Add %pR support for IORESOURCE_UNSET (Bjorn Helgaas)
     - Mark resources as IORESOURCE_UNSET if we can't assign them (Bjorn Helgaas)
     - Don't clear IORESOURCE_UNSET when updating BAR (Bjorn Helgaas)
     - Check IORESOURCE_UNSET before updating BAR (Bjorn Helgaas)
     - Don't try to claim IORESOURCE_UNSET resources (Bjorn Helgaas)
     - Mark 64-bit resource as IORESOURCE_UNSET if we only support 32-bit (Bjorn Helgaas)
     - Don't enable decoding if BAR hasn't been assigned an address (Bjorn Helgaas)
     - Add "weak" generic pcibios_enable_device() implementation (Bjorn Helgaas)
     - alpha, microblaze, sh, sparc, tile: Use default pcibios_enable_device() (Bjorn Helgaas)
     - s390: Use generic pci_enable_resources() (Bjorn Helgaas)
     - Don't check resource_size() in pci_bus_alloc_resource() (Bjorn Helgaas)
     - Set type in __request_region() (Bjorn Helgaas)
     - Check all IORESOURCE_TYPE_BITS in pci_bus_alloc_from_region() (Bjorn Helgaas)
     - Change pci_bus_alloc_resource() type_mask to unsigned long (Bjorn Helgaas)
     - Log IDE resource quirk in dmesg (Bjorn Helgaas)
     - Revert "[PATCH] Insert GART region into resource map" (Bjorn Helgaas)
 
   PCI device hotplug
     - Make check_link_active() non-static (Rajat Jain)
     - Use link change notifications for hot-plug and removal (Rajat Jain)
     - Enable link state change notifications (Rajat Jain)
     - Don't disable the link permanently during removal (Rajat Jain)
     - Don't check adapter or latch status while disabling (Rajat Jain)
     - Disable link notification across slot reset (Rajat Jain)
     - Ensure very fast hotplug events are also processed (Rajat Jain)
     - Add hotplug_lock to serialize hotplug events (Rajat Jain)
     - Remove a non-existent card, regardless of "surprise" capability (Rajat Jain)
     - Don't turn slot off when hot-added device already exists (Yijing Wang)
 
   MSI
     - Keep pci_enable_msi() documentation (Alexander Gordeev)
     - ahci: Fix broken single MSI fallback (Alexander Gordeev)
     - ahci, vfio: Use pci_enable_msi_range() (Alexander Gordeev)
     - Check kmalloc() return value, fix leak of name (Greg Kroah-Hartman)
     - Fix leak of msi_attrs (Greg Kroah-Hartman)
     - Fix pci_msix_vec_count() htmldocs failure (Masanari Iida)
 
   Virtualization
     - Device-specific ACS support (Alex Williamson)
 
   Freescale i.MX6
     - Wait for retraining (Marek Vasut)
 
   Marvell MVEBU
     - Use Device ID and revision from underlying endpoint (Andrew Lunn)
     - Fix incorrect size for PCI aperture resources (Jason Gunthorpe)
     - Call request_resource() on the apertures (Jason Gunthorpe)
     - Fix potential issue in range parsing (Jean-Jacques Hiblot)
 
   Renesas R-Car
     - Check platform_get_irq() return code (Ben Dooks)
     - Add error interrupt handling (Ben Dooks)
     - Fix bridge logic configuration accesses (Ben Dooks)
     - Register each instance independently (Magnus Damm)
     - Break out window size handling (Magnus Damm)
     - Make the Kconfig dependencies more generic (Magnus Damm)
 
   Synopsys DesignWare
     - Fix RC BAR to be single 64-bit non-prefetchable memory (Mohit Kumar)
 
   Miscellaneous
     - Remove unused SR-IOV VF Migration support (Bjorn Helgaas)
     - Enable INTx if BIOS left them disabled (Bjorn Helgaas)
     - Fix hex vs decimal typo in cpqhpc_probe() (Dan Carpenter)
     - Clean up par-arch object file list (Liviu Dudau)
     - Set IORESOURCE_ROM_SHADOW only for the default VGA device (Sander Eikelenboom)
     - ACPI, ARM, drm, powerpc, pcmcia, PCI: Use list_for_each_entry() for bus traversal (Yijing Wang)
     - Fix pci_bus_b() build failure (Paul Gortmaker)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJTOdAZAAoJEFmIoMA60/r8VYUQALRrReyMBk3pjRt/fKIX4Kwi
 ydSo/YJeeKTN8K93fLw8bb8bdPItJScJFTfEa4Q2SpZezR/ecGXLowisy0BBaPHK
 qtOyB8EqjkLS17GfyecIe9Nd2SIAI2De/0bchK3kDtIX1YlZB/k/tD3eCPMHDnnl
 m8c5kAHKPQYd8g01I+S8nrtGHk/A33grfYpJXPZbcqyhE0lWU3SI8KDAGbcKzNHE
 23Do0yNyd4nHIdixWlhETcNvzHn35Q/O38JJwW9Mf1aI9gusYuml6GFefCgu/iov
 lxqp3CEW7iPZgQEgNbrQ0HzWn/durL2Trd6S/Yh6f2xbm1LGYKWh3LZUFLd3AQDd
 INEpUgKsyb//nF3dtiyGnZlp0QykoqFyLo2AEDrb+ILTd4up5DeRY/m1UpjAXR5p
 QicBmrDksHrSivPmMZwLx1DFQYKjQbdx5lOqy9hQM/Jmsr+N3/l7QBrbQWXks3JZ
 NNAyn4RZHQB7UDQS/MmVPArs+JK5qaEDQD57QuOTlqgP19VY9C9E/l/aEqefjdFo
 XOAm7CwGpB/iBAkIbE6ROEDiJArigRVHEfxLYeE/jtGOdRDCD1deWk+g3S8DWD7m
 ZxWSgIVB00PMAmomczdg59YVFBhocgwPUa8/cw6yqzx2QKP4mWXIFZ/Sjau5I3tn
 WWoxXlUirZfTJc29XnVy
 =3mNS
 -----END PGP SIGNATURE-----

Merge tag 'pci-v3.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

Pull PCI changes from Bjorn Helgaas:
 "Enumeration
   - Increment max correctly in pci_scan_bridge() (Andreas Noever)
   - Clarify the "scan anyway" comment in pci_scan_bridge() (Andreas Noever)
   - Assign CardBus bus number only during the second pass (Andreas Noever)
   - Use request_resource_conflict() instead of insert_ for bus numbers (Andreas Noever)
   - Make sure bus number resources stay within their parents bounds (Andreas Noever)
   - Remove pci_fixup_parent_subordinate_busnr() (Andreas Noever)
   - Check for child busses which use more bus numbers than allocated (Andreas Noever)
   - Don't scan random busses in pci_scan_bridge() (Andreas Noever)
   - x86: Drop pcibios_scan_root() check for bus already scanned (Bjorn Helgaas)
   - x86: Use pcibios_scan_root() instead of pci_scan_bus_with_sysdata() (Bjorn Helgaas)
   - x86: Use pcibios_scan_root() instead of pci_scan_bus_on_node() (Bjorn Helgaas)
   - x86: Merge pci_scan_bus_on_node() into pcibios_scan_root() (Bjorn Helgaas)
   - x86: Drop return value of pcibios_scan_root() (Bjorn Helgaas)

  NUMA
   - x86: Add x86_pci_root_bus_node() to look up NUMA node from PCI bus (Bjorn Helgaas)
   - x86: Use x86_pci_root_bus_node() instead of get_mp_bus_to_node() (Bjorn Helgaas)
   - x86: Remove mp_bus_to_node[], set_mp_bus_to_node(), get_mp_bus_to_node() (Bjorn Helgaas)
   - x86: Use NUMA_NO_NODE, not -1, for unknown node (Bjorn Helgaas)
   - x86: Remove acpi_get_pxm() usage (Bjorn Helgaas)
   - ia64: Use NUMA_NO_NODE, not MAX_NUMNODES, for unknown node (Bjorn Helgaas)
   - ia64: Remove acpi_get_pxm() usage (Bjorn Helgaas)
   - ACPI: Fix acpi_get_node() prototype (Bjorn Helgaas)

  Resource management
   - i2o: Fix and refactor PCI space allocation (Bjorn Helgaas)
   - Add resource_contains() (Bjorn Helgaas)
   - Add %pR support for IORESOURCE_UNSET (Bjorn Helgaas)
   - Mark resources as IORESOURCE_UNSET if we can't assign them (Bjorn Helgaas)
   - Don't clear IORESOURCE_UNSET when updating BAR (Bjorn Helgaas)
   - Check IORESOURCE_UNSET before updating BAR (Bjorn Helgaas)
   - Don't try to claim IORESOURCE_UNSET resources (Bjorn Helgaas)
   - Mark 64-bit resource as IORESOURCE_UNSET if we only support 32-bit (Bjorn Helgaas)
   - Don't enable decoding if BAR hasn't been assigned an address (Bjorn Helgaas)
   - Add "weak" generic pcibios_enable_device() implementation (Bjorn Helgaas)
   - alpha, microblaze, sh, sparc, tile: Use default pcibios_enable_device() (Bjorn Helgaas)
   - s390: Use generic pci_enable_resources() (Bjorn Helgaas)
   - Don't check resource_size() in pci_bus_alloc_resource() (Bjorn Helgaas)
   - Set type in __request_region() (Bjorn Helgaas)
   - Check all IORESOURCE_TYPE_BITS in pci_bus_alloc_from_region() (Bjorn Helgaas)
   - Change pci_bus_alloc_resource() type_mask to unsigned long (Bjorn Helgaas)
   - Log IDE resource quirk in dmesg (Bjorn Helgaas)
   - Revert "[PATCH] Insert GART region into resource map" (Bjorn Helgaas)

  PCI device hotplug
   - Make check_link_active() non-static (Rajat Jain)
   - Use link change notifications for hot-plug and removal (Rajat Jain)
   - Enable link state change notifications (Rajat Jain)
   - Don't disable the link permanently during removal (Rajat Jain)
   - Don't check adapter or latch status while disabling (Rajat Jain)
   - Disable link notification across slot reset (Rajat Jain)
   - Ensure very fast hotplug events are also processed (Rajat Jain)
   - Add hotplug_lock to serialize hotplug events (Rajat Jain)
   - Remove a non-existent card, regardless of "surprise" capability (Rajat Jain)
   - Don't turn slot off when hot-added device already exists (Yijing Wang)

  MSI
   - Keep pci_enable_msi() documentation (Alexander Gordeev)
   - ahci: Fix broken single MSI fallback (Alexander Gordeev)
   - ahci, vfio: Use pci_enable_msi_range() (Alexander Gordeev)
   - Check kmalloc() return value, fix leak of name (Greg Kroah-Hartman)
   - Fix leak of msi_attrs (Greg Kroah-Hartman)
   - Fix pci_msix_vec_count() htmldocs failure (Masanari Iida)

  Virtualization
   - Device-specific ACS support (Alex Williamson)

  Freescale i.MX6
   - Wait for retraining (Marek Vasut)

  Marvell MVEBU
   - Use Device ID and revision from underlying endpoint (Andrew Lunn)
   - Fix incorrect size for PCI aperture resources (Jason Gunthorpe)
   - Call request_resource() on the apertures (Jason Gunthorpe)
   - Fix potential issue in range parsing (Jean-Jacques Hiblot)

  Renesas R-Car
   - Check platform_get_irq() return code (Ben Dooks)
   - Add error interrupt handling (Ben Dooks)
   - Fix bridge logic configuration accesses (Ben Dooks)
   - Register each instance independently (Magnus Damm)
   - Break out window size handling (Magnus Damm)
   - Make the Kconfig dependencies more generic (Magnus Damm)

  Synopsys DesignWare
   - Fix RC BAR to be single 64-bit non-prefetchable memory (Mohit Kumar)

  Miscellaneous
   - Remove unused SR-IOV VF Migration support (Bjorn Helgaas)
   - Enable INTx if BIOS left them disabled (Bjorn Helgaas)
   - Fix hex vs decimal typo in cpqhpc_probe() (Dan Carpenter)
   - Clean up par-arch object file list (Liviu Dudau)
   - Set IORESOURCE_ROM_SHADOW only for the default VGA device (Sander Eikelenboom)
   - ACPI, ARM, drm, powerpc, pcmcia, PCI: Use list_for_each_entry() for bus traversal (Yijing Wang)
   - Fix pci_bus_b() build failure (Paul Gortmaker)"

* tag 'pci-v3.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (108 commits)
  Revert "[PATCH] Insert GART region into resource map"
  PCI: Log IDE resource quirk in dmesg
  PCI: Change pci_bus_alloc_resource() type_mask to unsigned long
  PCI: Check all IORESOURCE_TYPE_BITS in pci_bus_alloc_from_region()
  resources: Set type in __request_region()
  PCI: Don't check resource_size() in pci_bus_alloc_resource()
  s390/PCI: Use generic pci_enable_resources()
  tile PCI RC: Use default pcibios_enable_device()
  sparc/PCI: Use default pcibios_enable_device() (Leon only)
  sh/PCI: Use default pcibios_enable_device()
  microblaze/PCI: Use default pcibios_enable_device()
  alpha/PCI: Use default pcibios_enable_device()
  PCI: Add "weak" generic pcibios_enable_device() implementation
  PCI: Don't enable decoding if BAR hasn't been assigned an address
  PCI: Enable INTx in pci_reenable_device() only when MSI/MSI-X not enabled
  PCI: Mark 64-bit resource as IORESOURCE_UNSET if we only support 32-bit
  PCI: Don't try to claim IORESOURCE_UNSET resources
  PCI: Check IORESOURCE_UNSET before updating BAR
  PCI: Don't clear IORESOURCE_UNSET when updating BAR
  PCI: Mark resources as IORESOURCE_UNSET if we can't assign them
  ...

Conflicts:
	arch/x86/include/asm/topology.h
	drivers/ata/ahci.c
This commit is contained in:
Linus Torvalds 2014-04-01 15:14:04 -07:00
commit 4b1779c2cf
68 changed files with 942 additions and 862 deletions

View File

@ -68,10 +68,6 @@ To disable SR-IOV capability:
echo 0 > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
To notify SR-IOV core of Virtual Function Migration:
(a) In the driver:
irqreturn_t pci_sriov_migration(struct pci_dev *dev);
3.2 Usage example
Following piece of code illustrates the usage of the SR-IOV API.

View File

@ -254,12 +254,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
}
}
int
pcibios_enable_device(struct pci_dev *dev, int mask)
{
return pci_enable_resources(dev, mask);
}
/*
* If we set up a device for bus mastering, we need to check the latency
* timer as certain firmware forgets to set it properly, as seen

View File

@ -19,7 +19,7 @@
static int debug_pci;
/*
* We can't use pci_find_device() here since we are
* We can't use pci_get_device() here since we are
* called from interrupt context.
*/
static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, int warn)
@ -57,13 +57,10 @@ static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, in
void pcibios_report_status(u_int status_mask, int warn)
{
struct list_head *l;
list_for_each(l, &pci_root_buses) {
struct pci_bus *bus = pci_bus_b(l);
struct pci_bus *bus;
list_for_each_entry(bus, &pci_root_buses, node)
pcibios_bus_report_status(bus, status_mask, warn);
}
}
/*

View File

@ -88,7 +88,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
/* Depth-First Search on bus tree */
for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
bus = pci_bus_b(ln);
bus = list_entry(ln, struct pci_bus, node);
if ((dev = bus->self)) {
for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
r = &dev->resource[idx];

View File

@ -1140,11 +1140,13 @@ sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
#ifdef CONFIG_NUMA
{
int node = ioc->node;
struct page *page;
page = alloc_pages_exact_node(ioc->node == MAX_NUMNODES ?
numa_node_id() : ioc->node, flags,
get_order(size));
if (node == NUMA_NO_NODE)
node = numa_node_id();
page = alloc_pages_exact_node(node, flags, get_order(size));
if (unlikely(!page))
return NULL;
@ -1914,7 +1916,7 @@ ioc_show(struct seq_file *s, void *v)
seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n",
ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF));
#ifdef CONFIG_NUMA
if (ioc->node != MAX_NUMNODES)
if (ioc->node != NUMA_NO_NODE)
seq_printf(s, "NUMA node : %d\n", ioc->node);
#endif
seq_printf(s, "IOVA size : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024));
@ -2015,31 +2017,19 @@ sba_connect_bus(struct pci_bus *bus)
printk(KERN_WARNING "No IOC for PCI Bus %04x:%02x in ACPI\n", pci_domain_nr(bus), bus->number);
}
#ifdef CONFIG_NUMA
static void __init
sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
{
#ifdef CONFIG_NUMA
unsigned int node;
int pxm;
ioc->node = MAX_NUMNODES;
pxm = acpi_get_pxm(handle);
if (pxm < 0)
return;
node = pxm_to_node(pxm);
if (node >= MAX_NUMNODES || !node_online(node))
return;
node = acpi_get_node(handle);
if (node != NUMA_NO_NODE && !node_online(node))
node = NUMA_NO_NODE;
ioc->node = node;
return;
}
#else
#define sba_map_ioc_to_node(ioc, handle)
#endif
}
static int
acpi_sba_ioc_add(struct acpi_device *device,

View File

@ -98,7 +98,7 @@ struct pci_controller {
struct acpi_device *companion;
void *iommu;
int segment;
int node; /* nearest node with memory or -1 for global allocation */
int node; /* nearest node with memory or NUMA_NO_NODE for global allocation */
void *platform_data;
};

View File

@ -799,14 +799,9 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
* ACPI based hotplug CPU support
*/
#ifdef CONFIG_ACPI_HOTPLUG_CPU
static
int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
static int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
{
#ifdef CONFIG_ACPI_NUMA
int pxm_id;
int nid;
pxm_id = acpi_get_pxm(handle);
/*
* We don't have cpu-only-node hotadd. But if the system equips
* SRAT table, pxm is already found and node is ready.
@ -814,11 +809,10 @@ int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
* This code here is for the system which doesn't have full SRAT
* table for possible cpus.
*/
nid = acpi_map_pxm_to_node(pxm_id);
node_cpuid[cpu].phys_id = physid;
node_cpuid[cpu].nid = nid;
node_cpuid[cpu].nid = acpi_get_node(handle);
#endif
return (0);
return 0;
}
int additional_cpus __initdata = -1;
@ -925,7 +919,7 @@ static acpi_status acpi_map_iosapic(acpi_handle handle, u32 depth,
union acpi_object *obj;
struct acpi_madt_io_sapic *iosapic;
unsigned int gsi_base;
int pxm, node;
int node;
/* Only care about objects w/ a method that returns the MADT */
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
@ -952,17 +946,9 @@ static acpi_status acpi_map_iosapic(acpi_handle handle, u32 depth,
kfree(buffer.pointer);
/*
* OK, it's an IOSAPIC MADT entry, look for a _PXM value to tell
* us which node to associate this with.
*/
pxm = acpi_get_pxm(handle);
if (pxm < 0)
return AE_OK;
node = pxm_to_node(pxm);
if (node >= MAX_NUMNODES || !node_online(node) ||
/* OK, it's an IOSAPIC MADT entry; associate it with a node */
node = acpi_get_node(handle);
if (node == NUMA_NO_NODE || !node_online(node) ||
cpumask_empty(cpumask_of_node(node)))
return AE_OK;

View File

@ -5,6 +5,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/vgaarb.h>
#include <asm/machvec.h>
@ -19,9 +20,10 @@
* IORESOURCE_ROM_SHADOW is used to associate the boot video
* card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
* is marked here since the boot video device will be the only enabled
* video device at this point.
* See pci_map_rom() for use of this flag. Before marking the device
* with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
* by either arch cde or vga-arbitration, if so only apply the fixup to this
* already determined primary video card.
*/
static void pci_fixup_video(struct pci_dev *pdev)
@ -35,9 +37,6 @@ static void pci_fixup_video(struct pci_dev *pdev)
return;
/* Maybe, this machine supports legacy memory map. */
if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
return;
/* Is VGA routed to us? */
bus = pdev->bus;
while (bus) {
@ -60,10 +59,14 @@ static void pci_fixup_video(struct pci_dev *pdev)
}
bus = bus->parent;
}
pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
if (!vga_default_device() || pdev == vga_default_device()) {
pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
vga_set_default_device(pdev);
}
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video);

View File

@ -126,7 +126,6 @@ static struct pci_controller *alloc_pci_controller(int seg)
return NULL;
controller->segment = seg;
controller->node = -1;
return controller;
}
@ -430,19 +429,14 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
struct pci_root_info *info = NULL;
int busnum = root->secondary.start;
struct pci_bus *pbus;
int pxm, ret;
int ret;
controller = alloc_pci_controller(domain);
if (!controller)
return NULL;
controller->companion = device;
pxm = acpi_get_pxm(device->handle);
#ifdef CONFIG_NUMA
if (pxm >= 0)
controller->node = pxm_to_node(pxm);
#endif
controller->node = acpi_get_node(device->handle);
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {

View File

@ -1294,11 +1294,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
return pci_enable_resources(dev, mask);
}
static void pcibios_setup_phb_resources(struct pci_controller *hose,
struct list_head *resources)
{

View File

@ -208,7 +208,6 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
unsigned long in_devfn)
{
struct pci_controller* hose;
struct list_head *ln;
struct pci_bus *bus = NULL;
struct device_node *hose_node;
@ -230,8 +229,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
* used on pre-domains setup. We return the first match
*/
for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
bus = pci_bus_b(ln);
list_for_each_entry(bus, &pci_root_buses, node) {
if (in_bus >= bus->number && in_bus <= bus->busn_res.end)
break;
bus = NULL;

View File

@ -37,15 +37,15 @@ find_bus_among_children(struct pci_bus *bus,
struct device_node *dn)
{
struct pci_bus *child = NULL;
struct list_head *tmp;
struct pci_bus *tmp;
struct device_node *busdn;
busdn = pci_bus_to_OF_node(bus);
if (busdn == dn)
return bus;
list_for_each(tmp, &bus->children) {
child = find_bus_among_children(pci_bus_b(tmp), dn);
list_for_each_entry(tmp, &bus->children, node) {
child = find_bus_among_children(tmp, dn);
if (child)
break;
};

View File

@ -686,27 +686,13 @@ int pcibios_add_device(struct pci_dev *pdev)
int pcibios_enable_device(struct pci_dev *pdev, int mask)
{
struct zpci_dev *zdev = get_zdev(pdev);
struct resource *res;
u16 cmd;
int i;
zdev->pdev = pdev;
zpci_debug_init_device(zdev);
zpci_fmb_enable_device(zdev);
zpci_map_resources(zdev);
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
for (i = 0; i < PCI_BAR_COUNT; i++) {
res = &pdev->resource[i];
if (res->flags & IORESOURCE_IO)
return -EINVAL;
if (res->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
pci_write_config_word(pdev, PCI_COMMAND, cmd);
return 0;
return pci_enable_resources(pdev, mask);
}
void pcibios_disable_device(struct pci_dev *pdev)

View File

@ -186,11 +186,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
return start;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
return pci_enable_resources(dev, mask);
}
static void __init
pcibios_bus_report_status_early(struct pci_channel *hose,
int top_bus, int current_bus,

View File

@ -99,11 +99,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
return res->start;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
return pci_enable_resources(dev, mask);
}
/* in/out routines taken from pcic.c
*
* This probably belongs here rather than ioport.c because

View File

@ -1064,18 +1064,6 @@ char *__init pcibios_setup(char *str)
return str;
}
/*
* Enable memory address decoding, as appropriate, for the
* device described by the 'dev' struct.
*
* This is called from the generic PCI layer, and can be called
* for bridges or endpoints.
*/
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
return pci_enable_resources(dev, mask);
}
/*
* Called for each device after PCI setup is done.
* We initialize the PCI device capabilities conservatively, assuming that

View File

@ -26,11 +26,6 @@ extern int pci_routeirq;
extern int noioapicquirk;
extern int noioapicreroute;
/* scan a bus after allocating a pci_sysdata for it */
extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
int node);
extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI_DOMAINS
@ -70,7 +65,7 @@ extern unsigned long pci_mem_start;
extern int pcibios_enabled;
void pcibios_config_init(void);
struct pci_bus *pcibios_scan_root(int bus);
void pcibios_scan_root(int bus);
void pcibios_set_master(struct pci_dev *dev);
void pcibios_penalize_isa_irq(int irq, int active);

View File

@ -132,19 +132,7 @@ static inline void arch_fix_phys_package_id(int num, u32 slot)
}
struct pci_bus;
int x86_pci_root_bus_node(int bus);
void x86_pci_root_bus_resources(int bus, struct list_head *resources);
#ifdef CONFIG_NUMA
extern int get_mp_bus_to_node(int busnum);
extern void set_mp_bus_to_node(int busnum, int node);
#else
static inline int get_mp_bus_to_node(int busnum)
{
return 0;
}
static inline void set_mp_bus_to_node(int busnum, int node)
{
}
#endif
#endif /* _ASM_X86_TOPOLOGY_H */

View File

@ -218,9 +218,8 @@ static void teardown_mcfg_map(struct pci_root_info *info)
}
#endif
static acpi_status
resource_to_addr(struct acpi_resource *resource,
struct acpi_resource_address64 *addr)
static acpi_status resource_to_addr(struct acpi_resource *resource,
struct acpi_resource_address64 *addr)
{
acpi_status status;
struct acpi_resource_memory24 *memory24;
@ -265,8 +264,7 @@ resource_to_addr(struct acpi_resource *resource,
return AE_ERROR;
}
static acpi_status
count_resource(struct acpi_resource *acpi_res, void *data)
static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
{
struct pci_root_info *info = data;
struct acpi_resource_address64 addr;
@ -278,8 +276,7 @@ count_resource(struct acpi_resource *acpi_res, void *data)
return AE_OK;
}
static acpi_status
setup_resource(struct acpi_resource *acpi_res, void *data)
static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
{
struct pci_root_info *info = data;
struct resource *res;
@ -435,9 +432,9 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)
__release_pci_root_info(info);
}
static void
probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
int busnum, int domain)
static void probe_pci_root_info(struct pci_root_info *info,
struct acpi_device *device,
int busnum, int domain)
{
size_t size;
@ -473,16 +470,13 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
struct pci_root_info *info = NULL;
struct pci_root_info *info;
int domain = root->segment;
int busnum = root->secondary.start;
LIST_HEAD(resources);
struct pci_bus *bus = NULL;
struct pci_bus *bus;
struct pci_sysdata *sd;
int node;
#ifdef CONFIG_ACPI_NUMA
int pxm;
#endif
if (pci_ignore_seg)
domain = 0;
@ -494,19 +488,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
return NULL;
}
node = -1;
#ifdef CONFIG_ACPI_NUMA
pxm = acpi_get_pxm(device->handle);
if (pxm >= 0)
node = pxm_to_node(pxm);
if (node != -1)
set_mp_bus_to_node(busnum, node);
else
#endif
node = get_mp_bus_to_node(busnum);
node = acpi_get_node(device->handle);
if (node == NUMA_NO_NODE)
node = x86_pci_root_bus_node(busnum);
if (node != -1 && !node_online(node))
node = -1;
if (node != NUMA_NO_NODE && !node_online(node))
node = NUMA_NO_NODE;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
@ -519,15 +506,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
sd->domain = domain;
sd->node = node;
sd->companion = device;
/*
* Maybe the desired pci bus has been already scanned. In such case
* it is unnecessary to scan the pci bus with the given domain,busnum.
*/
bus = pci_find_bus(domain, busnum);
if (bus) {
/*
* If the desired bus exits, the content of bus->sysdata will
* be replaced by sd.
* If the desired bus has been scanned already, replace
* its bus->sysdata.
*/
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(info);
@ -572,15 +556,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
pcie_bus_configure_settings(child);
}
if (bus && node != -1) {
#ifdef CONFIG_ACPI_NUMA
if (pxm >= 0)
dev_printk(KERN_DEBUG, &bus->dev,
"on NUMA node %d (pxm %d)\n", node, pxm);
#else
if (bus && node != NUMA_NO_NODE)
dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
#endif
}
return bus;
}

View File

@ -44,15 +44,6 @@ static struct pci_root_info __init *find_pci_root_info(int node, int link)
return NULL;
}
static void __init set_mp_bus_range_to_node(int min_bus, int max_bus, int node)
{
#ifdef CONFIG_NUMA
int j;
for (j = min_bus; j <= max_bus; j++)
set_mp_bus_to_node(j, node);
#endif
}
/**
* early_fill_mp_bus_to_node()
* called before pcibios_scan_root and pci_scan_bus
@ -117,7 +108,6 @@ static int __init early_fill_mp_bus_info(void)
min_bus = (reg >> 16) & 0xff;
max_bus = (reg >> 24) & 0xff;
node = (reg >> 4) & 0x07;
set_mp_bus_range_to_node(min_bus, max_bus, node);
link = (reg >> 8) & 0x03;
info = alloc_pci_root_info(min_bus, max_bus, node, link);

View File

@ -10,9 +10,6 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
{
struct pci_root_info *info;
if (list_empty(&pci_root_infos))
return NULL;
list_for_each_entry(info, &pci_root_infos, list)
if (info->busn.start == bus)
return info;
@ -20,6 +17,16 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
return NULL;
}
int x86_pci_root_bus_node(int bus)
{
struct pci_root_info *info = x86_find_pci_root_info(bus);
if (!info)
return NUMA_NO_NODE;
return info->node;
}
void x86_pci_root_bus_resources(int bus, struct list_head *resources)
{
struct pci_root_info *info = x86_find_pci_root_info(bus);

View File

@ -456,19 +456,25 @@ void __init dmi_check_pciprobe(void)
dmi_check_system(pciprobe_dmi_table);
}
struct pci_bus *pcibios_scan_root(int busnum)
void pcibios_scan_root(int busnum)
{
struct pci_bus *bus = NULL;
struct pci_bus *bus;
struct pci_sysdata *sd;
LIST_HEAD(resources);
while ((bus = pci_find_next_bus(bus)) != NULL) {
if (bus->number == busnum) {
/* Already scanned */
return bus;
}
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
if (!sd) {
printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busnum);
return;
}
sd->node = x86_pci_root_bus_node(busnum);
x86_pci_root_bus_resources(busnum, &resources);
printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
if (!bus) {
pci_free_resource_list(&resources);
kfree(sd);
}
return pci_scan_bus_on_node(busnum, &pci_root_ops,
get_mp_bus_to_node(busnum));
}
void __init pcibios_set_cache_line_size(void)
@ -677,105 +683,3 @@ int pci_ext_cfg_avail(void)
else
return 0;
}
struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
{
LIST_HEAD(resources);
struct pci_bus *bus = NULL;
struct pci_sysdata *sd;
/*
* Allocate per-root-bus (not per bus) arch-specific data.
* TODO: leak; this memory is never freed.
* It's arguable whether it's worth the trouble to care.
*/
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
if (!sd) {
printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
return NULL;
}
sd->node = node;
x86_pci_root_bus_resources(busno, &resources);
printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno);
bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
if (!bus) {
pci_free_resource_list(&resources);
kfree(sd);
}
return bus;
}
struct pci_bus *pci_scan_bus_with_sysdata(int busno)
{
return pci_scan_bus_on_node(busno, &pci_root_ops, -1);
}
/*
* NUMA info for PCI busses
*
* Early arch code is responsible for filling in reasonable values here.
* A node id of "-1" means "use current node". In other words, if a bus
* has a -1 node id, it's not tightly coupled to any particular chunk
* of memory (as is the case on some Nehalem systems).
*/
#ifdef CONFIG_NUMA
#define BUS_NR 256
#ifdef CONFIG_X86_64
static int mp_bus_to_node[BUS_NR] = {
[0 ... BUS_NR - 1] = -1
};
void set_mp_bus_to_node(int busnum, int node)
{
if (busnum >= 0 && busnum < BUS_NR)
mp_bus_to_node[busnum] = node;
}
int get_mp_bus_to_node(int busnum)
{
int node = -1;
if (busnum < 0 || busnum > (BUS_NR - 1))
return node;
node = mp_bus_to_node[busnum];
/*
* let numa_node_id to decide it later in dma_alloc_pages
* if there is no ram on that node
*/
if (node != -1 && !node_online(node))
node = -1;
return node;
}
#else /* CONFIG_X86_32 */
static int mp_bus_to_node[BUS_NR] = {
[0 ... BUS_NR - 1] = -1
};
void set_mp_bus_to_node(int busnum, int node)
{
if (busnum >= 0 && busnum < BUS_NR)
mp_bus_to_node[busnum] = (unsigned char) node;
}
int get_mp_bus_to_node(int busnum)
{
int node;
if (busnum < 0 || busnum > (BUS_NR - 1))
return 0;
node = mp_bus_to_node[busnum];
return node;
}
#endif /* CONFIG_X86_32 */
#endif /* CONFIG_NUMA */

View File

@ -25,9 +25,9 @@ static void pci_fixup_i450nx(struct pci_dev *d)
dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno,
suba, subb);
if (busno)
pci_scan_bus_with_sysdata(busno); /* Bus A */
pcibios_scan_root(busno); /* Bus A */
if (suba < subb)
pci_scan_bus_with_sysdata(suba+1); /* Bus B */
pcibios_scan_root(suba+1); /* Bus B */
}
pcibios_last_bus = -1;
}
@ -42,7 +42,7 @@ static void pci_fixup_i450gx(struct pci_dev *d)
u8 busno;
pci_read_config_byte(d, 0x4a, &busno);
dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno);
pci_scan_bus_with_sysdata(busno);
pcibios_scan_root(busno);
pcibios_last_bus = -1;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
@ -313,9 +313,10 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_r
* IORESOURCE_ROM_SHADOW is used to associate the boot video
* card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
* is marked here since the boot video device will be the only enabled
* video device at this point.
* See pci_map_rom() for use of this flag. Before marking the device
* with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
* by either arch cde or vga-arbitration, if so only apply the fixup to this
* already determined primary video card.
*/
static void pci_fixup_video(struct pci_dev *pdev)
@ -346,12 +347,13 @@ static void pci_fixup_video(struct pci_dev *pdev)
}
bus = bus->parent;
}
pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
if (!vga_default_device())
if (!vga_default_device() || pdev == vga_default_device()) {
pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
vga_set_default_device(pdev);
}
}
}
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,

View File

@ -136,13 +136,9 @@ static void __init pirq_peer_trick(void)
busmap[e->bus] = 1;
}
for (i = 1; i < 256; i++) {
int node;
if (!busmap[i] || pci_find_bus(0, i))
continue;
node = get_mp_bus_to_node(i);
if (pci_scan_bus_on_node(i, &pci_root_ops, node))
printk(KERN_INFO "PCI: Discovered primary peer "
"bus %02x [IRQ]\n", i);
pcibios_scan_root(i);
}
pcibios_last_bus = -1;
}

View File

@ -37,19 +37,17 @@ int __init pci_legacy_init(void)
void pcibios_scan_specific_bus(int busn)
{
int devfn;
long node;
u32 l;
if (pci_find_bus(0, busn))
return;
node = get_mp_bus_to_node(busn);
for (devfn = 0; devfn < 256; devfn += 8) {
if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) &&
l != 0x0000 && l != 0xffff) {
DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);
printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn);
pci_scan_bus_on_node(busn, &pci_root_ops, node);
pcibios_scan_root(busn);
return;
}
}

View File

@ -135,11 +135,11 @@ static void pci_fixup_i450nx(struct pci_dev *d)
pxb, busno, suba, subb);
if (busno) {
/* Bus A */
pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
pcibios_scan_root(QUADLOCAL2BUS(quad, busno));
}
if (suba < subb) {
/* Bus B */
pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1));
pcibios_scan_root(QUADLOCAL2BUS(quad, suba+1));
}
}
pcibios_last_bus = -1;
@ -159,7 +159,7 @@ int __init pci_numaq_init(void)
continue;
printk("Scanning PCI bus %d for quad %d\n",
QUADLOCAL2BUS(quad,0), quad);
pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0));
pcibios_scan_root(QUADLOCAL2BUS(quad, 0));
}
return 0;
}

View File

@ -78,8 +78,8 @@ int __init pci_visws_init(void)
"bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0);
raw_pci_ops = &pci_direct_conf1;
pci_scan_bus_with_sysdata(pci_bus0);
pci_scan_bus_with_sysdata(pci_bus1);
pcibios_scan_root(pci_bus0);
pcibios_scan_root(pci_bus1);
pci_fixup_irqs(pci_common_swizzle, visws_map_irq);
pcibios_resource_survey();
/* Request bus scan */

View File

@ -60,7 +60,7 @@ int node_to_pxm(int node)
return node_to_pxm_map[node];
}
void __acpi_map_pxm_to_node(int pxm, int node)
static void __acpi_map_pxm_to_node(int pxm, int node)
{
if (pxm_to_node_map[pxm] == NUMA_NO_NODE || node < pxm_to_node_map[pxm])
pxm_to_node_map[pxm] = node;
@ -193,7 +193,7 @@ static int __init acpi_parse_slit(struct acpi_table_header *table)
return 0;
}
void __init __attribute__ ((weak))
void __init __weak
acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
{
printk(KERN_WARNING PREFIX
@ -314,7 +314,7 @@ int __init acpi_numa_init(void)
return 0;
}
int acpi_get_pxm(acpi_handle h)
static int acpi_get_pxm(acpi_handle h)
{
unsigned long long pxm;
acpi_status status;
@ -331,14 +331,14 @@ int acpi_get_pxm(acpi_handle h)
return -1;
}
int acpi_get_node(acpi_handle *handle)
int acpi_get_node(acpi_handle handle)
{
int pxm, node = NUMA_NO_NODE;
int pxm;
pxm = acpi_get_pxm(handle);
if (pxm >= 0 && pxm < MAX_PXM_DOMAINS)
node = acpi_map_pxm_to_node(pxm);
if (pxm < 0 || pxm >= MAX_PXM_DOMAINS)
return NUMA_NO_NODE;
return node;
return acpi_map_pxm_to_node(pxm);
}
EXPORT_SYMBOL(acpi_get_node);

View File

@ -1166,13 +1166,13 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
struct ahci_host_priv *hpriv)
{
int rc, nvec;
int nvec;
if (hpriv->flags & AHCI_HFLAG_NO_MSI)
goto intx;
rc = pci_msi_vec_count(pdev);
if (rc < 0)
nvec = pci_msi_vec_count(pdev);
if (nvec < 0)
goto intx;
/*
@ -1180,21 +1180,19 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
* Message mode could be enforced. In this case assume that advantage
* of multipe MSIs is negated and use single MSI mode instead.
*/
if (rc < n_ports)
if (nvec < n_ports)
goto single_msi;
nvec = rc;
rc = pci_enable_msi_block(pdev, nvec);
if (rc < 0)
goto intx;
else if (rc > 0)
nvec = pci_enable_msi_range(pdev, nvec, nvec);
if (nvec == -ENOSPC)
goto single_msi;
else if (nvec < 0)
goto intx;
return nvec;
single_msi:
rc = pci_enable_msi(pdev);
if (rc)
if (pci_enable_msi(pdev))
goto intx;
return 1;

View File

@ -870,14 +870,14 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg));
if (!ret) {
mem->start = reg[0];
mem->end = mem->start + reg[1];
mem->end = mem->start + reg[1] - 1;
mem->flags = IORESOURCE_MEM;
}
ret = of_property_read_u32_array(np, "pcie-io-aperture", reg, ARRAY_SIZE(reg));
if (!ret) {
io->start = reg[0];
io->end = io->start + reg[1];
io->end = io->start + reg[1] - 1;
io->flags = IORESOURCE_IO;
}
}

View File

@ -319,7 +319,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
pci_dev_put(pci_dev);
}
if (!dev->hose) {
struct pci_bus *b = pci_bus_b(pci_root_buses.next);
struct pci_bus *b = list_entry(pci_root_buses.next,
struct pci_bus, node);
if (b)
dev->hose = b->sysdata;
}

View File

@ -25,6 +25,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/irqreturn.h>
/*
* Maximum number of IOMMUs supported

View File

@ -652,6 +652,44 @@ static int i2o_iop_activate(struct i2o_controller *c)
return i2o_hrt_get(c);
};
static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags)
{
i2o_status_block *sb = c->status_block.virt;
struct resource *res = &c->mem_resource;
resource_size_t size, align;
int err;
res->name = c->pdev->bus->name;
res->flags = flags;
res->start = 0;
res->end = 0;
osm_info("%s: requires private memory resources.\n", c->name);
if (flags & IORESOURCE_MEM) {
size = sb->desired_mem_size;
align = 1 << 20; /* unspecified, use 1Mb and play safe */
} else {
size = sb->desired_io_size;
align = 1 << 12; /* unspecified, use 4Kb and play safe */
}
err = pci_bus_alloc_resource(c->pdev->bus, res, size, align, 0, 0,
NULL, NULL);
if (err < 0)
return;
if (flags & IORESOURCE_MEM) {
c->mem_alloc = 1;
sb->current_mem_size = resource_size(res);
sb->current_mem_base = res->start;
} else if (flags & IORESOURCE_IO) {
c->io_alloc = 1;
sb->current_io_size = resource_size(res);
sb->current_io_base = res->start;
}
osm_info("%s: allocated PCI space %pR\n", c->name, res);
}
/**
* i2o_iop_systab_set - Set the I2O System Table of the specified IOP
* @c: I2O controller to which the system table should be send
@ -665,52 +703,13 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
struct i2o_message *msg;
i2o_status_block *sb = c->status_block.virt;
struct device *dev = &c->pdev->dev;
struct resource *root;
int rc;
if (sb->current_mem_size < sb->desired_mem_size) {
struct resource *res = &c->mem_resource;
res->name = c->pdev->bus->name;
res->flags = IORESOURCE_MEM;
res->start = 0;
res->end = 0;
osm_info("%s: requires private memory resources.\n", c->name);
root = pci_find_parent_resource(c->pdev, res);
if (root == NULL)
osm_warn("%s: Can't find parent resource!\n", c->name);
if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->mem_alloc = 1;
sb->current_mem_size = resource_size(res);
sb->current_mem_base = res->start;
osm_info("%s: allocated %llu bytes of PCI memory at "
"0x%016llX.\n", c->name,
(unsigned long long)resource_size(res),
(unsigned long long)res->start);
}
}
if (sb->current_mem_size < sb->desired_mem_size)
i2o_res_alloc(c, IORESOURCE_MEM);
if (sb->current_io_size < sb->desired_io_size) {
struct resource *res = &c->io_resource;
res->name = c->pdev->bus->name;
res->flags = IORESOURCE_IO;
res->start = 0;
res->end = 0;
osm_info("%s: requires private memory resources.\n", c->name);
root = pci_find_parent_resource(c->pdev, res);
if (root == NULL)
osm_warn("%s: Can't find parent resource!\n", c->name);
if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->io_alloc = 1;
sb->current_io_size = resource_size(res);
sb->current_mem_base = res->start;
osm_info("%s: allocated %llu bytes of PCI I/O at "
"0x%016llX.\n", c->name,
(unsigned long long)resource_size(res),
(unsigned long long)res->start);
}
}
if (sb->current_io_size < sb->desired_io_size)
i2o_res_alloc(c, IORESOURCE_IO);
msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
if (IS_ERR(msg))

View File

@ -20,6 +20,7 @@
#define _MEI_INTERFACE_H_
#include <linux/mei.h>
#include <linux/irqreturn.h>
#include "mei_dev.h"
#include "client.h"

View File

@ -29,6 +29,7 @@
#include <linux/workqueue.h>
#include <linux/io.h>
#include <linux/irqreturn.h>
/**
* struct mic_intr_info - Contains h/w specific interrupt sources info

View File

@ -24,6 +24,7 @@
#include <linux/cdev.h>
#include <linux/idr.h>
#include <linux/notifier.h>
#include <linux/irqreturn.h>
#include "mic_intr.h"

View File

@ -33,21 +33,15 @@ obj-$(CONFIG_PCI_IOV) += iov.o
#
# Some architectures use the generic PCI setup functions
#
obj-$(CONFIG_X86) += setup-bus.o
obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o
obj-$(CONFIG_PARISC) += setup-bus.o
obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
obj-$(CONFIG_PPC) += setup-bus.o
obj-$(CONFIG_FRV) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_ALPHA) += setup-irq.o
obj-$(CONFIG_ARM) += setup-irq.o
obj-$(CONFIG_UNICORE32) += setup-irq.o
obj-$(CONFIG_SUPERH) += setup-irq.o
obj-$(CONFIG_MIPS) += setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
obj-$(CONFIG_MN10300) += setup-bus.o
obj-$(CONFIG_MICROBLAZE) += setup-bus.o
obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o
obj-$(CONFIG_M68K) += setup-bus.o setup-irq.o
obj-$(CONFIG_TILE) += setup-irq.o
obj-$(CONFIG_SPARC_LEON) += setup-irq.o
obj-$(CONFIG_M68K) += setup-irq.o
#
# ACPI Related PCI FW Functions

View File

@ -132,7 +132,7 @@ static void pci_clip_resource_to_region(struct pci_bus *bus,
static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
resource_size_t size, resource_size_t align,
resource_size_t min, unsigned int type_mask,
resource_size_t min, unsigned long type_mask,
resource_size_t (*alignf)(void *,
const struct resource *,
resource_size_t,
@ -144,7 +144,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
struct resource *r, avail;
resource_size_t max;
type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
type_mask |= IORESOURCE_TYPE_BITS;
pci_bus_for_each_resource(bus, r, i) {
if (!r)
@ -200,7 +200,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
*/
int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
resource_size_t size, resource_size_t align,
resource_size_t min, unsigned int type_mask,
resource_size_t min, unsigned long type_mask,
resource_size_t (*alignf)(void *,
const struct resource *,
resource_size_t,

View File

@ -32,11 +32,6 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
bridge->release_data = release_data;
}
static bool resource_contains(struct resource *res1, struct resource *res2)
{
return res1->start <= res2->start && res1->end >= res2->end;
}
void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
struct resource *res)
{
@ -45,9 +40,6 @@ void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
resource_size_t offset = 0;
list_for_each_entry(window, &bridge->windows, list) {
if (resource_type(res) != resource_type(window->res))
continue;
if (resource_contains(window->res, res)) {
offset = window->offset;
break;

View File

@ -27,7 +27,7 @@ config PCI_TEGRA
config PCI_RCAR_GEN2
bool "Renesas R-Car Gen2 Internal PCI controller"
depends on ARM && (ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST)
depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
help
Say Y here if you want internal PCI support on R-Car Gen2 SoC.
There are 3 internal PCI controllers available with a single

View File

@ -424,20 +424,40 @@ static void imx6_pcie_reset_phy(struct pcie_port *pp)
static int imx6_pcie_link_up(struct pcie_port *pp)
{
u32 rc, ltssm, rx_valid;
u32 rc, debug_r0, rx_valid;
int count = 5;
/*
* Test if the PHY reports that the link is up and also that
* the link training finished. It might happen that the PHY
* reports the link is already up, but the link training bit
* is still set, so make sure to check the training is done
* as well here.
* Test if the PHY reports that the link is up and also that the LTSSM
* training finished. There are three possible states of the link when
* this code is called:
* 1) The link is DOWN (unlikely)
* The link didn't come up yet for some reason. This usually means
* we have a real problem somewhere. Reset the PHY and exit. This
* state calls for inspection of the DEBUG registers.
* 2) The link is UP, but still in LTSSM training
* Wait for the training to finish, which should take a very short
* time. If the training does not finish, we have a problem and we
* need to inspect the DEBUG registers. If the training does finish,
* the link is up and operating correctly.
* 3) The link is UP and no longer in LTSSM training
* The link is up and operating correctly.
*/
rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
if ((rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) &&
!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
return 1;
while (1) {
rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP))
break;
if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
return 1;
if (!count--)
break;
dev_dbg(pp->dev, "Link is up, but still in training\n");
/*
* Wait a little bit, then re-check if the link finished
* the training.
*/
usleep_range(1000, 2000);
}
/*
* From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
* Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
@ -446,15 +466,16 @@ static int imx6_pcie_link_up(struct pcie_port *pp)
* to gen2 is stuck
*/
pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
ltssm = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0) & 0x3F;
debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
if (rx_valid & 0x01)
return 0;
if (ltssm != 0x0d)
if ((debug_r0 & 0x3f) != 0x0d)
return 0;
dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc);
imx6_pcie_reset_phy(pp);

View File

@ -101,7 +101,9 @@ struct mvebu_pcie {
struct mvebu_pcie_port *ports;
struct msi_chip *msi;
struct resource io;
char io_name[30];
struct resource realio;
char mem_name[30];
struct resource mem;
struct resource busn;
int nports;
@ -672,10 +674,30 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
{
struct mvebu_pcie *pcie = sys_to_pcie(sys);
int i;
int domain = 0;
if (resource_size(&pcie->realio) != 0)
#ifdef CONFIG_PCI_DOMAINS
domain = sys->domain;
#endif
snprintf(pcie->mem_name, sizeof(pcie->mem_name), "PCI MEM %04x",
domain);
pcie->mem.name = pcie->mem_name;
snprintf(pcie->io_name, sizeof(pcie->io_name), "PCI I/O %04x", domain);
pcie->realio.name = pcie->io_name;
if (request_resource(&iomem_resource, &pcie->mem))
return 0;
if (resource_size(&pcie->realio) != 0) {
if (request_resource(&ioport_resource, &pcie->realio)) {
release_resource(&pcie->mem);
return 0;
}
pci_add_resource_offset(&sys->resources, &pcie->realio,
sys->io_offset);
}
pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
pci_add_resource(&sys->resources, &pcie->busn);
@ -797,7 +819,7 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
for (i = 0; i < nranges; i++) {
u32 flags = of_read_number(range, 1);
u32 slot = of_read_number(range, 2);
u32 slot = of_read_number(range + 1, 1);
u64 cpuaddr = of_read_number(range + na, pna);
unsigned long rtype;

View File

@ -18,6 +18,7 @@
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/sizes.h>
#include <linux/slab.h>
/* AHB-PCI Bridge PCI communication registers */
@ -39,9 +40,26 @@
#define RCAR_PCI_INT_ENABLE_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x20)
#define RCAR_PCI_INT_STATUS_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x24)
#define RCAR_PCI_INT_SIGTABORT (1 << 0)
#define RCAR_PCI_INT_SIGRETABORT (1 << 1)
#define RCAR_PCI_INT_REMABORT (1 << 2)
#define RCAR_PCI_INT_PERR (1 << 3)
#define RCAR_PCI_INT_SIGSERR (1 << 4)
#define RCAR_PCI_INT_RESERR (1 << 5)
#define RCAR_PCI_INT_WIN1ERR (1 << 12)
#define RCAR_PCI_INT_WIN2ERR (1 << 13)
#define RCAR_PCI_INT_A (1 << 16)
#define RCAR_PCI_INT_B (1 << 17)
#define RCAR_PCI_INT_PME (1 << 19)
#define RCAR_PCI_INT_ALLERRORS (RCAR_PCI_INT_SIGTABORT | \
RCAR_PCI_INT_SIGRETABORT | \
RCAR_PCI_INT_SIGRETABORT | \
RCAR_PCI_INT_REMABORT | \
RCAR_PCI_INT_PERR | \
RCAR_PCI_INT_SIGSERR | \
RCAR_PCI_INT_RESERR | \
RCAR_PCI_INT_WIN1ERR | \
RCAR_PCI_INT_WIN2ERR)
#define RCAR_AHB_BUS_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x30)
#define RCAR_AHB_BUS_MMODE_HTRANS (1 << 0)
@ -74,9 +92,6 @@
#define RCAR_PCI_UNIT_REV_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x48)
/* Number of internal PCI controllers */
#define RCAR_PCI_NR_CONTROLLERS 3
struct rcar_pci_priv {
struct device *dev;
void __iomem *reg;
@ -84,6 +99,7 @@ struct rcar_pci_priv {
struct resource mem_res;
struct resource *cfg_res;
int irq;
unsigned long window_size;
};
/* PCI configuration space operations */
@ -102,6 +118,10 @@ static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn,
if (slot > 2)
return NULL;
/* bridge logic only has registers to 0x40 */
if (slot == 0x0 && where >= 0x40)
return NULL;
val = slot ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG :
RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG;
@ -156,7 +176,7 @@ static int rcar_pci_write_config(struct pci_bus *bus, unsigned int devfn,
}
/* PCI interrupt mapping */
static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct pci_sys_data *sys = dev->bus->sysdata;
struct rcar_pci_priv *priv = sys->private_data;
@ -164,8 +184,48 @@ static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return priv->irq;
}
#ifdef CONFIG_PCI_DEBUG
/* if debug enabled, then attach an error handler irq to the bridge */
static irqreturn_t rcar_pci_err_irq(int irq, void *pw)
{
struct rcar_pci_priv *priv = pw;
u32 status = ioread32(priv->reg + RCAR_PCI_INT_STATUS_REG);
if (status & RCAR_PCI_INT_ALLERRORS) {
dev_err(priv->dev, "error irq: status %08x\n", status);
/* clear the error(s) */
iowrite32(status & RCAR_PCI_INT_ALLERRORS,
priv->reg + RCAR_PCI_INT_STATUS_REG);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
static void rcar_pci_setup_errirq(struct rcar_pci_priv *priv)
{
int ret;
u32 val;
ret = devm_request_irq(priv->dev, priv->irq, rcar_pci_err_irq,
IRQF_SHARED, "error irq", priv);
if (ret) {
dev_err(priv->dev, "cannot claim IRQ for error handling\n");
return;
}
val = ioread32(priv->reg + RCAR_PCI_INT_ENABLE_REG);
val |= RCAR_PCI_INT_ALLERRORS;
iowrite32(val, priv->reg + RCAR_PCI_INT_ENABLE_REG);
}
#else
static inline void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) { }
#endif
/* PCI host controller setup */
static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
{
struct rcar_pci_priv *priv = sys->private_data;
void __iomem *reg = priv->reg;
@ -183,10 +243,31 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
iowrite32(val, reg + RCAR_USBCTR_REG);
udelay(4);
/* De-assert reset and set PCIAHB window1 size to 1GB */
/* De-assert reset and reset PCIAHB window1 size */
val &= ~(RCAR_USBCTR_PCIAHB_WIN1_MASK | RCAR_USBCTR_PCICLK_MASK |
RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST);
iowrite32(val | RCAR_USBCTR_PCIAHB_WIN1_1G, reg + RCAR_USBCTR_REG);
/* Setup PCIAHB window1 size */
switch (priv->window_size) {
case SZ_2G:
val |= RCAR_USBCTR_PCIAHB_WIN1_2G;
break;
case SZ_1G:
val |= RCAR_USBCTR_PCIAHB_WIN1_1G;
break;
case SZ_512M:
val |= RCAR_USBCTR_PCIAHB_WIN1_512M;
break;
default:
pr_warn("unknown window size %ld - defaulting to 256M\n",
priv->window_size);
priv->window_size = SZ_256M;
/* fall-through */
case SZ_256M:
val |= RCAR_USBCTR_PCIAHB_WIN1_256M;
break;
}
iowrite32(val, reg + RCAR_USBCTR_REG);
/* Configure AHB master and slave modes */
iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG);
@ -197,7 +278,7 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
RCAR_PCI_ARBITER_PCIBP_MODE;
iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG);
/* PCI-AHB mapping: 0x40000000-0x80000000 */
/* PCI-AHB mapping: 0x40000000 base */
iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16,
reg + RCAR_PCIAHB_WIN1_CTR_REG);
@ -224,10 +305,15 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME,
reg + RCAR_PCI_INT_ENABLE_REG);
if (priv->irq > 0)
rcar_pci_setup_errirq(priv);
/* Add PCI resources */
pci_add_resource(&sys->resources, &priv->io_res);
pci_add_resource(&sys->resources, &priv->mem_res);
/* Setup bus number based on platform device id */
sys->busnr = to_platform_device(priv->dev)->id;
return 1;
}
@ -236,48 +322,13 @@ static struct pci_ops rcar_pci_ops = {
.write = rcar_pci_write_config,
};
static struct hw_pci rcar_hw_pci __initdata = {
.map_irq = rcar_pci_map_irq,
.ops = &rcar_pci_ops,
.setup = rcar_pci_setup,
};
static int rcar_pci_count __initdata;
static int __init rcar_pci_add_controller(struct rcar_pci_priv *priv)
{
void **private_data;
int count;
if (rcar_hw_pci.nr_controllers < rcar_pci_count)
goto add_priv;
/* (Re)allocate private data pointer array if needed */
count = rcar_pci_count + RCAR_PCI_NR_CONTROLLERS;
private_data = kzalloc(count * sizeof(void *), GFP_KERNEL);
if (!private_data)
return -ENOMEM;
rcar_pci_count = count;
if (rcar_hw_pci.private_data) {
memcpy(private_data, rcar_hw_pci.private_data,
rcar_hw_pci.nr_controllers * sizeof(void *));
kfree(rcar_hw_pci.private_data);
}
rcar_hw_pci.private_data = private_data;
add_priv:
/* Add private data pointer to the array */
rcar_hw_pci.private_data[rcar_hw_pci.nr_controllers++] = priv;
return 0;
}
static int __init rcar_pci_probe(struct platform_device *pdev)
static int rcar_pci_probe(struct platform_device *pdev)
{
struct resource *cfg_res, *mem_res;
struct rcar_pci_priv *priv;
void __iomem *reg;
struct hw_pci hw;
void *hw_private[1];
cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg = devm_ioremap_resource(&pdev->dev, cfg_res);
@ -308,31 +359,34 @@ static int __init rcar_pci_probe(struct platform_device *pdev)
priv->reg = reg;
priv->dev = &pdev->dev;
return rcar_pci_add_controller(priv);
if (priv->irq < 0) {
dev_err(&pdev->dev, "no valid irq found\n");
return priv->irq;
}
priv->window_size = SZ_1G;
hw_private[0] = priv;
memset(&hw, 0, sizeof(hw));
hw.nr_controllers = ARRAY_SIZE(hw_private);
hw.private_data = hw_private;
hw.map_irq = rcar_pci_map_irq;
hw.ops = &rcar_pci_ops;
hw.setup = rcar_pci_setup;
pci_common_init_dev(&pdev->dev, &hw);
return 0;
}
static struct platform_driver rcar_pci_driver = {
.driver = {
.name = "pci-rcar-gen2",
.owner = THIS_MODULE,
.suppress_bind_attrs = true,
},
.probe = rcar_pci_probe,
};
static int __init rcar_pci_init(void)
{
int retval;
retval = platform_driver_probe(&rcar_pci_driver, rcar_pci_probe);
if (!retval)
pci_common_init(&rcar_hw_pci);
/* Private data pointer array is not needed any more */
kfree(rcar_hw_pci.private_data);
rcar_hw_pci.private_data = NULL;
return retval;
}
subsys_initcall(rcar_pci_init);
module_platform_driver(rcar_pci_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI");

View File

@ -798,7 +798,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
/* setup RC BARs */
dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_0);
dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_1);
dw_pcie_writel_rc(pp, 0x00000000, PCI_BASE_ADDRESS_1);
/* setup interrupt pins */
dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE, &val);

View File

@ -424,7 +424,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
*/
static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
{
struct list_head *tmp;
struct pci_bus *tmp;
unsigned char max, n;
/*
@ -437,8 +437,8 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
*/
max = bus->busn_res.start;
list_for_each(tmp, &bus->children) {
n = pci_bus_max_busnr(pci_bus_b(tmp));
list_for_each_entry(tmp, &bus->children, node) {
n = pci_bus_max_busnr(tmp);
if (n > max)
max = n;
}

View File

@ -920,12 +920,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
bus->max_bus_speed = PCI_SPEED_100MHz_PCIX;
break;
}
if (bus_cap & 20) {
if (bus_cap & 0x20) {
dbg("bus max supports 66MHz PCI-X\n");
bus->max_bus_speed = PCI_SPEED_66MHz_PCIX;
break;
}
if (bus_cap & 10) {
if (bus_cap & 0x10) {
dbg("bus max supports 66MHz PCI\n");
bus->max_bus_speed = PCI_SPEED_66MHz;
break;

View File

@ -76,6 +76,7 @@ struct slot {
struct hotplug_slot *hotplug_slot;
struct delayed_work work; /* work for button event */
struct mutex lock;
struct mutex hotplug_lock;
struct workqueue_struct *wq;
};
@ -109,6 +110,8 @@ struct controller {
#define INT_BUTTON_PRESS 7
#define INT_BUTTON_RELEASE 8
#define INT_BUTTON_CANCEL 9
#define INT_LINK_UP 10
#define INT_LINK_DOWN 11
#define STATIC_STATE 0
#define BLINKINGON_STATE 1
@ -132,6 +135,7 @@ u8 pciehp_handle_attention_button(struct slot *p_slot);
u8 pciehp_handle_switch_change(struct slot *p_slot);
u8 pciehp_handle_presence_change(struct slot *p_slot);
u8 pciehp_handle_power_fault(struct slot *p_slot);
void pciehp_handle_linkstate_change(struct slot *p_slot);
int pciehp_configure_device(struct slot *p_slot);
int pciehp_unconfigure_device(struct slot *p_slot);
void pciehp_queue_pushbutton_work(struct work_struct *work);
@ -153,6 +157,7 @@ void pciehp_green_led_on(struct slot *slot);
void pciehp_green_led_off(struct slot *slot);
void pciehp_green_led_blink(struct slot *slot);
int pciehp_check_link_status(struct controller *ctrl);
bool pciehp_check_link_active(struct controller *ctrl);
void pciehp_release_ctrl(struct controller *ctrl);
int pciehp_reset_slot(struct slot *slot, int probe);

View File

@ -112,6 +112,7 @@ static struct pcie_port_service_driver __initdata dummy_driver = {
static int __init select_detection_mode(void)
{
struct dummy_slot *slot, *tmp;
if (pcie_port_service_register(&dummy_driver))
return PCIEHP_DETECT_ACPI;
pcie_port_service_unregister(&dummy_driver);

View File

@ -108,6 +108,7 @@ static int init_slot(struct controller *ctrl)
ops = kzalloc(sizeof(*ops), GFP_KERNEL);
if (!ops)
goto out;
ops->enable_slot = enable_slot;
ops->disable_slot = disable_slot;
ops->get_power_status = get_power_status;
@ -283,8 +284,11 @@ static int pciehp_probe(struct pcie_device *dev)
slot = ctrl->slot;
pciehp_get_adapter_status(slot, &occupied);
pciehp_get_power_status(slot, &poweron);
if (occupied && pciehp_force)
if (occupied && pciehp_force) {
mutex_lock(&slot->hotplug_lock);
pciehp_enable_slot(slot);
mutex_unlock(&slot->hotplug_lock);
}
/* If empty slot's power status is on, turn power off */
if (!occupied && poweron && POWER_CTRL(ctrl))
pciehp_power_off_slot(slot);
@ -328,10 +332,12 @@ static int pciehp_resume (struct pcie_device *dev)
/* Check if slot is occupied */
pciehp_get_adapter_status(slot, &status);
mutex_lock(&slot->hotplug_lock);
if (status)
pciehp_enable_slot(slot);
else
pciehp_disable_slot(slot);
mutex_unlock(&slot->hotplug_lock);
return 0;
}
#endif /* PM */

View File

@ -150,6 +150,27 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)
return 1;
}
void pciehp_handle_linkstate_change(struct slot *p_slot)
{
u32 event_type;
struct controller *ctrl = p_slot->ctrl;
/* Link Status Change */
ctrl_dbg(ctrl, "Data Link Layer State change\n");
if (pciehp_check_link_active(ctrl)) {
ctrl_info(ctrl, "slot(%s): Link Up event\n",
slot_name(p_slot));
event_type = INT_LINK_UP;
} else {
ctrl_info(ctrl, "slot(%s): Link Down event\n",
slot_name(p_slot));
event_type = INT_LINK_DOWN;
}
queue_interrupt_event(p_slot, event_type);
}
/* The following routines constitute the bulk of the
hotplug controller logic
*/
@ -212,7 +233,8 @@ static int board_added(struct slot *p_slot)
if (retval) {
ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
pci_domain_nr(parent), parent->number);
goto err_exit;
if (retval != -EEXIST)
goto err_exit;
}
pciehp_green_led_on(p_slot);
@ -255,6 +277,9 @@ static int remove_board(struct slot *p_slot)
struct power_work_info {
struct slot *p_slot;
struct work_struct work;
unsigned int req;
#define DISABLE_REQ 0
#define ENABLE_REQ 1
};
/**
@ -269,30 +294,38 @@ static void pciehp_power_thread(struct work_struct *work)
struct power_work_info *info =
container_of(work, struct power_work_info, work);
struct slot *p_slot = info->p_slot;
int ret;
mutex_lock(&p_slot->lock);
switch (p_slot->state) {
case POWEROFF_STATE:
mutex_unlock(&p_slot->lock);
switch (info->req) {
case DISABLE_REQ:
ctrl_dbg(p_slot->ctrl,
"Disabling domain:bus:device=%04x:%02x:00\n",
pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
p_slot->ctrl->pcie->port->subordinate->number);
mutex_lock(&p_slot->hotplug_lock);
pciehp_disable_slot(p_slot);
mutex_unlock(&p_slot->hotplug_lock);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
break;
case POWERON_STATE:
mutex_unlock(&p_slot->lock);
if (pciehp_enable_slot(p_slot))
break;
case ENABLE_REQ:
ctrl_dbg(p_slot->ctrl,
"Enabling domain:bus:device=%04x:%02x:00\n",
pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
p_slot->ctrl->pcie->port->subordinate->number);
mutex_lock(&p_slot->hotplug_lock);
ret = pciehp_enable_slot(p_slot);
mutex_unlock(&p_slot->hotplug_lock);
if (ret)
pciehp_green_led_off(p_slot);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
mutex_unlock(&p_slot->lock);
break;
default:
break;
}
mutex_unlock(&p_slot->lock);
kfree(info);
}
@ -315,9 +348,11 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
switch (p_slot->state) {
case BLINKINGOFF_STATE:
p_slot->state = POWEROFF_STATE;
info->req = DISABLE_REQ;
break;
case BLINKINGON_STATE:
p_slot->state = POWERON_STATE;
info->req = ENABLE_REQ;
break;
default:
kfree(info);
@ -364,11 +399,10 @@ static void handle_button_press_event(struct slot *p_slot)
*/
ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
cancel_delayed_work(&p_slot->work);
if (p_slot->state == BLINKINGOFF_STATE) {
if (p_slot->state == BLINKINGOFF_STATE)
pciehp_green_led_on(p_slot);
} else {
else
pciehp_green_led_off(p_slot);
}
pciehp_set_attention_status(p_slot, 0);
ctrl_info(ctrl, "PCI slot #%s - action canceled "
"due to button press\n", slot_name(p_slot));
@ -407,14 +441,81 @@ static void handle_surprise_event(struct slot *p_slot)
INIT_WORK(&info->work, pciehp_power_thread);
pciehp_get_adapter_status(p_slot, &getstatus);
if (!getstatus)
if (!getstatus) {
p_slot->state = POWEROFF_STATE;
else
info->req = DISABLE_REQ;
} else {
p_slot->state = POWERON_STATE;
info->req = ENABLE_REQ;
}
queue_work(p_slot->wq, &info->work);
}
/*
* Note: This function must be called with slot->lock held
*/
static void handle_link_event(struct slot *p_slot, u32 event)
{
struct controller *ctrl = p_slot->ctrl;
struct power_work_info *info;
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
__func__);
return;
}
info->p_slot = p_slot;
info->req = event == INT_LINK_UP ? ENABLE_REQ : DISABLE_REQ;
INIT_WORK(&info->work, pciehp_power_thread);
switch (p_slot->state) {
case BLINKINGON_STATE:
case BLINKINGOFF_STATE:
cancel_delayed_work(&p_slot->work);
/* Fall through */
case STATIC_STATE:
p_slot->state = event == INT_LINK_UP ?
POWERON_STATE : POWEROFF_STATE;
queue_work(p_slot->wq, &info->work);
break;
case POWERON_STATE:
if (event == INT_LINK_UP) {
ctrl_info(ctrl,
"Link Up event ignored on slot(%s): already powering on\n",
slot_name(p_slot));
kfree(info);
} else {
ctrl_info(ctrl,
"Link Down event queued on slot(%s): currently getting powered on\n",
slot_name(p_slot));
p_slot->state = POWEROFF_STATE;
queue_work(p_slot->wq, &info->work);
}
break;
case POWEROFF_STATE:
if (event == INT_LINK_UP) {
ctrl_info(ctrl,
"Link Up event queued on slot(%s): currently getting powered off\n",
slot_name(p_slot));
p_slot->state = POWERON_STATE;
queue_work(p_slot->wq, &info->work);
} else {
ctrl_info(ctrl,
"Link Down event ignored on slot(%s): already powering off\n",
slot_name(p_slot));
kfree(info);
}
break;
default:
ctrl_err(ctrl, "Not a valid state on slot(%s)\n",
slot_name(p_slot));
kfree(info);
break;
}
}
static void interrupt_event_handler(struct work_struct *work)
{
struct event_info *info = container_of(work, struct event_info, work);
@ -433,12 +534,23 @@ static void interrupt_event_handler(struct work_struct *work)
pciehp_green_led_off(p_slot);
break;
case INT_PRESENCE_ON:
case INT_PRESENCE_OFF:
if (!HP_SUPR_RM(ctrl))
break;
ctrl_dbg(ctrl, "Surprise Insertion\n");
handle_surprise_event(p_slot);
break;
case INT_PRESENCE_OFF:
/*
* Regardless of surprise capability, we need to
* definitely remove a card that has been pulled out!
*/
ctrl_dbg(ctrl, "Surprise Removal\n");
handle_surprise_event(p_slot);
break;
case INT_LINK_UP:
case INT_LINK_DOWN:
handle_link_event(p_slot, info->event_type);
break;
default:
break;
}
@ -447,6 +559,9 @@ static void interrupt_event_handler(struct work_struct *work)
kfree(info);
}
/*
* Note: This function must be called with slot->hotplug_lock held
*/
int pciehp_enable_slot(struct slot *p_slot)
{
u8 getstatus = 0;
@ -479,13 +594,15 @@ int pciehp_enable_slot(struct slot *p_slot)
pciehp_get_latch_status(p_slot, &getstatus);
rc = board_added(p_slot);
if (rc) {
if (rc)
pciehp_get_latch_status(p_slot, &getstatus);
}
return rc;
}
/*
* Note: This function must be called with slot->hotplug_lock held
*/
int pciehp_disable_slot(struct slot *p_slot)
{
u8 getstatus = 0;
@ -494,24 +611,6 @@ int pciehp_disable_slot(struct slot *p_slot)
if (!p_slot->ctrl)
return 1;
if (!HP_SUPR_RM(p_slot->ctrl)) {
pciehp_get_adapter_status(p_slot, &getstatus);
if (!getstatus) {
ctrl_info(ctrl, "No adapter on slot(%s)\n",
slot_name(p_slot));
return -ENODEV;
}
}
if (MRL_SENS(p_slot->ctrl)) {
pciehp_get_latch_status(p_slot, &getstatus);
if (getstatus) {
ctrl_info(ctrl, "Latch open on slot(%s)\n",
slot_name(p_slot));
return -ENODEV;
}
}
if (POWER_CTRL(p_slot->ctrl)) {
pciehp_get_power_status(p_slot, &getstatus);
if (!getstatus) {
@ -536,7 +635,9 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
case STATIC_STATE:
p_slot->state = POWERON_STATE;
mutex_unlock(&p_slot->lock);
mutex_lock(&p_slot->hotplug_lock);
retval = pciehp_enable_slot(p_slot);
mutex_unlock(&p_slot->hotplug_lock);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
break;

View File

@ -206,7 +206,7 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
mutex_unlock(&ctrl->ctrl_lock);
}
static bool check_link_active(struct controller *ctrl)
bool pciehp_check_link_active(struct controller *ctrl)
{
struct pci_dev *pdev = ctrl_dev(ctrl);
u16 lnk_status;
@ -225,12 +225,12 @@ static void __pcie_wait_link_active(struct controller *ctrl, bool active)
{
int timeout = 1000;
if (check_link_active(ctrl) == active)
if (pciehp_check_link_active(ctrl) == active)
return;
while (timeout > 0) {
msleep(10);
timeout -= 10;
if (check_link_active(ctrl) == active)
if (pciehp_check_link_active(ctrl) == active)
return;
}
ctrl_dbg(ctrl, "Data Link Layer Link Active not %s in 1000 msec\n",
@ -242,11 +242,6 @@ static void pcie_wait_link_active(struct controller *ctrl)
__pcie_wait_link_active(ctrl, true);
}
static void pcie_wait_link_not_active(struct controller *ctrl)
{
__pcie_wait_link_active(ctrl, false);
}
static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
{
u32 l;
@ -332,11 +327,6 @@ static int pciehp_link_enable(struct controller *ctrl)
return __pciehp_link_set(ctrl, true);
}
static int pciehp_link_disable(struct controller *ctrl)
{
return __pciehp_link_set(ctrl, false);
}
void pciehp_get_attention_status(struct slot *slot, u8 *status)
{
struct controller *ctrl = slot->ctrl;
@ -508,14 +498,6 @@ void pciehp_power_off_slot(struct slot * slot)
{
struct controller *ctrl = slot->ctrl;
/* Disable the link at first */
pciehp_link_disable(ctrl);
/* wait the link is down */
if (ctrl->link_active_reporting)
pcie_wait_link_not_active(ctrl);
else
msleep(1000);
pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC);
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
@ -540,7 +522,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
PCI_EXP_SLTSTA_CC);
PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
detected &= ~intr_loc;
intr_loc |= detected;
if (!intr_loc)
@ -579,6 +561,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
ctrl->power_fault_detected = 1;
pciehp_handle_power_fault(slot);
}
if (intr_loc & PCI_EXP_SLTSTA_DLLSC)
pciehp_handle_linkstate_change(slot);
return IRQ_HANDLED;
}
@ -596,9 +582,17 @@ void pcie_enable_notification(struct controller *ctrl)
* when it is cleared in the interrupt service routine, and
* next power fault detected interrupt was notified again.
*/
cmd = PCI_EXP_SLTCTL_PDCE;
/*
* Always enable link events: thus link-up and link-down shall
* always be treated as hotplug and unplug respectively. Enable
* presence detect only if Attention Button is not present.
*/
cmd = PCI_EXP_SLTCTL_DLLSCE;
if (ATTN_BUTTN(ctrl))
cmd |= PCI_EXP_SLTCTL_ABPE;
else
cmd |= PCI_EXP_SLTCTL_PDCE;
if (MRL_SENS(ctrl))
cmd |= PCI_EXP_SLTCTL_MRLSCE;
if (!pciehp_poll_mode)
@ -606,7 +600,8 @@ void pcie_enable_notification(struct controller *ctrl)
mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE);
PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
PCI_EXP_SLTCTL_DLLSCE);
pcie_write_cmd(ctrl, cmd, mask);
}
@ -624,33 +619,38 @@ static void pcie_disable_notification(struct controller *ctrl)
/*
* pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary
* bus reset of the bridge, but if the slot supports surprise removal we need
* to disable presence detection around the bus reset and clear any spurious
* bus reset of the bridge, but at the same time we want to ensure that it is
* not seen as a hot-unplug, followed by the hot-plug of the device. Thus,
* disable link state notification and presence detection change notification
* momentarily, if we see that they could interfere. Also, clear any spurious
* events after.
*/
int pciehp_reset_slot(struct slot *slot, int probe)
{
struct controller *ctrl = slot->ctrl;
struct pci_dev *pdev = ctrl_dev(ctrl);
u16 stat_mask = 0, ctrl_mask = 0;
if (probe)
return 0;
if (HP_SUPR_RM(ctrl)) {
pcie_write_cmd(ctrl, 0, PCI_EXP_SLTCTL_PDCE);
if (pciehp_poll_mode)
del_timer_sync(&ctrl->poll_timer);
if (!ATTN_BUTTN(ctrl)) {
ctrl_mask |= PCI_EXP_SLTCTL_PDCE;
stat_mask |= PCI_EXP_SLTSTA_PDC;
}
ctrl_mask |= PCI_EXP_SLTCTL_DLLSCE;
stat_mask |= PCI_EXP_SLTSTA_DLLSC;
pcie_write_cmd(ctrl, 0, ctrl_mask);
if (pciehp_poll_mode)
del_timer_sync(&ctrl->poll_timer);
pci_reset_bridge_secondary_bus(ctrl->pcie->port);
if (HP_SUPR_RM(ctrl)) {
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_PDC);
pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE);
if (pciehp_poll_mode)
int_poll_timeout(ctrl->poll_timer.data);
}
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask);
pcie_write_cmd(ctrl, ctrl_mask, ctrl_mask);
if (pciehp_poll_mode)
int_poll_timeout(ctrl->poll_timer.data);
return 0;
}
@ -687,6 +687,7 @@ static int pcie_init_slot(struct controller *ctrl)
slot->ctrl = ctrl;
mutex_init(&slot->lock);
mutex_init(&slot->hotplug_lock);
INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
ctrl->slot = slot;
return 0;

View File

@ -50,7 +50,7 @@ int pciehp_configure_device(struct slot *p_slot)
"at %04x:%02x:00, cannot hot-add\n", pci_name(dev),
pci_domain_nr(parent), parent->number);
pci_dev_put(dev);
ret = -EINVAL;
ret = -EEXIST;
goto out;
}

View File

@ -170,97 +170,6 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset)
pci_dev_put(dev);
}
static int sriov_migration(struct pci_dev *dev)
{
u16 status;
struct pci_sriov *iov = dev->sriov;
if (!iov->num_VFs)
return 0;
if (!(iov->cap & PCI_SRIOV_CAP_VFM))
return 0;
pci_read_config_word(dev, iov->pos + PCI_SRIOV_STATUS, &status);
if (!(status & PCI_SRIOV_STATUS_VFM))
return 0;
schedule_work(&iov->mtask);
return 1;
}
static void sriov_migration_task(struct work_struct *work)
{
int i;
u8 state;
u16 status;
struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask);
for (i = iov->initial_VFs; i < iov->num_VFs; i++) {
state = readb(iov->mstate + i);
if (state == PCI_SRIOV_VFM_MI) {
writeb(PCI_SRIOV_VFM_AV, iov->mstate + i);
state = readb(iov->mstate + i);
if (state == PCI_SRIOV_VFM_AV)
virtfn_add(iov->self, i, 1);
} else if (state == PCI_SRIOV_VFM_MO) {
virtfn_remove(iov->self, i, 1);
writeb(PCI_SRIOV_VFM_UA, iov->mstate + i);
state = readb(iov->mstate + i);
if (state == PCI_SRIOV_VFM_AV)
virtfn_add(iov->self, i, 0);
}
}
pci_read_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, &status);
status &= ~PCI_SRIOV_STATUS_VFM;
pci_write_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, status);
}
static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn)
{
int bir;
u32 table;
resource_size_t pa;
struct pci_sriov *iov = dev->sriov;
if (nr_virtfn <= iov->initial_VFs)
return 0;
pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table);
bir = PCI_SRIOV_VFM_BIR(table);
if (bir > PCI_STD_RESOURCE_END)
return -EIO;
table = PCI_SRIOV_VFM_OFFSET(table);
if (table + nr_virtfn > pci_resource_len(dev, bir))
return -EIO;
pa = pci_resource_start(dev, bir) + table;
iov->mstate = ioremap(pa, nr_virtfn);
if (!iov->mstate)
return -ENOMEM;
INIT_WORK(&iov->mtask, sriov_migration_task);
iov->ctrl |= PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR;
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
return 0;
}
static void sriov_disable_migration(struct pci_dev *dev)
{
struct pci_sriov *iov = dev->sriov;
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
cancel_work_sync(&iov->mtask);
iounmap(iov->mstate);
}
static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
{
int rc;
@ -351,12 +260,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
goto failed;
}
if (iov->cap & PCI_SRIOV_CAP_VFM) {
rc = sriov_enable_migration(dev, nr_virtfn);
if (rc)
goto failed;
}
kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
iov->num_VFs = nr_virtfn;
@ -387,9 +290,6 @@ static void sriov_disable(struct pci_dev *dev)
if (!iov->num_VFs)
return;
if (iov->cap & PCI_SRIOV_CAP_VFM)
sriov_disable_migration(dev);
for (i = 0; i < iov->num_VFs; i++)
virtfn_remove(dev, i, 0);
@ -687,25 +587,6 @@ void pci_disable_sriov(struct pci_dev *dev)
}
EXPORT_SYMBOL_GPL(pci_disable_sriov);
/**
* pci_sriov_migration - notify SR-IOV core of Virtual Function Migration
* @dev: the PCI device
*
* Returns IRQ_HANDLED if the IRQ is handled, or IRQ_NONE if not.
*
* Physical Function driver is responsible to register IRQ handler using
* VF Migration Interrupt Message Number, and call this function when the
* interrupt is generated by the hardware.
*/
irqreturn_t pci_sriov_migration(struct pci_dev *dev)
{
if (!dev->is_physfn)
return IRQ_NONE;
return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE;
}
EXPORT_SYMBOL_GPL(pci_sriov_migration);
/**
* pci_num_vf - return number of VFs associated with a PF device_release_driver
* @dev: the PCI device

View File

@ -108,12 +108,12 @@ static bool pcie_ari_disabled;
*/
unsigned char pci_bus_max_busnr(struct pci_bus* bus)
{
struct list_head *tmp;
struct pci_bus *tmp;
unsigned char max, n;
max = bus->busn_res.end;
list_for_each(tmp, &bus->children) {
n = pci_bus_max_busnr(pci_bus_b(tmp));
list_for_each_entry(tmp, &bus->children, node) {
n = pci_bus_max_busnr(tmp);
if(n > max)
max = n;
}
@ -401,33 +401,40 @@ EXPORT_SYMBOL_GPL(pci_find_ht_capability);
* @res: child resource record for which parent is sought
*
* For given resource region of given device, return the resource
* region of parent bus the given region is contained in or where
* it should be allocated from.
* region of parent bus the given region is contained in.
*/
struct resource *
pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
{
const struct pci_bus *bus = dev->bus;
struct resource *r;
int i;
struct resource *best = NULL, *r;
pci_bus_for_each_resource(bus, r, i) {
if (!r)
continue;
if (res->start && !(res->start >= r->start && res->end <= r->end))
continue; /* Not contained */
if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
continue; /* Wrong type */
if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH))
return r; /* Exact match */
/* We can't insert a non-prefetch resource inside a prefetchable parent .. */
if (r->flags & IORESOURCE_PREFETCH)
continue;
/* .. but we can put a prefetchable resource inside a non-prefetchable one */
if (!best)
best = r;
if (res->start && resource_contains(r, res)) {
/*
* If the window is prefetchable but the BAR is
* not, the allocator made a mistake.
*/
if (r->flags & IORESOURCE_PREFETCH &&
!(res->flags & IORESOURCE_PREFETCH))
return NULL;
/*
* If we're below a transparent bridge, there may
* be both a positively-decoded aperture and a
* subtractively-decoded region that contain the BAR.
* We want the positively-decoded one, so this depends
* on pci_bus_for_each_resource() giving us those
* first.
*/
return r;
}
}
return best;
return NULL;
}
/**
@ -1178,6 +1185,11 @@ int pci_load_and_free_saved_state(struct pci_dev *dev,
}
EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
int __weak pcibios_enable_device(struct pci_dev *dev, int bars)
{
return pci_enable_resources(dev, bars);
}
static int do_pci_enable_device(struct pci_dev *dev, int bars)
{
int err;
@ -1624,29 +1636,27 @@ static void pci_pme_list_scan(struct work_struct *work)
struct pci_pme_device *pme_dev, *n;
mutex_lock(&pci_pme_list_mutex);
if (!list_empty(&pci_pme_list)) {
list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
if (pme_dev->dev->pme_poll) {
struct pci_dev *bridge;
list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
if (pme_dev->dev->pme_poll) {
struct pci_dev *bridge;
bridge = pme_dev->dev->bus->self;
/*
* If bridge is in low power state, the
* configuration space of subordinate devices
* may be not accessible
*/
if (bridge && bridge->current_state != PCI_D0)
continue;
pci_pme_wakeup(pme_dev->dev, NULL);
} else {
list_del(&pme_dev->list);
kfree(pme_dev);
}
bridge = pme_dev->dev->bus->self;
/*
* If bridge is in low power state, the
* configuration space of subordinate devices
* may be not accessible
*/
if (bridge && bridge->current_state != PCI_D0)
continue;
pci_pme_wakeup(pme_dev->dev, NULL);
} else {
list_del(&pme_dev->list);
kfree(pme_dev);
}
if (!list_empty(&pci_pme_list))
schedule_delayed_work(&pci_pme_work,
msecs_to_jiffies(PME_TIMEOUT));
}
if (!list_empty(&pci_pme_list))
schedule_delayed_work(&pci_pme_work,
msecs_to_jiffies(PME_TIMEOUT));
mutex_unlock(&pci_pme_list_mutex);
}
@ -2193,21 +2203,18 @@ void pci_request_acs(void)
}
/**
* pci_enable_acs - enable ACS if hardware support it
* pci_std_enable_acs - enable ACS on devices using standard ACS capabilites
* @dev: the PCI device
*/
void pci_enable_acs(struct pci_dev *dev)
static int pci_std_enable_acs(struct pci_dev *dev)
{
int pos;
u16 cap;
u16 ctrl;
if (!pci_acs_enable)
return;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
if (!pos)
return;
return -ENODEV;
pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
@ -2225,6 +2232,23 @@ void pci_enable_acs(struct pci_dev *dev)
ctrl |= (cap & PCI_ACS_UF);
pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
return 0;
}
/**
* pci_enable_acs - enable ACS if hardware support it
* @dev: the PCI device
*/
void pci_enable_acs(struct pci_dev *dev)
{
if (!pci_acs_enable)
return;
if (!pci_std_enable_acs(dev))
return;
pci_dev_specific_enable_acs(dev);
}
static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
@ -4250,6 +4274,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
"Rounding up size of resource #%d to %#llx.\n",
i, (unsigned long long)size);
}
r->flags |= IORESOURCE_UNSET;
r->end = size - 1;
r->start = 0;
}
@ -4263,6 +4288,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
r = &dev->resource[i];
if (!(r->flags & IORESOURCE_MEM))
continue;
r->flags |= IORESOURCE_UNSET;
r->end = resource_size(r) - 1;
r->start = 0;
}

View File

@ -1,8 +1,6 @@
#ifndef DRIVERS_PCI_H
#define DRIVERS_PCI_H
#include <linux/workqueue.h>
#define PCI_CFG_SPACE_SIZE 256
#define PCI_CFG_SPACE_EXP_SIZE 4096
@ -240,8 +238,6 @@ struct pci_sriov {
struct pci_dev *dev; /* lowest numbered PF */
struct pci_dev *self; /* this PF */
struct mutex lock; /* lock for VF bus */
struct work_struct mtask; /* VF Migration task */
u8 __iomem *mstate; /* VF Migration State Array */
};
#ifdef CONFIG_PCI_ATS

View File

@ -252,6 +252,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
/* Address above 32-bit boundary; disable the BAR */
pci_write_config_dword(dev, pos, 0);
pci_write_config_dword(dev, pos + 4, 0);
res->flags |= IORESOURCE_UNSET;
region.start = 0;
region.end = sz64;
bar_disabled = true;
@ -731,22 +732,6 @@ struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *de
return child;
}
static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
{
struct pci_bus *parent = child->parent;
/* Attempts to fix that up are really dangerous unless
we're going to re-assign all bus numbers. */
if (!pcibios_assign_all_busses())
return;
while (parent->parent && parent->busn_res.end < max) {
parent->busn_res.end = max;
pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
parent = parent->parent;
}
}
/*
* If it's a bridge, configure it and scan the bus behind it.
* For CardBus bridges, we don't scan behind as the devices will
@ -782,7 +767,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
/* Check if setup is sensible at all */
if (!pass &&
(primary != bus->number || secondary <= bus->number ||
secondary > subordinate)) {
secondary > subordinate || subordinate > bus->busn_res.end)) {
dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n",
secondary, subordinate);
broken = 1;
@ -805,11 +790,10 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
goto out;
/*
* If we already got to this bus through a different bridge,
* don't re-add it. This can happen with the i450NX chipset.
*
* However, we continue to descend down the hierarchy and
* scan remaining child buses.
* The bus might already exist for two reasons: Either we are
* rescanning the bus or the bus is reachable through more than
* one bridge. The second case can happen with the i450NX
* chipset.
*/
child = pci_find_bus(pci_domain_nr(bus), secondary);
if (!child) {
@ -822,17 +806,19 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
}
cmax = pci_scan_child_bus(child);
if (cmax > max)
max = cmax;
if (child->busn_res.end > max)
max = child->busn_res.end;
if (cmax > subordinate)
dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n",
subordinate, cmax);
/* subordinate should equal child->busn_res.end */
if (subordinate > max)
max = subordinate;
} else {
/*
* We need to assign a number to this bus which we always
* do in the second pass.
*/
if (!pass) {
if (pcibios_assign_all_busses() || broken)
if (pcibios_assign_all_busses() || broken || is_cardbus)
/* Temporarily disable forwarding of the
configuration cycles on all bridges in
this bus segment to avoid possible
@ -844,19 +830,25 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
goto out;
}
if (max >= bus->busn_res.end) {
dev_warn(&dev->dev, "can't allocate child bus %02x from %pR\n",
max, &bus->busn_res);
goto out;
}
/* Clear errors */
pci_write_config_word(dev, PCI_STATUS, 0xffff);
/* Prevent assigning a bus number that already exists.
* This can happen when a bridge is hot-plugged, so in
* this case we only re-scan this bus. */
/* The bus will already exist if we are rescanning */
child = pci_find_bus(pci_domain_nr(bus), max+1);
if (!child) {
child = pci_add_new_bus(bus, dev, ++max);
child = pci_add_new_bus(bus, dev, max+1);
if (!child)
goto out;
pci_bus_insert_busn_res(child, max, 0xff);
pci_bus_insert_busn_res(child, max+1,
bus->busn_res.end);
}
max++;
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
| ((unsigned int)(child->busn_res.start) << 8)
@ -878,20 +870,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
if (!is_cardbus) {
child->bridge_ctl = bctl;
/*
* Adjust subordinate busnr in parent buses.
* We do this before scanning for children because
* some devices may not be detected if the bios
* was lazy.
*/
pci_fixup_parent_subordinate_busnr(child, max);
/* Now we can scan all subordinate buses... */
max = pci_scan_child_bus(child);
/*
* now fix it up again since we have found
* the real value of max.
*/
pci_fixup_parent_subordinate_busnr(child, max);
} else {
/*
* For CardBus bridges, we leave 4 bus numbers
@ -922,11 +901,15 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
}
}
max += i;
pci_fixup_parent_subordinate_busnr(child, max);
}
/*
* Set the subordinate bus number to its real value.
*/
if (max > bus->busn_res.end) {
dev_warn(&dev->dev, "max busn %02x is outside %pR\n",
max, &bus->busn_res);
max = bus->busn_res.end;
}
pci_bus_update_busn_res_end(child, max);
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
}
@ -1125,10 +1108,10 @@ int pci_setup_device(struct pci_dev *dev)
pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);
/*
* Do the ugly legacy mode stuff here rather than broken chip
* quirk code. Legacy mode ATA controllers have fixed
* addresses. These are not always echoed in BAR0-3, and
* BAR0-3 in a few cases contain junk!
* Do the ugly legacy mode stuff here rather than broken chip
* quirk code. Legacy mode ATA controllers have fixed
* addresses. These are not always echoed in BAR0-3, and
* BAR0-3 in a few cases contain junk!
*/
if (class == PCI_CLASS_STORAGE_IDE) {
u8 progif;
@ -1139,11 +1122,15 @@ int pci_setup_device(struct pci_dev *dev)
res = &dev->resource[0];
res->flags = LEGACY_IO_RESOURCE;
pcibios_bus_to_resource(dev->bus, res, &region);
dev_info(&dev->dev, "legacy IDE quirk: reg 0x10: %pR\n",
res);
region.start = 0x3F6;
region.end = 0x3F6;
res = &dev->resource[1];
res->flags = LEGACY_IO_RESOURCE;
pcibios_bus_to_resource(dev->bus, res, &region);
dev_info(&dev->dev, "legacy IDE quirk: reg 0x14: %pR\n",
res);
}
if ((progif & 4) == 0) {
region.start = 0x170;
@ -1151,11 +1138,15 @@ int pci_setup_device(struct pci_dev *dev)
res = &dev->resource[2];
res->flags = LEGACY_IO_RESOURCE;
pcibios_bus_to_resource(dev->bus, res, &region);
dev_info(&dev->dev, "legacy IDE quirk: reg 0x18: %pR\n",
res);
region.start = 0x376;
region.end = 0x376;
res = &dev->resource[3];
res->flags = LEGACY_IO_RESOURCE;
pcibios_bus_to_resource(dev->bus, res, &region);
dev_info(&dev->dev, "legacy IDE quirk: reg 0x1c: %pR\n",
res);
}
}
break;
@ -1835,7 +1826,7 @@ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
res->flags |= IORESOURCE_PCI_FIXED;
}
conflict = insert_resource_conflict(parent_res, res);
conflict = request_resource_conflict(parent_res, res);
if (conflict)
dev_printk(KERN_DEBUG, &b->dev,

View File

@ -296,6 +296,7 @@ static void quirk_s3_64M(struct pci_dev *dev)
struct resource *r = &dev->resource[0];
if ((r->start & 0x3ffffff) || r->end != r->start + 0x3ffffff) {
r->flags |= IORESOURCE_UNSET;
r->start = 0;
r->end = 0x3ffffff;
}
@ -937,6 +938,8 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C
static void quirk_dunord(struct pci_dev *dev)
{
struct resource *r = &dev->resource [1];
r->flags |= IORESOURCE_UNSET;
r->start = 0;
r->end = 0xffffff;
}
@ -1740,6 +1743,7 @@ static void quirk_tc86c001_ide(struct pci_dev *dev)
struct resource *r = &dev->resource[0];
if (r->start & 0x8) {
r->flags |= IORESOURCE_UNSET;
r->start = 0;
r->end = 0xf;
}
@ -1769,6 +1773,7 @@ static void quirk_plx_pci9050(struct pci_dev *dev)
dev_info(&dev->dev,
"Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
bar);
r->flags |= IORESOURCE_UNSET;
r->start = 0;
r->end = 0xff;
}
@ -3423,6 +3428,61 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
#endif
}
/*
* Many Intel PCH root ports do provide ACS-like features to disable peer
* transactions and validate bus numbers in requests, but do not provide an
* actual PCIe ACS capability. This is the list of device IDs known to fall
* into that category as provided by Intel in Red Hat bugzilla 1037684.
*/
static const u16 pci_quirk_intel_pch_acs_ids[] = {
/* Ibexpeak PCH */
0x3b42, 0x3b43, 0x3b44, 0x3b45, 0x3b46, 0x3b47, 0x3b48, 0x3b49,
0x3b4a, 0x3b4b, 0x3b4c, 0x3b4d, 0x3b4e, 0x3b4f, 0x3b50, 0x3b51,
/* Cougarpoint PCH */
0x1c10, 0x1c11, 0x1c12, 0x1c13, 0x1c14, 0x1c15, 0x1c16, 0x1c17,
0x1c18, 0x1c19, 0x1c1a, 0x1c1b, 0x1c1c, 0x1c1d, 0x1c1e, 0x1c1f,
/* Pantherpoint PCH */
0x1e10, 0x1e11, 0x1e12, 0x1e13, 0x1e14, 0x1e15, 0x1e16, 0x1e17,
0x1e18, 0x1e19, 0x1e1a, 0x1e1b, 0x1e1c, 0x1e1d, 0x1e1e, 0x1e1f,
/* Lynxpoint-H PCH */
0x8c10, 0x8c11, 0x8c12, 0x8c13, 0x8c14, 0x8c15, 0x8c16, 0x8c17,
0x8c18, 0x8c19, 0x8c1a, 0x8c1b, 0x8c1c, 0x8c1d, 0x8c1e, 0x8c1f,
/* Lynxpoint-LP PCH */
0x9c10, 0x9c11, 0x9c12, 0x9c13, 0x9c14, 0x9c15, 0x9c16, 0x9c17,
0x9c18, 0x9c19, 0x9c1a, 0x9c1b,
/* Wildcat PCH */
0x9c90, 0x9c91, 0x9c92, 0x9c93, 0x9c94, 0x9c95, 0x9c96, 0x9c97,
0x9c98, 0x9c99, 0x9c9a, 0x9c9b,
};
static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev)
{
int i;
/* Filter out a few obvious non-matches first */
if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
return false;
for (i = 0; i < ARRAY_SIZE(pci_quirk_intel_pch_acs_ids); i++)
if (pci_quirk_intel_pch_acs_ids[i] == dev->device)
return true;
return false;
}
#define INTEL_PCH_ACS_FLAGS (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV)
static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
{
u16 flags = dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK ?
INTEL_PCH_ACS_FLAGS : 0;
if (!pci_quirk_intel_pch_acs_match(dev))
return -ENOTTY;
return acs_flags & ~flags ? 0 : 1;
}
static const struct pci_dev_acs_enabled {
u16 vendor;
u16 device;
@ -3434,6 +3494,7 @@ static const struct pci_dev_acs_enabled {
{ PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs },
{ PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs },
{ PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs },
{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
{ 0 }
};
@ -3461,3 +3522,132 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
return -ENOTTY;
}
/* Config space offset of Root Complex Base Address register */
#define INTEL_LPC_RCBA_REG 0xf0
/* 31:14 RCBA address */
#define INTEL_LPC_RCBA_MASK 0xffffc000
/* RCBA Enable */
#define INTEL_LPC_RCBA_ENABLE (1 << 0)
/* Backbone Scratch Pad Register */
#define INTEL_BSPR_REG 0x1104
/* Backbone Peer Non-Posted Disable */
#define INTEL_BSPR_REG_BPNPD (1 << 8)
/* Backbone Peer Posted Disable */
#define INTEL_BSPR_REG_BPPD (1 << 9)
/* Upstream Peer Decode Configuration Register */
#define INTEL_UPDCR_REG 0x1114
/* 5:0 Peer Decode Enable bits */
#define INTEL_UPDCR_REG_MASK 0x3f
static int pci_quirk_enable_intel_lpc_acs(struct pci_dev *dev)
{
u32 rcba, bspr, updcr;
void __iomem *rcba_mem;
/*
* Read the RCBA register from the LPC (D31:F0). PCH root ports
* are D28:F* and therefore get probed before LPC, thus we can't
* use pci_get_slot/pci_read_config_dword here.
*/
pci_bus_read_config_dword(dev->bus, PCI_DEVFN(31, 0),
INTEL_LPC_RCBA_REG, &rcba);
if (!(rcba & INTEL_LPC_RCBA_ENABLE))
return -EINVAL;
rcba_mem = ioremap_nocache(rcba & INTEL_LPC_RCBA_MASK,
PAGE_ALIGN(INTEL_UPDCR_REG));
if (!rcba_mem)
return -ENOMEM;
/*
* The BSPR can disallow peer cycles, but it's set by soft strap and
* therefore read-only. If both posted and non-posted peer cycles are
* disallowed, we're ok. If either are allowed, then we need to use
* the UPDCR to disable peer decodes for each port. This provides the
* PCIe ACS equivalent of PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF
*/
bspr = readl(rcba_mem + INTEL_BSPR_REG);
bspr &= INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD;
if (bspr != (INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD)) {
updcr = readl(rcba_mem + INTEL_UPDCR_REG);
if (updcr & INTEL_UPDCR_REG_MASK) {
dev_info(&dev->dev, "Disabling UPDCR peer decodes\n");
updcr &= ~INTEL_UPDCR_REG_MASK;
writel(updcr, rcba_mem + INTEL_UPDCR_REG);
}
}
iounmap(rcba_mem);
return 0;
}
/* Miscellaneous Port Configuration register */
#define INTEL_MPC_REG 0xd8
/* MPC: Invalid Receive Bus Number Check Enable */
#define INTEL_MPC_REG_IRBNCE (1 << 26)
static void pci_quirk_enable_intel_rp_mpc_acs(struct pci_dev *dev)
{
u32 mpc;
/*
* When enabled, the IRBNCE bit of the MPC register enables the
* equivalent of PCI ACS Source Validation (PCI_ACS_SV), which
* ensures that requester IDs fall within the bus number range
* of the bridge. Enable if not already.
*/
pci_read_config_dword(dev, INTEL_MPC_REG, &mpc);
if (!(mpc & INTEL_MPC_REG_IRBNCE)) {
dev_info(&dev->dev, "Enabling MPC IRBNCE\n");
mpc |= INTEL_MPC_REG_IRBNCE;
pci_write_config_word(dev, INTEL_MPC_REG, mpc);
}
}
static int pci_quirk_enable_intel_pch_acs(struct pci_dev *dev)
{
if (!pci_quirk_intel_pch_acs_match(dev))
return -ENOTTY;
if (pci_quirk_enable_intel_lpc_acs(dev)) {
dev_warn(&dev->dev, "Failed to enable Intel PCH ACS quirk\n");
return 0;
}
pci_quirk_enable_intel_rp_mpc_acs(dev);
dev->dev_flags |= PCI_DEV_FLAGS_ACS_ENABLED_QUIRK;
dev_info(&dev->dev, "Intel PCH root port ACS workaround enabled\n");
return 0;
}
static const struct pci_dev_enable_acs {
u16 vendor;
u16 device;
int (*enable_acs)(struct pci_dev *dev);
} pci_dev_enable_acs[] = {
{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs },
{ 0 }
};
void pci_dev_specific_enable_acs(struct pci_dev *dev)
{
const struct pci_dev_enable_acs *i;
int ret;
for (i = pci_dev_enable_acs; i->enable_acs; i++) {
if ((i->vendor == dev->vendor ||
i->vendor == (u16)PCI_ANY_ID) &&
(i->device == dev->device ||
i->device == (u16)PCI_ANY_ID)) {
ret = i->enable_acs(dev);
if (ret >= 0)
return;
}
}
}

View File

@ -197,8 +197,10 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
void pci_cleanup_rom(struct pci_dev *pdev)
{
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
if (res->flags & IORESOURCE_ROM_COPY) {
kfree((void*)(unsigned long)res->start);
res->flags |= IORESOURCE_UNSET;
res->flags &= ~IORESOURCE_ROM_COPY;
res->start = 0;
res->end = 0;

View File

@ -54,14 +54,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
{
struct pci_bus* child;
struct list_head *tmp;
struct pci_bus *child;
struct pci_bus *tmp;
if(bus->number == busnr)
return bus;
list_for_each(tmp, &bus->children) {
child = pci_do_find_bus(pci_bus_b(tmp), busnr);
list_for_each_entry(tmp, &bus->children, node) {
child = pci_do_find_bus(tmp, busnr);
if(child)
return child;
}
@ -111,7 +111,7 @@ pci_find_next_bus(const struct pci_bus *from)
down_read(&pci_bus_sem);
n = from ? from->node.next : pci_root_buses.next;
if (n != &pci_root_buses)
b = pci_bus_b(n);
b = list_entry(n, struct pci_bus, node);
up_read(&pci_bus_sem);
return b;
}

View File

@ -44,6 +44,9 @@ void pci_update_resource(struct pci_dev *dev, int resno)
if (!res->flags)
return;
if (res->flags & IORESOURCE_UNSET)
return;
/*
* Ignore non-moveable resources. This might be legacy resources for
* which no functional BAR register exists or another important
@ -101,11 +104,6 @@ void pci_update_resource(struct pci_dev *dev, int resno)
if (disable)
pci_write_config_word(dev, PCI_COMMAND, cmd);
res->flags &= ~IORESOURCE_UNSET;
dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
resno, res, (unsigned long long)region.start,
(unsigned long long)region.end);
}
int pci_claim_resource(struct pci_dev *dev, int resource)
@ -113,18 +111,23 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
struct resource *res = &dev->resource[resource];
struct resource *root, *conflict;
if (res->flags & IORESOURCE_UNSET) {
dev_info(&dev->dev, "can't claim BAR %d %pR: no address assigned\n",
resource, res);
return -EINVAL;
}
root = pci_find_parent_resource(dev, res);
if (!root) {
dev_info(&dev->dev, "no compatible bridge window for %pR\n",
res);
dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n",
resource, res);
return -EINVAL;
}
conflict = request_resource_conflict(root, res);
if (conflict) {
dev_info(&dev->dev,
"address space collision: %pR conflicts with %s %pR\n",
res, conflict->name, conflict);
dev_info(&dev->dev, "can't claim BAR %d %pR: address conflict with %s %pR\n",
resource, res, conflict->name, conflict);
return -EBUSY;
}
@ -263,6 +266,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
resource_size_t align, size;
int ret;
res->flags |= IORESOURCE_UNSET;
align = pci_resource_alignment(dev, res);
if (!align) {
dev_info(&dev->dev, "BAR %d: can't assign %pR "
@ -282,6 +286,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
ret = pci_revert_fw_address(res, dev, resno, size);
if (!ret) {
res->flags &= ~IORESOURCE_UNSET;
res->flags &= ~IORESOURCE_STARTALIGN;
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
if (resno < PCI_BRIDGE_RESOURCES)
@ -297,6 +302,7 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
resource_size_t new_size;
int ret;
res->flags |= IORESOURCE_UNSET;
if (!res->parent) {
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
"\n", resno, res);
@ -307,6 +313,7 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
new_size = resource_size(res) + addsize;
ret = _pci_assign_resource(dev, resno, new_size, min_align);
if (!ret) {
res->flags &= ~IORESOURCE_UNSET;
res->flags &= ~IORESOURCE_STARTALIGN;
dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
if (resno < PCI_BRIDGE_RESOURCES)
@ -336,9 +343,15 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
(!(r->flags & IORESOURCE_ROM_ENABLE)))
continue;
if (r->flags & IORESOURCE_UNSET) {
dev_err(&dev->dev, "can't enable device: BAR %d %pR not assigned\n",
i, r);
return -EINVAL;
}
if (!r->parent) {
dev_err(&dev->dev, "device not available "
"(can't reserve %pR)\n", r);
dev_err(&dev->dev, "can't enable device: BAR %d %pR not claimed\n",
i, r);
return -EINVAL;
}

View File

@ -1076,7 +1076,7 @@ static void yenta_config_init(struct yenta_socket *socket)
*/
static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
{
struct list_head *tmp;
struct pci_bus *sibling;
unsigned char upper_limit;
/*
* We only check and fix the parent bridge: All systems which need
@ -1095,18 +1095,18 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
/* stay within the limits of the bus range of the parent: */
upper_limit = bridge_to_fix->parent->busn_res.end;
/* check the bus ranges of all silbling bridges to prevent overlap */
list_for_each(tmp, &bridge_to_fix->parent->children) {
struct pci_bus *silbling = pci_bus_b(tmp);
/* check the bus ranges of all sibling bridges to prevent overlap */
list_for_each_entry(sibling, &bridge_to_fix->parent->children,
node) {
/*
* If the silbling has a higher secondary bus number
* If the sibling has a higher secondary bus number
* and it's secondary is equal or smaller than our
* current upper limit, set the new upper limit to
* the bus number below the silbling's range:
* the bus number below the sibling's range:
*/
if (silbling->busn_res.start > bridge_to_fix->busn_res.end
&& silbling->busn_res.start <= upper_limit)
upper_limit = silbling->busn_res.start - 1;
if (sibling->busn_res.start > bridge_to_fix->busn_res.end
&& sibling->busn_res.start <= upper_limit)
upper_limit = sibling->busn_res.start - 1;
}
/* Show that the wanted subordinate number is not possible: */

View File

@ -482,15 +482,19 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
for (i = 0; i < nvec; i++)
vdev->msix[i].entry = i;
ret = pci_enable_msix(pdev, vdev->msix, nvec);
if (ret) {
ret = pci_enable_msix_range(pdev, vdev->msix, 1, nvec);
if (ret < nvec) {
if (ret > 0)
pci_disable_msix(pdev);
kfree(vdev->msix);
kfree(vdev->ctx);
return ret;
}
} else {
ret = pci_enable_msi_block(pdev, nvec);
if (ret) {
ret = pci_enable_msi_range(pdev, 1, nvec);
if (ret < nvec) {
if (ret > 0)
pci_disable_msi(pdev);
kfree(vdev->ctx);
return ret;
}

View File

@ -13,7 +13,6 @@
extern int pxm_to_node(int);
extern int node_to_pxm(int);
extern void __acpi_map_pxm_to_node(int, int);
extern int acpi_map_pxm_to_node(int);
extern unsigned char acpi_srat_revision;

View File

@ -263,14 +263,9 @@ extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
extern void acpi_osi_setup(char *str);
#ifdef CONFIG_ACPI_NUMA
int acpi_get_pxm(acpi_handle handle);
int acpi_get_node(acpi_handle *handle);
int acpi_get_node(acpi_handle handle);
#else
static inline int acpi_get_pxm(acpi_handle handle)
{
return 0;
}
static inline int acpi_get_node(acpi_handle *handle)
static inline int acpi_get_node(acpi_handle handle)
{
return 0;
}

View File

@ -51,7 +51,7 @@ struct resource {
#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */
#define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000
#define IORESOURCE_UNSET 0x20000000 /* No address assigned yet */
#define IORESOURCE_AUTO 0x40000000
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
@ -169,6 +169,16 @@ static inline unsigned long resource_type(const struct resource *res)
{
return res->flags & IORESOURCE_TYPE_BITS;
}
/* True iff r1 completely contains r2 */
static inline bool resource_contains(struct resource *r1, struct resource *r2)
{
if (resource_type(r1) != resource_type(r2))
return false;
if (r1->flags & IORESOURCE_UNSET || r2->flags & IORESOURCE_UNSET)
return false;
return r1->start <= r2->start && r1->end >= r2->end;
}
/* Convenience shorthand with allocation */
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0)

View File

@ -29,7 +29,6 @@
#include <linux/atomic.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/irqreturn.h>
#include <uapi/linux/pci.h>
#include <linux/pci_ids.h>
@ -170,6 +169,8 @@ enum pci_dev_flags {
PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
/* Provide indication device is assigned by a Virtual Machine Manager */
PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
/* Flag for quirk use to store if quirk-specific ACS is enabled */
PCI_DEV_FLAGS_ACS_ENABLED_QUIRK = (__force pci_dev_flags_t) 8,
};
enum pci_irq_reroute_variant {
@ -461,7 +462,6 @@ struct pci_bus {
unsigned int is_added:1;
};
#define pci_bus_b(n) list_entry(n, struct pci_bus, node)
#define to_pci_bus(n) container_of(n, struct pci_bus, dev)
/*
@ -1066,7 +1066,7 @@ void pci_bus_remove_resources(struct pci_bus *bus);
int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
struct resource *res, resource_size_t size,
resource_size_t align, resource_size_t min,
unsigned int type_mask,
unsigned long type_mask,
resource_size_t (*alignf)(void *,
const struct resource *,
resource_size_t,
@ -1530,6 +1530,7 @@ enum pci_fixup_pass {
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
struct pci_dev *pci_get_dma_source(struct pci_dev *dev);
int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags);
void pci_dev_specific_enable_acs(struct pci_dev *dev);
#else
static inline void pci_fixup_device(enum pci_fixup_pass pass,
struct pci_dev *dev) { }
@ -1542,6 +1543,7 @@ static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev,
{
return -ENOTTY;
}
static inline void pci_dev_specific_enable_acs(struct pci_dev *dev) { }
#endif
void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
@ -1597,7 +1599,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
#ifdef CONFIG_PCI_IOV
int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
void pci_disable_sriov(struct pci_dev *dev);
irqreturn_t pci_sriov_migration(struct pci_dev *dev);
int pci_num_vf(struct pci_dev *dev);
int pci_vfs_assigned(struct pci_dev *dev);
int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
@ -1606,8 +1607,6 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev);
static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
{ return -ENODEV; }
static inline void pci_disable_sriov(struct pci_dev *dev) { }
static inline irqreturn_t pci_sriov_migration(struct pci_dev *dev)
{ return IRQ_NONE; }
static inline int pci_num_vf(struct pci_dev *dev) { return 0; }
static inline int pci_vfs_assigned(struct pci_dev *dev)
{ return 0; }

View File

@ -432,11 +432,6 @@ static void resource_clip(struct resource *res, resource_size_t min,
res->end = max;
}
static bool resource_contains(struct resource *res1, struct resource *res2)
{
return res1->start <= res2->start && res1->end >= res2->end;
}
/*
* Find empty slot in the resource tree with the given range and
* alignment constraints
@ -471,10 +466,11 @@ static int __find_resource(struct resource *root, struct resource *old,
arch_remove_reservations(&tmp);
/* Check for overflow after ALIGN() */
avail = *new;
avail.start = ALIGN(tmp.start, constraint->align);
avail.end = tmp.end;
avail.flags = new->flags & ~IORESOURCE_UNSET;
if (avail.start >= tmp.start) {
alloc.flags = avail.flags;
alloc.start = constraint->alignf(constraint->alignf_data, &avail,
size, constraint->align);
alloc.end = alloc.start + size - 1;
@ -949,8 +945,8 @@ struct resource * __request_region(struct resource *parent,
res->name = name;
res->start = start;
res->end = start + n - 1;
res->flags = IORESOURCE_BUSY;
res->flags |= flags;
res->flags = resource_type(parent);
res->flags |= IORESOURCE_BUSY | flags;
write_lock(&resource_lock);

View File

@ -719,10 +719,15 @@ char *resource_string(char *buf, char *end, struct resource *res,
specp = &mem_spec;
decode = 0;
}
p = number(p, pend, res->start, *specp);
if (res->start != res->end) {
*p++ = '-';
p = number(p, pend, res->end, *specp);
if (decode && res->flags & IORESOURCE_UNSET) {
p = string(p, pend, "size ", str_spec);
p = number(p, pend, resource_size(res), *specp);
} else {
p = number(p, pend, res->start, *specp);
if (res->start != res->end) {
*p++ = '-';
p = number(p, pend, res->end, *specp);
}
}
if (decode) {
if (res->flags & IORESOURCE_MEM_64)