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:
commit
4b1779c2cf
68 changed files with 942 additions and 862 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define _MEI_INTERFACE_H_
|
||||
|
||||
#include <linux/mei.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include "mei_dev.h"
|
||||
#include "client.h"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/cdev.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/irqreturn.h>
|
||||
|
||||
#include "mic_intr.h"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, ®ion);
|
||||
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, ®ion);
|
||||
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, ®ion);
|
||||
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, ®ion);
|
||||
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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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: */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue