Commit a9238741 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull PCI changes from Bjorn Helgaas:

  PCI device hotplug:
    - Use PCIe native hotplug, not ACPI hotplug, when possible (Neil Horman)
    - Assign resources on per-host bridge basis (Yinghai Lu)

  MPS (Max Payload Size):
    - Allow larger MPS settings below hotplug-capable Root Port (Yijing Wang)
    - Add warnings about unsafe MPS settings (Yijing Wang)
    - Simplify interface and messages (Bjorn Helgaas)

  SR-IOV:
    - Return -ENOSYS on non-SR-IOV devices (Stefan Assmann)
    - Update NumVFs register when disabling SR-IOV (Yijing Wang)

  Virtualization:
    - Add bus and slot reset support (Alex Williamson)
    - Fix ACS (Access Control Services) issues (Alex Williamson)

  Miscellaneous:
    - Simplify PCIe Capability accessors (Bjorn Helgaas)
    - Add pcibios_pm_ops for arch-specific hibernate stuff (Sebastian Ott)
    - Disable decoding during BAR sizing only when necessary (Zoltan Kiss)
    - Delay enabling bridges until they're needed (Yinghai Lu)
    - Split Designware support into Synopsys and Exynos parts (Jingoo Han)
    - Convert class code to use dev_groups (Greg Kroah-Hartman)
    - Cleanup Designware and Exynos I/O access wrappers (Seungwon Jeon)
    - Fix bridge I/O window alignment (Bjorn Helgaas)
    - Add pci_wait_for_pending_transaction() (Casey Leedom)
    - Use devm_ioremap_resource() in Marvell driver (Tushar Behera)

* tag 'pci-v3.12-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (63 commits)
  PCI/ACPI: Fix _OSC ordering to allow PCIe hotplug use when available
  PCI: exynos: Add I/O access wrappers
  PCI: designware: Drop "addr" arg from dw_pcie_readl_rc()/dw_pcie_writel_rc()
  PCI: Remove pcie_cap_has_devctl()
  PCI: Support PCIe Capability Slot registers only for ports with slots
  PCI: Remove PCIe Capability version checks
  PCI: Allow PCIe Capability link-related register access for switches
  PCI: Add offsets of PCIe capability registers
  PCI: Tidy bitmasks and spacing of PCIe capability definitions
  PCI: Remove obsolete comment reference to pci_pcie_cap2()
  PCI: Clarify PCI_EXP_TYPE_PCI_BRIDGE comment
  PCI: Rename PCIe capability definitions to follow convention
  PCI: Warn if unsafe MPS settings detected
  PCI: Fix MPS peer-to-peer DMA comment syntax
  PCI: Disable decoding for BAR sizing only when it was actually enabled
  PCI: Add comment about needing pci_msi_off() even when CONFIG_PCI_MSI=n
  PCI: Add pcibios_pm_ops for optional arch-specific hibernate functionality
  PCI: Don't restrict MPS for slots below Root Ports
  PCI: Simplify MPS test for Downstream Port
  PCI: Remove unnecessary check for pcie_get_mps() failure
  ...
parents 40031da4 e89c3316
...@@ -18,6 +18,7 @@ Required properties: ...@@ -18,6 +18,7 @@ Required properties:
- interrupt-map-mask and interrupt-map: standard PCI properties - interrupt-map-mask and interrupt-map: standard PCI properties
to define the mapping of the PCIe interface to interrupt to define the mapping of the PCIe interface to interrupt
numbers. numbers.
- num-lanes: number of lanes to use
- reset-gpio: gpio pin number of power good signal - reset-gpio: gpio pin number of power good signal
Example: Example:
...@@ -41,6 +42,7 @@ SoC specific DT Entry: ...@@ -41,6 +42,7 @@ SoC specific DT Entry:
#interrupt-cells = <1>; #interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>; interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0x0 0 &gic 53>; interrupt-map = <0x0 0 &gic 53>;
num-lanes = <4>;
}; };
pcie@2a0000 { pcie@2a0000 {
...@@ -60,6 +62,7 @@ SoC specific DT Entry: ...@@ -60,6 +62,7 @@ SoC specific DT Entry:
#interrupt-cells = <1>; #interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>; interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0x0 0 &gic 56>; interrupt-map = <0x0 0 &gic 56>;
num-lanes = <4>;
}; };
Board specific DT Entry: Board specific DT Entry:
......
...@@ -248,6 +248,7 @@ pcie@290000 { ...@@ -248,6 +248,7 @@ pcie@290000 {
#interrupt-cells = <1>; #interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>; interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0x0 0 &gic 53>; interrupt-map = <0x0 0 &gic 53>;
num-lanes = <4>;
}; };
pcie@2a0000 { pcie@2a0000 {
...@@ -267,5 +268,6 @@ pcie@2a0000 { ...@@ -267,5 +268,6 @@ pcie@2a0000 {
#interrupt-cells = <1>; #interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>; interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0x0 0 &gic 56>; interrupt-map = <0x0 0 &gic 56>;
num-lanes = <4>;
}; };
}; };
...@@ -525,11 +525,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw) ...@@ -525,11 +525,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
* Assign resources. * Assign resources.
*/ */
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
/*
* Enable bridges
*/
pci_enable_bridges(bus);
} }
/* /*
......
...@@ -320,7 +320,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); ...@@ -320,7 +320,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
* are examined. * are examined.
*/ */
void __init pcibios_fixup_bus(struct pci_bus *bus) void pcibios_fixup_bus(struct pci_bus *bus)
{ {
#if 0 #if 0
printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number); printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
......
...@@ -319,7 +319,6 @@ static int __init mcf_pci_init(void) ...@@ -319,7 +319,6 @@ static int __init mcf_pci_init(void)
pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq); pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq);
pci_bus_size_bridges(rootbus); pci_bus_size_bridges(rootbus);
pci_bus_assign_resources(rootbus); pci_bus_assign_resources(rootbus);
pci_enable_bridges(rootbus);
return 0; return 0;
} }
......
...@@ -113,7 +113,6 @@ static void pcibios_scanbus(struct pci_controller *hose) ...@@ -113,7 +113,6 @@ static void pcibios_scanbus(struct pci_controller *hose)
if (!pci_has_flag(PCI_PROBE_ONLY)) { if (!pci_has_flag(PCI_PROBE_ONLY)) {
pci_bus_size_bridges(bus); pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
pci_enable_bridges(bus);
} }
} }
} }
......
...@@ -1674,12 +1674,8 @@ void pcibios_scan_phb(struct pci_controller *hose) ...@@ -1674,12 +1674,8 @@ void pcibios_scan_phb(struct pci_controller *hose)
/* Configure PCI Express settings */ /* Configure PCI Express settings */
if (bus && !pci_has_flag(PCI_PROBE_ONLY)) { if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
struct pci_bus *child; struct pci_bus *child;
list_for_each_entry(child, &bus->children, node) { list_for_each_entry(child, &bus->children, node)
struct pci_dev *self = child->self; pcie_bus_configure_settings(child);
if (!self)
continue;
pcie_bus_configure_settings(child, self->pcie_mpss);
}
} }
} }
......
...@@ -69,7 +69,6 @@ static void pcibios_scanbus(struct pci_channel *hose) ...@@ -69,7 +69,6 @@ static void pcibios_scanbus(struct pci_channel *hose)
pci_bus_size_bridges(bus); pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
pci_enable_bridges(bus);
} else { } else {
pci_free_resource_list(&resources); pci_free_resource_list(&resources);
} }
......
...@@ -508,13 +508,8 @@ static void fixup_read_and_payload_sizes(struct pci_controller *controller) ...@@ -508,13 +508,8 @@ static void fixup_read_and_payload_sizes(struct pci_controller *controller)
rc_dev_cap.word); rc_dev_cap.word);
/* Configure PCI Express MPS setting. */ /* Configure PCI Express MPS setting. */
list_for_each_entry(child, &root_bus->children, node) { list_for_each_entry(child, &root_bus->children, node)
struct pci_dev *self = child->self; pcie_bus_configure_settings(child);
if (!self)
continue;
pcie_bus_configure_settings(child, self->pcie_mpss);
}
/* /*
* Set the mac_config register in trio based on the MPS/MRS of the link. * Set the mac_config register in trio based on the MPS/MRS of the link.
......
...@@ -568,13 +568,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) ...@@ -568,13 +568,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
*/ */
if (bus) { if (bus) {
struct pci_bus *child; struct pci_bus *child;
list_for_each_entry(child, &bus->children, node) { list_for_each_entry(child, &bus->children, node)
struct pci_dev *self = child->self; pcie_bus_configure_settings(child);
if (!self)
continue;
pcie_bus_configure_settings(child, self->pcie_mpss);
}
} }
if (bus && node != -1) { if (bus && node != -1) {
......
...@@ -700,7 +700,7 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, ...@@ -700,7 +700,7 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed) if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
return -ENODEV; return -ENODEV;
if (start > end) if (start > end || !addr)
return -EINVAL; return -EINVAL;
mutex_lock(&pci_mmcfg_lock); mutex_lock(&pci_mmcfg_lock);
...@@ -716,11 +716,6 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, ...@@ -716,11 +716,6 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
return -EEXIST; return -EEXIST;
} }
if (!addr) {
mutex_unlock(&pci_mmcfg_lock);
return -EINVAL;
}
rc = -EBUSY; rc = -EBUSY;
cfg = pci_mmconfig_alloc(seg, start, end, addr); cfg = pci_mmconfig_alloc(seg, start, end, addr);
if (cfg == NULL) { if (cfg == NULL) {
......
...@@ -23,11 +23,11 @@ ...@@ -23,11 +23,11 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/acpi.h>
#include <linux/io.h>
#include <linux/smp.h>
#include <asm/acpi.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/pci_x86.h> #include <asm/pci_x86.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
#include <asm/io_apic.h> #include <asm/io_apic.h>
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#define PCI_FIXED_BAR_4_SIZE 0x14 #define PCI_FIXED_BAR_4_SIZE 0x14
#define PCI_FIXED_BAR_5_SIZE 0x1c #define PCI_FIXED_BAR_5_SIZE 0x1c
static int pci_soc_mode = 0; static int pci_soc_mode;
/** /**
* fixed_bar_cap - return the offset of the fixed BAR cap if found * fixed_bar_cap - return the offset of the fixed BAR cap if found
...@@ -141,7 +141,8 @@ static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn, ...@@ -141,7 +141,8 @@ static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn,
*/ */
static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg) static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
{ {
/* This is a workaround for A0 LNC bug where PCI status register does /*
* This is a workaround for A0 LNC bug where PCI status register does
* not have new CAP bit set. can not be written by SW either. * not have new CAP bit set. can not be written by SW either.
* *
* PCI header type in real LNC indicates a single function device, this * PCI header type in real LNC indicates a single function device, this
...@@ -154,7 +155,7 @@ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg) ...@@ -154,7 +155,7 @@ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
|| devfn == PCI_DEVFN(0, 0) || devfn == PCI_DEVFN(0, 0)
|| devfn == PCI_DEVFN(3, 0))) || devfn == PCI_DEVFN(3, 0)))
return 1; return 1;
return 0; /* langwell on others */ return 0; /* Langwell on others */
} }
static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
...@@ -172,7 +173,8 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -172,7 +173,8 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
{ {
int offset; int offset;
/* On MRST, there is no PCI ROM BAR, this will cause a subsequent read /*
* On MRST, there is no PCI ROM BAR, this will cause a subsequent read
* to ROM BAR return 0 then being ignored. * to ROM BAR return 0 then being ignored.
*/ */
if (where == PCI_ROM_ADDRESS) if (where == PCI_ROM_ADDRESS)
...@@ -210,7 +212,8 @@ static int mrst_pci_irq_enable(struct pci_dev *dev) ...@@ -210,7 +212,8 @@ static int mrst_pci_irq_enable(struct pci_dev *dev)
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
/* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to /*
* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
* IOAPIC RTE entries, so we just enable RTE for the device. * IOAPIC RTE entries, so we just enable RTE for the device.
*/ */
irq_attr.ioapic = mp_find_ioapic(dev->irq); irq_attr.ioapic = mp_find_ioapic(dev->irq);
...@@ -235,7 +238,7 @@ struct pci_ops pci_mrst_ops = { ...@@ -235,7 +238,7 @@ struct pci_ops pci_mrst_ops = {
*/ */
int __init pci_mrst_init(void) int __init pci_mrst_init(void)
{ {
printk(KERN_INFO "Intel MID platform detected, using MID PCI ops\n"); pr_info("Intel MID platform detected, using MID PCI ops\n");
pci_mmcfg_late_init(); pci_mmcfg_late_init();
pcibios_enable_irq = mrst_pci_irq_enable; pcibios_enable_irq = mrst_pci_irq_enable;
pci_root_ops = pci_mrst_ops; pci_root_ops = pci_mrst_ops;
...@@ -244,17 +247,21 @@ int __init pci_mrst_init(void) ...@@ -244,17 +247,21 @@ int __init pci_mrst_init(void)
return 1; return 1;
} }
/* Langwell devices are not true pci devices, they are not subject to 10 ms /*
* d3 to d0 delay required by pci spec. * Langwell devices are not true PCI devices; they are not subject to 10 ms
* d3 to d0 delay required by PCI spec.
*/ */
static void pci_d3delay_fixup(struct pci_dev *dev) static void pci_d3delay_fixup(struct pci_dev *dev)
{ {
/* PCI fixups are effectively decided compile time. If we have a dual /*
SoC/non-SoC kernel we don't want to mangle d3 on non SoC devices */ * PCI fixups are effectively decided compile time. If we have a dual
* SoC/non-SoC kernel we don't want to mangle d3 on non-SoC devices.
*/
if (!pci_soc_mode) if (!pci_soc_mode)
return; return;
/* true pci devices in lincroft should allow type 1 access, the rest /*
* are langwell fake pci devices. * True PCI devices in Lincroft should allow type 1 access, the rest
* are Langwell fake PCI devices.
*/ */
if (type1_access_ok(dev->bus->number, dev->devfn, PCI_DEVICE_ID)) if (type1_access_ok(dev->bus->number, dev->devfn, PCI_DEVICE_ID))
return; return;
......
...@@ -378,6 +378,7 @@ static int acpi_pci_root_add(struct acpi_device *device, ...@@ -378,6 +378,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
struct acpi_pci_root *root; struct acpi_pci_root *root;
u32 flags, base_flags; u32 flags, base_flags;
acpi_handle handle = device->handle; acpi_handle handle = device->handle;
bool no_aspm = false, clear_aspm = false;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root) if (!root)
...@@ -437,27 +438,6 @@ static int acpi_pci_root_add(struct acpi_device *device, ...@@ -437,27 +438,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
acpi_pci_osc_support(root, flags); acpi_pci_osc_support(root, flags);
/*
* TBD: Need PCI interface for enumeration/configuration of roots.
*/
/*
* Scan the Root Bridge
* --------------------
* Must do this prior to any attempt to bind the root device, as the
* PCI namespace does not get created until this call is made (and
* thus the root bridge's pci_dev does not exist).
*/
root->bus = pci_acpi_scan_root(root);
if (!root->bus) {
dev_err(&device->dev,
"Bus %04x:%02x not present in PCI namespace\n",
root->segment, (unsigned int)root->secondary.start);
result = -ENODEV;
goto end;
}
/* Indicate support for various _OSC capabilities. */
if (pci_ext_cfg_avail()) if (pci_ext_cfg_avail())
flags |= OSC_EXT_PCI_CONFIG_SUPPORT; flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
if (pcie_aspm_support_enabled()) { if (pcie_aspm_support_enabled()) {
...@@ -471,7 +451,7 @@ static int acpi_pci_root_add(struct acpi_device *device, ...@@ -471,7 +451,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
dev_info(&device->dev, "ACPI _OSC support " dev_info(&device->dev, "ACPI _OSC support "
"notification failed, disabling PCIe ASPM\n"); "notification failed, disabling PCIe ASPM\n");
pcie_no_aspm(); no_aspm = true;
flags = base_flags; flags = base_flags;
} }
} }
...@@ -503,7 +483,7 @@ static int acpi_pci_root_add(struct acpi_device *device, ...@@ -503,7 +483,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
* We have ASPM control, but the FADT indicates * We have ASPM control, but the FADT indicates
* that it's unsupported. Clear it. * that it's unsupported. Clear it.
*/ */
pcie_clear_aspm(root->bus); clear_aspm = true;
} }
} else { } else {
dev_info(&device->dev, dev_info(&device->dev,
...@@ -512,7 +492,14 @@ static int acpi_pci_root_add(struct acpi_device *device, ...@@ -512,7 +492,14 @@ static int acpi_pci_root_add(struct acpi_device *device,
acpi_format_exception(status), flags); acpi_format_exception(status), flags);
dev_info(&device->dev, dev_info(&device->dev,
"ACPI _OSC control for PCIe not granted, disabling ASPM\n"); "ACPI _OSC control for PCIe not granted, disabling ASPM\n");
pcie_no_aspm(); /*
* We want to disable ASPM here, but aspm_disabled
* needs to remain in its state from boot so that we
* properly handle PCIe 1.1 devices. So we set this
* flag here, to defer the action until after the ACPI
* root scan.
*/
no_aspm = true;
} }
} else { } else {
dev_info(&device->dev, dev_info(&device->dev,
...@@ -520,16 +507,40 @@ static int acpi_pci_root_add(struct acpi_device *device, ...@@ -520,16 +507,40 @@ static int acpi_pci_root_add(struct acpi_device *device,
"(_OSC support mask: 0x%02x)\n", flags); "(_OSC support mask: 0x%02x)\n", flags);
} }
/*
* TBD: Need PCI interface for enumeration/configuration of roots.
*/
/*
* Scan the Root Bridge
* --------------------
* Must do this prior to any attempt to bind the root device, as the
* PCI namespace does not get created until this call is made (and
* thus the root bridge's pci_dev does not exist).
*/
root->bus = pci_acpi_scan_root(root);
if (!root->bus) {
dev_err(&device->dev,
"Bus %04x:%02x not present in PCI namespace\n",
root->segment, (unsigned int)root->secondary.start);
result = -ENODEV;
goto end;
}
if (clear_aspm) {
dev_info(&device->dev, "Disabling ASPM (FADT indicates it is unsupported)\n");
pcie_clear_aspm(root->bus);
}
if (no_aspm)
pcie_no_aspm();
pci_acpi_add_bus_pm_notifier(device, root->bus); pci_acpi_add_bus_pm_notifier(device, root->bus);
if (device->wakeup.flags.run_wake) if (device->wakeup.flags.run_wake)
device_set_run_wake(root->bus->bridge, true); device_set_run_wake(root->bus->bridge, true);
if (system_state != SYSTEM_BOOTING) { if (system_state != SYSTEM_BOOTING) {
pcibios_resource_survey_bus(root->bus); pcibios_resource_survey_bus(root->bus);
pci_assign_unassigned_bus_resources(root->bus); pci_assign_unassigned_root_bus_resources(root->bus);
/* need to after hot-added ioapic is registered */
pci_enable_bridges(root->bus);
} }
pci_bus_add_devices(root->bus); pci_bus_add_devices(root->bus);
......
...@@ -44,7 +44,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) ...@@ -44,7 +44,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
/* Configure LTR */ /* Configure LTR */
pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cap); pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cap);
if (cap & PCI_EXP_LTR_EN) if (cap & PCI_EXP_DEVCTL2_LTR_EN)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3);
/* Configure OBFF */ /* Configure OBFF */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03);
......
...@@ -9960,8 +9960,6 @@ static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi) ...@@ -9960,8 +9960,6 @@ static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi)
static int bnx2x_do_flr(struct bnx2x *bp) static int bnx2x_do_flr(struct bnx2x *bp)
{ {
int i;
u16 status;
struct pci_dev *dev = bp->pdev; struct pci_dev *dev = bp->pdev;
if (CHIP_IS_E1x(bp)) { if (CHIP_IS_E1x(bp)) {
...@@ -9976,20 +9974,8 @@ static int bnx2x_do_flr(struct bnx2x *bp) ...@@ -9976,20 +9974,8 @@ static int bnx2x_do_flr(struct bnx2x *bp)
return -EINVAL; return -EINVAL;
} }
/* Wait for Transaction Pending bit clean */ if (!pci_wait_for_pending_transaction(dev))
for (i = 0; i < 4; i++) { dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
if (i)
msleep((1 << (i - 1)) * 100);
pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
if (!(status & PCI_EXP_DEVSTA_TRPND))
goto clear;
}
dev_err(&dev->dev,
"transaction is not cleared; proceeding with reset anyway\n");
clear:
BNX2X_DEV_INFO("Initiating FLR\n"); BNX2X_DEV_INFO("Initiating FLR\n");
bnx2x_fw_command(bp, DRV_MSG_CODE_INITIATE_FLR, 0); bnx2x_fw_command(bp, DRV_MSG_CODE_INITIATE_FLR, 0);
......
...@@ -1590,7 +1590,6 @@ lba_driver_probe(struct parisc_device *dev) ...@@ -1590,7 +1590,6 @@ lba_driver_probe(struct parisc_device *dev)
lba_dump_res(&lba_dev->hba.lmmio_space, 2); lba_dump_res(&lba_dev->hba.lmmio_space, 2);
#endif #endif
} }
pci_enable_bridges(lba_bus);
/* /*
** Once PCI register ops has walked the bus, access to config ** Once PCI register ops has walked the bus, access to config
......
...@@ -475,37 +475,33 @@ static inline int pcie_cap_version(const struct pci_dev *dev) ...@@ -475,37 +475,33 @@ static inline int pcie_cap_version(const struct pci_dev *dev)
return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS; return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
} }
static inline bool pcie_cap_has_devctl(const struct pci_dev *dev)
{
return true;
}
static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev) static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
{ {
int type = pci_pcie_type(dev); int type = pci_pcie_type(dev);
return pcie_cap_version(dev) > 1 || return type == PCI_EXP_TYPE_ENDPOINT ||
type == PCI_EXP_TYPE_LEG_END ||
type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_ROOT_PORT ||
type == PCI_EXP_TYPE_ENDPOINT || type == PCI_EXP_TYPE_UPSTREAM ||
type == PCI_EXP_TYPE_LEG_END; type == PCI_EXP_TYPE_DOWNSTREAM ||
type == PCI_EXP_TYPE_PCI_BRIDGE ||
type == PCI_EXP_TYPE_PCIE_BRIDGE;
} }
static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev) static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
{ {
int type = pci_pcie_type(dev); int type = pci_pcie_type(dev);
return pcie_cap_version(dev) > 1 || return (type == PCI_EXP_TYPE_ROOT_PORT ||
type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_DOWNSTREAM) &&
(type == PCI_EXP_TYPE_DOWNSTREAM && pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT;
pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT);
} }
static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev) static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev)
{ {
int type = pci_pcie_type(dev); int type = pci_pcie_type(dev);
return pcie_cap_version(dev) > 1 || return type == PCI_EXP_TYPE_ROOT_PORT ||
type == PCI_EXP_TYPE_ROOT_PORT ||
type == PCI_EXP_TYPE_RC_EC; type == PCI_EXP_TYPE_RC_EC;
} }
...@@ -520,7 +516,7 @@ static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos) ...@@ -520,7 +516,7 @@ static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
case PCI_EXP_DEVCAP: case PCI_EXP_DEVCAP:
case PCI_EXP_DEVCTL: case PCI_EXP_DEVCTL:
case PCI_EXP_DEVSTA: case PCI_EXP_DEVSTA:
return pcie_cap_has_devctl(dev); return true;
case PCI_EXP_LNKCAP: case PCI_EXP_LNKCAP:
case PCI_EXP_LNKCTL: case PCI_EXP_LNKCTL:
case PCI_EXP_LNKSTA: case PCI_EXP_LNKSTA:
......
...@@ -216,24 +216,6 @@ void pci_bus_add_devices(const struct pci_bus *bus) ...@@ -216,24 +216,6 @@ void pci_bus_add_devices(const struct pci_bus *bus)
} }
} }
void pci_enable_bridges(struct pci_bus *bus)
{
struct pci_dev *dev;
int retval;
list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->subordinate) {
if (!pci_is_enabled(dev)) {
retval = pci_enable_device(dev);
if (retval)
dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval);
pci_set_master(dev);
}
pci_enable_bridges(dev->subordinate);
}
}
}
/** pci_walk_bus - walk devices on/under bus, calling callback. /** pci_walk_bus - walk devices on/under bus, calling callback.
* @top bus whose devices should be walked * @top bus whose devices should be walked
* @cb callback to be called for each device found * @cb callback to be called for each device found
...@@ -301,4 +283,3 @@ EXPORT_SYMBOL(pci_bus_put); ...@@ -301,4 +283,3 @@ EXPORT_SYMBOL(pci_bus_put);
EXPORT_SYMBOL(pci_bus_alloc_resource); EXPORT_SYMBOL(pci_bus_alloc_resource);
EXPORT_SYMBOL_GPL(pci_bus_add_device); EXPORT_SYMBOL_GPL(pci_bus_add_device);
EXPORT_SYMBOL(pci_bus_add_devices); EXPORT_SYMBOL(pci_bus_add_devices);
EXPORT_SYMBOL(pci_enable_bridges);
...@@ -4,6 +4,7 @@ menu "PCI host controller drivers" ...@@ -4,6 +4,7 @@ menu "PCI host controller drivers"
config PCI_MVEBU config PCI_MVEBU
bool "Marvell EBU PCIe controller" bool "Marvell EBU PCIe controller"
depends on ARCH_MVEBU || ARCH_KIRKWOOD depends on ARCH_MVEBU || ARCH_KIRKWOOD
depends on OF
config PCIE_DW config PCIE_DW
bool bool
......
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCIE_DW) += pcie-designware.o obj-$(CONFIG_PCIE_DW) += pcie-designware.o
obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
This diff is collapsed.
...@@ -725,9 +725,9 @@ mvebu_pcie_map_registers(struct platform_device *pdev, ...@@ -725,9 +725,9 @@ mvebu_pcie_map_registers(struct platform_device *pdev,
ret = of_address_to_resource(np, 0, &regs); ret = of_address_to_resource(np, 0, &regs);
if (ret) if (ret)
return NULL; return ERR_PTR(ret);
return devm_request_and_ioremap(&pdev->dev, &regs); return devm_ioremap_resource(&pdev->dev, &regs);
} }
static int __init mvebu_pcie_probe(struct platform_device *pdev) static int __init mvebu_pcie_probe(struct platform_device *pdev)
...@@ -817,9 +817,10 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) ...@@ -817,9 +817,10 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
continue; continue;
port->base = mvebu_pcie_map_registers(pdev, child, port); port->base = mvebu_pcie_map_registers(pdev, child, port);
if (!port->base) { if (IS_ERR(port->base)) {
dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
port->port, port->lane); port->port, port->lane);
port->base = NULL;
continue; continue;
} }
......
This diff is collapsed.
/*
* Synopsys Designware PCIe host controller driver
*
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Jingoo Han <jg1.han@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
struct pcie_port_info {
u32 cfg0_size;
u32 cfg1_size;
u32 io_size;
u32 mem_size;
phys_addr_t io_bus_addr;
phys_addr_t mem_bus_addr;
};
struct pcie_port {
struct device *dev;
u8 root_bus_nr;
void __iomem *dbi_base;
u64 cfg0_base;
void __iomem *va_cfg0_base;
u64 cfg1_base;
void __iomem *va_cfg1_base;
u64 io_base;
u64 mem_base;
spinlock_t conf_lock;
struct resource cfg;
struct resource io;
struct resource mem;
struct pcie_port_info config;
int irq;
u32 lanes;
struct pcie_host_ops *ops;
};
struct pcie_host_ops {
void (*readl_rc)(struct pcie_port *pp,
void __iomem *dbi_base, u32 *val);
void (*writel_rc)(struct pcie_port *pp,
u32 val, void __iomem *dbi_base);
int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val);
int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val);
int (*link_up)(struct pcie_port *pp);
void (*host_init)(struct pcie_port *pp);
};
extern unsigned long global_io_offset;
int cfg_read(void __iomem *addr, int where, int size, u32 *val);
int cfg_write(void __iomem *addr, int where, int size, u32 val);
int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, u32 val);
int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, u32 *val);
int dw_pcie_link_up(struct pcie_port *pp);
void dw_pcie_setup_rc(struct pcie_port *pp);
int dw_pcie_host_init(struct pcie_port *pp);
int dw_pcie_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys);
int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
...@@ -572,7 +572,6 @@ static void __ref enable_slot(struct acpiphp_slot *slot) ...@@ -572,7 +572,6 @@ static void __ref enable_slot(struct acpiphp_slot *slot)
acpiphp_sanitize_bus(bus); acpiphp_sanitize_bus(bus);
acpiphp_set_hpp_values(bus); acpiphp_set_hpp_values(bus);
acpiphp_set_acpi_region(slot); acpiphp_set_acpi_region(slot);
pci_enable_bridges(bus);
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
/* Assume that newly added devices are powered on already. */ /* Assume that newly added devices are powered on already. */
......
...@@ -155,6 +155,7 @@ void pciehp_green_led_off(struct slot *slot); ...@@ -155,6 +155,7 @@ void pciehp_green_led_off(struct slot *slot);
void pciehp_green_led_blink(struct slot *slot); void pciehp_green_led_blink(struct slot *slot);
int pciehp_check_link_status(struct controller *ctrl); int pciehp_check_link_status(struct controller *ctrl);
void pciehp_release_ctrl(struct controller *ctrl); void pciehp_release_ctrl(struct controller *ctrl);
int pciehp_reset_slot(struct slot *slot, int probe);
static inline const char *slot_name(struct slot *slot) static inline const char *slot_name(struct slot *slot)
{ {
......
...@@ -69,6 +69,7 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); ...@@ -69,6 +69,7 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
static int get_attention_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value);
static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value);
static int get_adapter_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
static int reset_slot (struct hotplug_slot *slot, int probe);
/** /**
* release_slot - free up the memory used by a slot * release_slot - free up the memory used by a slot
...@@ -111,6 +112,7 @@ static int init_slot(struct controller *ctrl) ...@@ -111,6 +112,7 @@ static int init_slot(struct controller *ctrl)
ops->disable_slot = disable_slot; ops->disable_slot = disable_slot;
ops->get_power_status = get_power_status; ops->get_power_status = get_power_status;
ops->get_adapter_status = get_adapter_status; ops->get_adapter_status = get_adapter_status;
ops->reset_slot = reset_slot;
if (MRL_SENS(ctrl)) if (MRL_SENS(ctrl))
ops->get_latch_status = get_latch_status; ops->get_latch_status = get_latch_status;
if (ATTN_LED(ctrl)) { if (ATTN_LED(ctrl)) {
...@@ -223,6 +225,16 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -223,6 +225,16 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
return pciehp_get_adapter_status(slot, value); return pciehp_get_adapter_status(slot, value);
} }
static int reset_slot(struct hotplug_slot *hotplug_slot, int probe)
{
struct slot *slot = hotplug_slot->private;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot));
return pciehp_reset_slot(slot, probe);
}
static int pciehp_probe(struct pcie_device *dev) static int pciehp_probe(struct pcie_device *dev)
{ {
int rc; int rc;
......
...@@ -749,6 +749,37 @@ static void pcie_disable_notification(struct controller *ctrl) ...@@ -749,6 +749,37 @@ static void pcie_disable_notification(struct controller *ctrl)
ctrl_warn(ctrl, "Cannot disable software notification\n"); ctrl_warn(ctrl, "Cannot disable software notification\n");
} }
/*
* 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
* events after.
*/
int pciehp_reset_slot(struct slot *slot, int probe)
{
struct controller *ctrl = slot->ctrl;
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);
}
pci_reset_bridge_secondary_bus(ctrl->pcie->port);
if (HP_SUPR_RM(ctrl)) {
pciehp_writew(ctrl, 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);
}
return 0;
}
int pcie_init_notification(struct controller *ctrl) int pcie_init_notification(struct controller *ctrl)
{ {
if (pciehp_request_irq(ctrl)) if (pciehp_request_irq(ctrl))
......
...@@ -160,9 +160,8 @@ void pci_configure_slot(struct pci_dev *dev) ...@@ -160,9 +160,8 @@ void pci_configure_slot(struct pci_dev *dev)
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
return; return;
if (dev->bus && dev->bus->self) if (dev->bus)
pcie_bus_configure_settings(dev->bus, pcie_bus_configure_settings(dev->bus);
dev->bus->self->pcie_mpss);
memset(&hpp, 0, sizeof(hpp)); memset(&hpp, 0, sizeof(hpp));
ret = pci_get_hp_params(dev, &hpp); ret = pci_get_hp_params(dev, &hpp);
......
...@@ -286,7 +286,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) ...@@ -286,7 +286,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial))) (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
return -EINVAL; return -EINVAL;
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn);
pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &offset); pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &offset);
pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &stride); pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &stride);
if (!offset || (nr_virtfn > 1 && !stride)) if (!offset || (nr_virtfn > 1 && !stride))
...@@ -324,7 +323,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) ...@@ -324,7 +323,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
if (!pdev->is_physfn) { if (!pdev->is_physfn) {
pci_dev_put(pdev); pci_dev_put(pdev);
return -ENODEV; return -ENOSYS;
} }
rc = sysfs_create_link(&dev->dev.kobj, rc = sysfs_create_link(&dev->dev.kobj,
...@@ -334,6 +333,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) ...@@ -334,6 +333,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
return rc; return rc;
} }
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn);
iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE; iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
pci_cfg_access_lock(dev); pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
...@@ -368,6 +368,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) ...@@ -368,6 +368,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
pci_cfg_access_lock(dev); pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0);
ssleep(1); ssleep(1);
pci_cfg_access_unlock(dev); pci_cfg_access_unlock(dev);
...@@ -401,6 +402,7 @@ static void sriov_disable(struct pci_dev *dev) ...@@ -401,6 +402,7 @@ static void sriov_disable(struct pci_dev *dev)
sysfs_remove_link(&dev->dev.kobj, "dep_link"); sysfs_remove_link(&dev->dev.kobj, "dep_link");
iov->num_VFs = 0; iov->num_VFs = 0;
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0);
} }
static int sriov_init(struct pci_dev *dev, int pos) static int sriov_init(struct pci_dev *dev, int pos)
...@@ -662,7 +664,7 @@ int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) ...@@ -662,7 +664,7 @@ int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
might_sleep(); might_sleep();
if (!dev->is_physfn) if (!dev->is_physfn)
return -ENODEV; return -ENOSYS;
return sriov_enable(dev, nr_virtfn); return sriov_enable(dev, nr_virtfn);
} }
...@@ -722,7 +724,7 @@ EXPORT_SYMBOL_GPL(pci_num_vf); ...@@ -722,7 +724,7 @@ EXPORT_SYMBOL_GPL(pci_num_vf);
* @dev: the PCI device * @dev: the PCI device
* *
* Returns number of VFs belonging to this device that are assigned to a guest. * Returns number of VFs belonging to this device that are assigned to a guest.
* If device is not a physical function returns -ENODEV. * If device is not a physical function returns 0.
*/ */
int pci_vfs_assigned(struct pci_dev *dev) int pci_vfs_assigned(struct pci_dev *dev)
{ {
...@@ -767,12 +769,15 @@ EXPORT_SYMBOL_GPL(pci_vfs_assigned); ...@@ -767,12 +769,15 @@ EXPORT_SYMBOL_GPL(pci_vfs_assigned);
* device's mutex held. * device's mutex held.
* *
* Returns 0 if PF is an SRIOV-capable device and * Returns 0 if PF is an SRIOV-capable device and
* value of numvfs valid. If not a PF with VFS, return -EINVAL; * value of numvfs valid. If not a PF return -ENOSYS;
* if numvfs is invalid return -EINVAL;
* if VFs already enabled, return -EBUSY. * if VFs already enabled, return -EBUSY.
*/ */
int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs) int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
{ {
if (!dev->is_physfn || (numvfs > dev->sriov->total_VFs)) if (!dev->is_physfn)
return -ENOSYS;
if (numvfs > dev->sriov->total_VFs)
return -EINVAL; return -EINVAL;
/* Shouldn't change if VFs already enabled */ /* Shouldn't change if VFs already enabled */
...@@ -786,17 +791,17 @@ int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs) ...@@ -786,17 +791,17 @@ int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs); EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs);
/** /**
* pci_sriov_get_totalvfs -- get total VFs supported on this devic3 * pci_sriov_get_totalvfs -- get total VFs supported on this device
* @dev: the PCI PF device * @dev: the PCI PF device
* *
* For a PCIe device with SRIOV support, return the PCIe * For a PCIe device with SRIOV support, return the PCIe
* SRIOV capability value of TotalVFs or the value of driver_max_VFs * SRIOV capability value of TotalVFs or the value of driver_max_VFs
* if the driver reduced it. Otherwise, -EINVAL. * if the driver reduced it. Otherwise 0.
*/ */
int pci_sriov_get_totalvfs(struct pci_dev *dev) int pci_sriov_get_totalvfs(struct pci_dev *dev)
{ {
if (!dev->is_physfn) if (!dev->is_physfn)
return -EINVAL; return 0;
if (dev->sriov->driver_max_VFs) if (dev->sriov->driver_max_VFs)
return dev->sriov->driver_max_VFs; return dev->sriov->driver_max_VFs;
......
...@@ -763,6 +763,13 @@ static int pci_pm_resume(struct device *dev) ...@@ -763,6 +763,13 @@ static int pci_pm_resume(struct device *dev)
#ifdef CONFIG_HIBERNATE_CALLBACKS #ifdef CONFIG_HIBERNATE_CALLBACKS
/*
* pcibios_pm_ops - provide arch-specific hooks when a PCI device is doing
* a hibernate transition
*/
struct dev_pm_ops __weak pcibios_pm_ops;
static int pci_pm_freeze(struct device *dev) static int pci_pm_freeze(struct device *dev)
{ {
struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_dev *pci_dev = to_pci_dev(dev);
...@@ -786,6 +793,9 @@ static int pci_pm_freeze(struct device *dev) ...@@ -786,6 +793,9 @@ static int pci_pm_freeze(struct device *dev)
return error; return error;
} }
if (pcibios_pm_ops.freeze)
return pcibios_pm_ops.freeze(dev);
return 0; return 0;
} }
...@@ -811,6 +821,9 @@ static int pci_pm_freeze_noirq(struct device *dev) ...@@ -811,6 +821,9 @@ static int pci_pm_freeze_noirq(struct device *dev)
pci_pm_set_unknown_state(pci_dev); pci_pm_set_unknown_state(pci_dev);
if (pcibios_pm_ops.freeze_noirq)
return pcibios_pm_ops.freeze_noirq(dev);
return 0; return 0;
} }
...@@ -820,6 +833,12 @@ static int pci_pm_thaw_noirq(struct device *dev) ...@@ -820,6 +833,12 @@ static int pci_pm_thaw_noirq(struct device *dev)
struct device_driver *drv = dev->driver; struct device_driver *drv = dev->driver;
int error = 0; int error = 0;
if (pcibios_pm_ops.thaw_noirq) {
error = pcibios_pm_ops.thaw_noirq(dev);
if (error)
return error;
}
if (pci_has_legacy_pm_support(pci_dev)) if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_resume_early(dev); return pci_legacy_resume_early(dev);
...@@ -837,6 +856,12 @@ static int pci_pm_thaw(struct device *dev) ...@@ -837,6 +856,12 @@ static int pci_pm_thaw(struct device *dev)
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int error = 0; int error = 0;
if (pcibios_pm_ops.thaw) {
error = pcibios_pm_ops.thaw(dev);
if (error)
return error;
}
if (pci_has_legacy_pm_support(pci_dev)) if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_resume(dev); return pci_legacy_resume(dev);
...@@ -878,6 +903,9 @@ static int pci_pm_poweroff(struct device *dev) ...@@ -878,6 +903,9 @@ static int pci_pm_poweroff(struct device *dev)
Fixup: Fixup:
pci_fixup_device(pci_fixup_suspend, pci_dev); pci_fixup_device(pci_fixup_suspend, pci_dev);
if (pcibios_pm_ops.poweroff)
return pcibios_pm_ops.poweroff(dev);
return 0; return 0;
} }
...@@ -911,6 +939,9 @@ static int pci_pm_poweroff_noirq(struct device *dev) ...@@ -911,6 +939,9 @@ static int pci_pm_poweroff_noirq(struct device *dev)
if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
pci_write_config_word(pci_dev, PCI_COMMAND, 0); pci_write_config_word(pci_dev, PCI_COMMAND, 0);
if (pcibios_pm_ops.poweroff_noirq)
return pcibios_pm_ops.poweroff_noirq(dev);
return 0; return 0;
} }
...@@ -920,6 +951,12 @@ static int pci_pm_restore_noirq(struct device *dev) ...@@ -920,6 +951,12 @@ static int pci_pm_restore_noirq(struct device *dev)
struct device_driver *drv = dev->driver; struct device_driver *drv = dev->driver;
int error = 0; int error = 0;
if (pcibios_pm_ops.restore_noirq) {
error = pcibios_pm_ops.restore_noirq(dev);
if (error)
return error;
}
pci_pm_default_resume_early(pci_dev); pci_pm_default_resume_early(pci_dev);
if (pci_has_legacy_pm_support(pci_dev)) if (pci_has_legacy_pm_support(pci_dev))
...@@ -937,6 +974,12 @@ static int pci_pm_restore(struct device *dev) ...@@ -937,6 +974,12 @@ static int pci_pm_restore(struct device *dev)
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int error = 0; int error = 0;
if (pcibios_pm_ops.restore) {
error = pcibios_pm_ops.restore(dev);
if (error)
return error;
}
/* /*
* This is necessary for the hibernation error path in which restore is * This is necessary for the hibernation error path in which restore is
* called without restoring the standard config registers of the device. * called without restoring the standard config registers of the device.
......
...@@ -131,19 +131,19 @@ static ssize_t pci_bus_show_cpuaffinity(struct device *dev, ...@@ -131,19 +131,19 @@ static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
return ret; return ret;
} }
static inline ssize_t pci_bus_show_cpumaskaffinity(struct device *dev, static ssize_t cpuaffinity_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr, char *buf)
char *buf)
{ {
return pci_bus_show_cpuaffinity(dev, 0, attr, buf); return pci_bus_show_cpuaffinity(dev, 0, attr, buf);
} }
static DEVICE_ATTR_RO(cpuaffinity);
static inline ssize_t pci_bus_show_cpulistaffinity(struct device *dev, static ssize_t cpulistaffinity_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr, char *buf)
char *buf)
{ {
return pci_bus_show_cpuaffinity(dev, 1, attr, buf); return pci_bus_show_cpuaffinity(dev, 1, attr, buf);
} }
static DEVICE_ATTR_RO(cpulistaffinity);
/* show resources */ /* show resources */
static ssize_t static ssize_t
...@@ -379,6 +379,7 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr, ...@@ -379,6 +379,7 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
} }
return count; return count;
} }
static DEVICE_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store);
#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
static ssize_t d3cold_allowed_store(struct device *dev, static ssize_t d3cold_allowed_store(struct device *dev,
...@@ -514,11 +515,20 @@ struct device_attribute pci_dev_attrs[] = { ...@@ -514,11 +515,20 @@ struct device_attribute pci_dev_attrs[] = {
__ATTR_NULL, __ATTR_NULL,
}; };
struct device_attribute pcibus_dev_attrs[] = { static struct attribute *pcibus_attrs[] = {
__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store), &dev_attr_rescan.attr,
__ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL), &dev_attr_cpuaffinity.attr,
__ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL), &dev_attr_cpulistaffinity.attr,
__ATTR_NULL, NULL,
};
static const struct attribute_group pcibus_group = {
.attrs = pcibus_attrs,
};
const struct attribute_group *pcibus_groups[] = {
&pcibus_group,
NULL,
}; };
static ssize_t static ssize_t
......
This diff is collapsed.
...@@ -151,7 +151,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev) ...@@ -151,7 +151,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
} }
extern struct device_attribute pci_dev_attrs[]; extern struct device_attribute pci_dev_attrs[];
extern struct device_attribute pcibus_dev_attrs[]; extern const struct attribute_group *pcibus_groups[];
extern struct device_type pci_dev_type; extern struct device_type pci_dev_type;
extern struct bus_attribute pci_bus_attrs[]; extern struct bus_attribute pci_bus_attrs[];
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# PCI Express Port Bus Configuration # PCI Express Port Bus Configuration
# #
config PCIEPORTBUS config PCIEPORTBUS
bool "PCI Express support" bool "PCI Express Port Bus support"
depends on PCI depends on PCI
help help
This automatically enables PCI Express Port Bus support. Users can This automatically enables PCI Express Port Bus support. Users can
......
...@@ -352,7 +352,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) ...@@ -352,7 +352,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32); pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
aer_do_secondary_bus_reset(dev); pci_reset_bridge_secondary_bus(dev);
dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n"); dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n");
/* Clear Root Error Status */ /* Clear Root Error Status */
......
...@@ -106,7 +106,6 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig, ...@@ -106,7 +106,6 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
} }
extern struct bus_type pcie_port_bus_type; extern struct bus_type pcie_port_bus_type;
void aer_do_secondary_bus_reset(struct pci_dev *dev);
int aer_init(struct pcie_device *dev); int aer_init(struct pcie_device *dev);
void aer_isr(struct work_struct *work); void aer_isr(struct work_struct *work);
void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
......
...@@ -366,39 +366,6 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, ...@@ -366,39 +366,6 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
return result_data.result; return result_data.result;
} }
/**
* aer_do_secondary_bus_reset - perform secondary bus reset
* @dev: pointer to bridge's pci_dev data structure
*
* Invoked when performing link reset at Root Port or Downstream Port.
*/
void aer_do_secondary_bus_reset(struct pci_dev *dev)
{
u16 p2p_ctrl;
/* Assert Secondary Bus Reset */
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &p2p_ctrl);
p2p_ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
/*
* we should send hot reset message for 2ms to allow it time to
* propagate to all downstream ports
*/
msleep(2);
/* De-assert Secondary Bus Reset */
p2p_ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
/*
* System software must wait for at least 100ms from the end
* of a reset of one or more device before it is permitted
* to issue Configuration Requests to those devices.
*/
msleep(200);
}
/** /**
* default_reset_link - default reset function * default_reset_link - default reset function
* @dev: pointer to pci_dev data structure * @dev: pointer to pci_dev data structure
...@@ -408,7 +375,7 @@ void aer_do_secondary_bus_reset(struct pci_dev *dev) ...@@ -408,7 +375,7 @@ void aer_do_secondary_bus_reset(struct pci_dev *dev)
*/ */
static pci_ers_result_t default_reset_link(struct pci_dev *dev) static pci_ers_result_t default_reset_link(struct pci_dev *dev)
{ {
aer_do_secondary_bus_reset(dev); pci_reset_bridge_secondary_bus(dev);
dev_printk(KERN_DEBUG, &dev->dev, "downstream link has been reset\n"); dev_printk(KERN_DEBUG, &dev->dev, "downstream link has been reset\n");
return PCI_ERS_RESULT_RECOVERED; return PCI_ERS_RESULT_RECOVERED;
} }
......
...@@ -96,7 +96,7 @@ static void release_pcibus_dev(struct device *dev) ...@@ -96,7 +96,7 @@ static void release_pcibus_dev(struct device *dev)
static struct class pcibus_class = { static struct class pcibus_class = {
.name = "pci_bus", .name = "pci_bus",
.dev_release = &release_pcibus_dev, .dev_release = &release_pcibus_dev,
.dev_attrs = pcibus_dev_attrs, .dev_groups = pcibus_groups,
}; };
static int __init pcibus_class_init(void) static int __init pcibus_class_init(void)
...@@ -156,6 +156,8 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar) ...@@ -156,6 +156,8 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
return flags; return flags;
} }
#define PCI_COMMAND_DECODE_ENABLE (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)
/** /**
* pci_read_base - read a PCI BAR * pci_read_base - read a PCI BAR
* @dev: the PCI device * @dev: the PCI device
...@@ -178,8 +180,10 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -178,8 +180,10 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
/* No printks while decoding is disabled! */ /* No printks while decoding is disabled! */
if (!dev->mmio_always_on) { if (!dev->mmio_always_on) {
pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
if (orig_cmd & PCI_COMMAND_DECODE_ENABLE) {
pci_write_config_word(dev, PCI_COMMAND, pci_write_config_word(dev, PCI_COMMAND,
orig_cmd & ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO)); orig_cmd & ~PCI_COMMAND_DECODE_ENABLE);
}
} }
res->name = pci_name(dev); res->name = pci_name(dev);
...@@ -293,7 +297,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -293,7 +297,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
fail: fail:
res->flags = 0; res->flags = 0;
out: out:
if (!dev->mmio_always_on) if (!dev->mmio_always_on &&
(orig_cmd & PCI_COMMAND_DECODE_ENABLE))
pci_write_config_word(dev, PCI_COMMAND, orig_cmd); pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
if (bar_too_big) if (bar_too_big)
...@@ -1491,24 +1496,23 @@ static int pcie_find_smpss(struct pci_dev *dev, void *data) ...@@ -1491,24 +1496,23 @@ static int pcie_find_smpss(struct pci_dev *dev, void *data)
if (!pci_is_pcie(dev)) if (!pci_is_pcie(dev))
return 0; return 0;
/* For PCIE hotplug enabled slots not connected directly to a /*
* PCI-E root port, there can be problems when hotplugging * We don't have a way to change MPS settings on devices that have
* devices. This is due to the possibility of hotplugging a * drivers attached. A hot-added device might support only the minimum
* device into the fabric with a smaller MPS that the devices * MPS setting (MPS=128). Therefore, if the fabric contains a bridge
* currently running have configured. Modifying the MPS on the * where devices may be hot-added, we limit the fabric MPS to 128 so
* running devices could cause a fatal bus error due to an * hot-added devices will work correctly.
* incoming frame being larger than the newly configured MPS. *
* To work around this, the MPS for the entire fabric must be * However, if we hot-add a device to a slot directly below a Root
* set to the minimum size. Any devices hotplugged into this * Port, it's impossible for there to be other existing devices below
* fabric will have the minimum MPS set. If the PCI hotplug * the port. We don't limit the MPS in this case because we can
* slot is directly connected to the root port and there are not * reconfigure MPS on both the Root Port and the hot-added device,
* other devices on the fabric (which seems to be the most * and there are no other devices involved.
* common case), then this is not an issue and MPS discovery *
* will occur as normal. * Note that this PCIE_BUS_SAFE path assumes no peer-to-peer DMA.
*/ */
if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) || if (dev->is_hotplug_bridge &&
(dev->bus->self && pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
pci_pcie_type(dev->bus->self) != PCI_EXP_TYPE_ROOT_PORT)))
*smpss = 0; *smpss = 0;
if (*smpss > dev->pcie_mpss) if (*smpss > dev->pcie_mpss)
...@@ -1583,6 +1587,22 @@ static void pcie_write_mrrs(struct pci_dev *dev) ...@@ -1583,6 +1587,22 @@ static void pcie_write_mrrs(struct pci_dev *dev)
"with pci=pcie_bus_safe.\n"); "with pci=pcie_bus_safe.\n");
} }
static void pcie_bus_detect_mps(struct pci_dev *dev)
{
struct pci_dev *bridge = dev->bus->self;
int mps, p_mps;
if (!bridge)
return;
mps = pcie_get_mps(dev);
p_mps = pcie_get_mps(bridge);
if (mps != p_mps)
dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
mps, pci_name(bridge), p_mps);
}
static int pcie_bus_configure_set(struct pci_dev *dev, void *data) static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
{ {
int mps, orig_mps; int mps, orig_mps;
...@@ -1590,13 +1610,18 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data) ...@@ -1590,13 +1610,18 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
if (!pci_is_pcie(dev)) if (!pci_is_pcie(dev))
return 0; return 0;
if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
pcie_bus_detect_mps(dev);
return 0;
}
mps = 128 << *(u8 *)data; mps = 128 << *(u8 *)data;
orig_mps = pcie_get_mps(dev); orig_mps = pcie_get_mps(dev);
pcie_write_mps(dev, mps); pcie_write_mps(dev, mps);
pcie_write_mrrs(dev); pcie_write_mrrs(dev);
dev_info(&dev->dev, "PCI-E Max Payload Size set to %4d/%4d (was %4d), " dev_info(&dev->dev, "Max Payload Size set to %4d/%4d (was %4d), "
"Max Read Rq %4d\n", pcie_get_mps(dev), 128 << dev->pcie_mpss, "Max Read Rq %4d\n", pcie_get_mps(dev), 128 << dev->pcie_mpss,
orig_mps, pcie_get_readrq(dev)); orig_mps, pcie_get_readrq(dev));
...@@ -1607,25 +1632,25 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data) ...@@ -1607,25 +1632,25 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
* parents then children fashion. If this changes, then this code will not * parents then children fashion. If this changes, then this code will not
* work as designed. * work as designed.
*/ */
void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss) void pcie_bus_configure_settings(struct pci_bus *bus)
{ {
u8 smpss; u8 smpss;
if (!pci_is_pcie(bus->self)) if (!bus->self)
return; return;
if (pcie_bus_config == PCIE_BUS_TUNE_OFF) if (!pci_is_pcie(bus->self))
return; return;
/* FIXME - Peer to peer DMA is possible, though the endpoint would need /* FIXME - Peer to peer DMA is possible, though the endpoint would need
* to be aware to the MPS of the destination. To work around this, * to be aware of the MPS of the destination. To work around this,
* simply force the MPS of the entire system to the smallest possible. * simply force the MPS of the entire system to the smallest possible.
*/ */
if (pcie_bus_config == PCIE_BUS_PEER2PEER) if (pcie_bus_config == PCIE_BUS_PEER2PEER)
smpss = 0; smpss = 0;
if (pcie_bus_config == PCIE_BUS_SAFE) { if (pcie_bus_config == PCIE_BUS_SAFE) {
smpss = mpss; smpss = bus->self->pcie_mpss;
pcie_find_smpss(bus->self, &smpss); pcie_find_smpss(bus->self, &smpss);
pci_walk_bus(bus, pcie_find_smpss, &smpss); pci_walk_bus(bus, pcie_find_smpss, &smpss);
...@@ -1979,7 +2004,6 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus) ...@@ -1979,7 +2004,6 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
max = pci_scan_child_bus(bus); max = pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus); pci_assign_unassigned_bus_resources(bus);
pci_enable_bridges(bus);
pci_bus_add_devices(bus); pci_bus_add_devices(bus);
return max; return max;
......
...@@ -3126,9 +3126,6 @@ static int reset_intel_generic_dev(struct pci_dev *dev, int probe) ...@@ -3126,9 +3126,6 @@ static int reset_intel_generic_dev(struct pci_dev *dev, int probe)
static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
{ {
int i;
u16 status;
/* /*
* http://www.intel.com/content/dam/doc/datasheet/82599-10-gbe-controller-datasheet.pdf * http://www.intel.com/content/dam/doc/datasheet/82599-10-gbe-controller-datasheet.pdf
* *
...@@ -3140,20 +3137,9 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) ...@@ -3140,20 +3137,9 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
if (probe) if (probe)
return 0; return 0;
/* Wait for Transaction Pending bit clean */ if (!pci_wait_for_pending_transaction(dev))
for (i = 0; i < 4; i++) { dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
if (i)
msleep((1 << (i - 1)) * 100);
pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
if (!(status & PCI_EXP_DEVSTA_TRPND))
goto clear;
}
dev_err(&dev->dev, "transaction is not cleared; "
"proceeding with reset anyway\n");
clear:
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
msleep(100); msleep(100);
...@@ -3208,6 +3194,83 @@ static int reset_ivb_igd(struct pci_dev *dev, int probe) ...@@ -3208,6 +3194,83 @@ static int reset_ivb_igd(struct pci_dev *dev, int probe)
return 0; return 0;
} }
/*
* Device-specific reset method for Chelsio T4-based adapters.
*/
static int reset_chelsio_generic_dev(struct pci_dev *dev, int probe)
{
u16 old_command;
u16 msix_flags;
/*
* If this isn't a Chelsio T4-based device, return -ENOTTY indicating
* that we have no device-specific reset method.
*/
if ((dev->device & 0xf000) != 0x4000)
return -ENOTTY;
/*
* If this is the "probe" phase, return 0 indicating that we can
* reset this device.
*/
if (probe)
return 0;
/*
* T4 can wedge if there are DMAs in flight within the chip and Bus
* Master has been disabled. We need to have it on till the Function
* Level Reset completes. (BUS_MASTER is disabled in
* pci_reset_function()).
*/
pci_read_config_word(dev, PCI_COMMAND, &old_command);
pci_write_config_word(dev, PCI_COMMAND,
old_command | PCI_COMMAND_MASTER);
/*
* Perform the actual device function reset, saving and restoring
* configuration information around the reset.
*/
pci_save_state(dev);
/*
* T4 also suffers a Head-Of-Line blocking problem if MSI-X interrupts
* are disabled when an MSI-X interrupt message needs to be delivered.
* So we briefly re-enable MSI-X interrupts for the duration of the
* FLR. The pci_restore_state() below will restore the original
* MSI-X state.
*/
pci_read_config_word(dev, dev->msix_cap+PCI_MSIX_FLAGS, &msix_flags);
if ((msix_flags & PCI_MSIX_FLAGS_ENABLE) == 0)
pci_write_config_word(dev, dev->msix_cap+PCI_MSIX_FLAGS,
msix_flags |
PCI_MSIX_FLAGS_ENABLE |
PCI_MSIX_FLAGS_MASKALL);
/*
* Start of pcie_flr() code sequence. This reset code is a copy of
* the guts of pcie_flr() because that's not an exported function.
*/
if (!pci_wait_for_pending_transaction(dev))
dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
msleep(100);
/*
* End of pcie_flr() code sequence.
*/
/*
* Restore the configuration information (BAR values, etc.) including
* the original PCI Configuration Space Command word, and return
* success.
*/
pci_restore_state(dev);
pci_write_config_word(dev, PCI_COMMAND, old_command);
return 0;
}
#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed #define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed
#define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156 #define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156
#define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166 #define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166
...@@ -3221,6 +3284,8 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { ...@@ -3221,6 +3284,8 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
reset_ivb_igd }, reset_ivb_igd },
{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
reset_intel_generic_dev }, reset_intel_generic_dev },
{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
reset_chelsio_generic_dev },
{ 0 } { 0 }
}; };
...@@ -3295,11 +3360,61 @@ struct pci_dev *pci_get_dma_source(struct pci_dev *dev) ...@@ -3295,11 +3360,61 @@ struct pci_dev *pci_get_dma_source(struct pci_dev *dev)
return pci_dev_get(dev); return pci_dev_get(dev);
} }
/*
* AMD has indicated that the devices below do not support peer-to-peer
* in any system where they are found in the southbridge with an AMD
* IOMMU in the system. Multifunction devices that do not support
* peer-to-peer between functions can claim to support a subset of ACS.
* Such devices effectively enable request redirect (RR) and completion
* redirect (CR) since all transactions are redirected to the upstream
* root complex.
*
* http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94086
* http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94102
* http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/99402
*
* 1002:4385 SBx00 SMBus Controller
* 1002:439c SB7x0/SB8x0/SB9x0 IDE Controller
* 1002:4383 SBx00 Azalia (Intel HDA)
* 1002:439d SB7x0/SB8x0/SB9x0 LPC host controller
* 1002:4384 SBx00 PCI to PCI Bridge
* 1002:4399 SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
*/
static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
{
#ifdef CONFIG_ACPI
struct acpi_table_header *header = NULL;
acpi_status status;
/* Targeting multifunction devices on the SB (appears on root bus) */
if (!dev->multifunction || !pci_is_root_bus(dev->bus))
return -ENODEV;
/* The IVRS table describes the AMD IOMMU */
status = acpi_get_table("IVRS", 0, &header);
if (ACPI_FAILURE(status))
return -ENODEV;
/* Filter out flags not applicable to multifunction */
acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT);
return acs_flags & ~(PCI_ACS_RR | PCI_ACS_CR) ? 0 : 1;
#else
return -ENODEV;
#endif
}
static const struct pci_dev_acs_enabled { static const struct pci_dev_acs_enabled {
u16 vendor; u16 vendor;
u16 device; u16 device;
int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags); int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags);
} pci_dev_acs_enabled[] = { } pci_dev_acs_enabled[] = {
{ PCI_VENDOR_ID_ATI, 0x4385, pci_quirk_amd_sb_acs },
{ PCI_VENDOR_ID_ATI, 0x439c, pci_quirk_amd_sb_acs },
{ PCI_VENDOR_ID_ATI, 0x4383, pci_quirk_amd_sb_acs },
{ 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 },
{ 0 } { 0 }
}; };
......
...@@ -814,14 +814,14 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, ...@@ -814,14 +814,14 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
{ {
struct pci_dev *dev; struct pci_dev *dev;
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
unsigned long size = 0, size0 = 0, size1 = 0; resource_size_t size = 0, size0 = 0, size1 = 0;
resource_size_t children_add_size = 0; resource_size_t children_add_size = 0;
resource_size_t min_align, io_align, align; resource_size_t min_align, align;
if (!b_res) if (!b_res)
return; return;
io_align = min_align = window_alignment(bus, IORESOURCE_IO); min_align = window_alignment(bus, IORESOURCE_IO);
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
int i; int i;
...@@ -848,9 +848,6 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, ...@@ -848,9 +848,6 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
} }
} }
if (min_align > io_align)
min_align = io_align;
size0 = calculate_iosize(size, min_size, size1, size0 = calculate_iosize(size, min_size, size1,
resource_size(b_res), min_align); resource_size(b_res), min_align);
if (children_add_size > add_size) if (children_add_size > add_size)
...@@ -874,8 +871,9 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, ...@@ -874,8 +871,9 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
add_to_list(realloc_head, bus->self, b_res, size1-size0, add_to_list(realloc_head, bus->self, b_res, size1-size0,
min_align); min_align);
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
"%pR to %pR add_size %lx\n", b_res, "%pR to %pR add_size %llx\n", b_res,
&bus->busn_res, size1-size0); &bus->busn_res,
(unsigned long long)size1-size0);
} }
} }
...@@ -905,6 +903,8 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns, ...@@ -905,6 +903,8 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
* pbus_size_mem() - size the memory window of a given bus * pbus_size_mem() - size the memory window of a given bus
* *
* @bus : the bus * @bus : the bus
* @mask: mask the resource flag, then compare it with type
* @type: the type of free resource from bridge
* @min_size : the minimum memory window that must to be allocated * @min_size : the minimum memory window that must to be allocated
* @add_size : additional optional memory window * @add_size : additional optional memory window
* @realloc_head : track the additional memory window on this list * @realloc_head : track the additional memory window on this list
...@@ -1364,39 +1364,21 @@ static void pci_bus_dump_resources(struct pci_bus *bus) ...@@ -1364,39 +1364,21 @@ static void pci_bus_dump_resources(struct pci_bus *bus)
} }
} }
static int __init pci_bus_get_depth(struct pci_bus *bus) static int pci_bus_get_depth(struct pci_bus *bus)
{ {
int depth = 0; int depth = 0;
struct pci_dev *dev; struct pci_bus *child_bus;
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(child_bus, &bus->children, node){
int ret; int ret;
struct pci_bus *b = dev->subordinate;
if (!b)
continue;
ret = pci_bus_get_depth(b); ret = pci_bus_get_depth(child_bus);
if (ret + 1 > depth) if (ret + 1 > depth)
depth = ret + 1; depth = ret + 1;
} }
return depth; return depth;
} }
static int __init pci_get_max_depth(void)
{
int depth = 0;
struct pci_bus *bus;
list_for_each_entry(bus, &pci_root_buses, node) {
int ret;
ret = pci_bus_get_depth(bus);
if (ret > depth)
depth = ret;
}
return depth;
}
/* /*
* -1: undefined, will auto detect later * -1: undefined, will auto detect later
...@@ -1413,7 +1395,7 @@ enum enable_type { ...@@ -1413,7 +1395,7 @@ enum enable_type {
auto_enabled, auto_enabled,
}; };
static enum enable_type pci_realloc_enable __initdata = undefined; static enum enable_type pci_realloc_enable = undefined;
void __init pci_realloc_get_opt(char *str) void __init pci_realloc_get_opt(char *str)
{ {
if (!strncmp(str, "off", 3)) if (!strncmp(str, "off", 3))
...@@ -1421,45 +1403,64 @@ void __init pci_realloc_get_opt(char *str) ...@@ -1421,45 +1403,64 @@ void __init pci_realloc_get_opt(char *str)
else if (!strncmp(str, "on", 2)) else if (!strncmp(str, "on", 2))
pci_realloc_enable = user_enabled; pci_realloc_enable = user_enabled;
} }
static bool __init pci_realloc_enabled(void) static bool pci_realloc_enabled(enum enable_type enable)
{ {
return pci_realloc_enable >= user_enabled; return enable >= user_enabled;
} }
static void __init pci_realloc_detect(void)
{
#if defined(CONFIG_PCI_IOV) && defined(CONFIG_PCI_REALLOC_ENABLE_AUTO) #if defined(CONFIG_PCI_IOV) && defined(CONFIG_PCI_REALLOC_ENABLE_AUTO)
struct pci_dev *dev = NULL; static int iov_resources_unassigned(struct pci_dev *dev, void *data)
{
if (pci_realloc_enable != undefined)
return;
for_each_pci_dev(dev) {
int i; int i;
bool *unassigned = data;
for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) { for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) {
struct resource *r = &dev->resource[i]; struct resource *r = &dev->resource[i];
struct pci_bus_region region;
/* Not assigned, or rejected by kernel ? */ /* Not assigned or rejected by kernel? */
if (r->flags && !r->start) { if (!r->flags)
pci_realloc_enable = auto_enabled; continue;
return; pcibios_resource_to_bus(dev, &region, r);
} if (!region.start) {
*unassigned = true;
return 1; /* return early from pci_walk_bus() */
} }
} }
#endif
return 0;
} }
static enum enable_type pci_realloc_detect(struct pci_bus *bus,
enum enable_type enable_local)
{
bool unassigned = false;
if (enable_local != undefined)
return enable_local;
pci_walk_bus(bus, iov_resources_unassigned, &unassigned);
if (unassigned)
return auto_enabled;
return enable_local;
}
#else
static enum enable_type pci_realloc_detect(struct pci_bus *bus,
enum enable_type enable_local)
{
return enable_local;
}
#endif
/* /*
* first try will not touch pci bridge res * first try will not touch pci bridge res
* second and later try will clear small leaf bridge res * second and later try will clear small leaf bridge res
* will stop till to the max deepth if can not find good one * will stop till to the max deepth if can not find good one
*/ */
void __init void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
pci_assign_unassigned_resources(void)
{ {
struct pci_bus *bus;
LIST_HEAD(realloc_head); /* list of resources that LIST_HEAD(realloc_head); /* list of resources that
want additional resources */ want additional resources */
struct list_head *add_list = NULL; struct list_head *add_list = NULL;
...@@ -1470,14 +1471,16 @@ pci_assign_unassigned_resources(void) ...@@ -1470,14 +1471,16 @@ pci_assign_unassigned_resources(void)
unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
IORESOURCE_PREFETCH; IORESOURCE_PREFETCH;
int pci_try_num = 1; int pci_try_num = 1;
enum enable_type enable_local;
/* don't realloc if asked to do so */ /* don't realloc if asked to do so */
pci_realloc_detect(); enable_local = pci_realloc_detect(bus, pci_realloc_enable);
if (pci_realloc_enabled()) { if (pci_realloc_enabled(enable_local)) {
int max_depth = pci_get_max_depth(); int max_depth = pci_bus_get_depth(bus);
pci_try_num = max_depth + 1; pci_try_num = max_depth + 1;
printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", dev_printk(KERN_DEBUG, &bus->dev,
"max bus depth: %d pci_try_num: %d\n",
max_depth, pci_try_num); max_depth, pci_try_num);
} }
...@@ -1490,11 +1493,9 @@ pci_assign_unassigned_resources(void) ...@@ -1490,11 +1493,9 @@ pci_assign_unassigned_resources(void)
add_list = &realloc_head; add_list = &realloc_head;
/* Depth first, calculate sizes and alignments of all /* Depth first, calculate sizes and alignments of all
subordinate buses. */ subordinate buses. */
list_for_each_entry(bus, &pci_root_buses, node)
__pci_bus_size_bridges(bus, add_list); __pci_bus_size_bridges(bus, add_list);
/* Depth last, allocate resources and update the hardware. */ /* Depth last, allocate resources and update the hardware. */
list_for_each_entry(bus, &pci_root_buses, node)
__pci_bus_assign_resources(bus, add_list, &fail_head); __pci_bus_assign_resources(bus, add_list, &fail_head);
if (add_list) if (add_list)
BUG_ON(!list_empty(add_list)); BUG_ON(!list_empty(add_list));
...@@ -1502,20 +1503,20 @@ pci_assign_unassigned_resources(void) ...@@ -1502,20 +1503,20 @@ pci_assign_unassigned_resources(void)
/* any device complain? */ /* any device complain? */
if (list_empty(&fail_head)) if (list_empty(&fail_head))
goto enable_and_dump; goto dump;
if (tried_times >= pci_try_num) { if (tried_times >= pci_try_num) {
if (pci_realloc_enable == undefined) if (enable_local == undefined)
printk(KERN_INFO "Some PCI device resources are unassigned, try booting with pci=realloc\n"); dev_info(&bus->dev, "Some PCI device resources are unassigned, try booting with pci=realloc\n");
else if (pci_realloc_enable == auto_enabled) else if (enable_local == auto_enabled)
printk(KERN_INFO "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n"); dev_info(&bus->dev, "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n");
free_list(&fail_head); free_list(&fail_head);
goto enable_and_dump; goto dump;
} }
printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", dev_printk(KERN_DEBUG, &bus->dev,
tried_times + 1); "No. %d try to assign unassigned res\n", tried_times + 1);
/* third times and later will not check if it is leaf */ /* third times and later will not check if it is leaf */
if ((tried_times + 1) > 2) if ((tried_times + 1) > 2)
...@@ -1525,12 +1526,11 @@ pci_assign_unassigned_resources(void) ...@@ -1525,12 +1526,11 @@ pci_assign_unassigned_resources(void)
* Try to release leaf bridge's resources that doesn't fit resource of * Try to release leaf bridge's resources that doesn't fit resource of
* child device under that bridge * child device under that bridge
*/ */
list_for_each_entry(fail_res, &fail_head, list) { list_for_each_entry(fail_res, &fail_head, list)
bus = fail_res->dev->bus; pci_bus_release_bridge_resources(fail_res->dev->bus,
pci_bus_release_bridge_resources(bus,
fail_res->flags & type_mask, fail_res->flags & type_mask,
rel_type); rel_type);
}
/* restore size and flags */ /* restore size and flags */
list_for_each_entry(fail_res, &fail_head, list) { list_for_each_entry(fail_res, &fail_head, list) {
struct resource *res = fail_res->res; struct resource *res = fail_res->res;
...@@ -1545,16 +1545,19 @@ pci_assign_unassigned_resources(void) ...@@ -1545,16 +1545,19 @@ pci_assign_unassigned_resources(void)
goto again; goto again;
enable_and_dump: dump:
/* Depth last, update the hardware. */
list_for_each_entry(bus, &pci_root_buses, node)
pci_enable_bridges(bus);
/* dump the resource on buses */ /* dump the resource on buses */
list_for_each_entry(bus, &pci_root_buses, node)
pci_bus_dump_resources(bus); pci_bus_dump_resources(bus);
} }
void __init pci_assign_unassigned_resources(void)
{
struct pci_bus *root_bus;
list_for_each_entry(root_bus, &pci_root_buses, node)
pci_assign_unassigned_root_bus_resources(root_bus);
}
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
{ {
struct pci_bus *parent = bridge->subordinate; struct pci_bus *parent = bridge->subordinate;
...@@ -1589,13 +1592,11 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) ...@@ -1589,13 +1592,11 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
* Try to release leaf bridge's resources that doesn't fit resource of * Try to release leaf bridge's resources that doesn't fit resource of
* child device under that bridge * child device under that bridge
*/ */
list_for_each_entry(fail_res, &fail_head, list) { list_for_each_entry(fail_res, &fail_head, list)
struct pci_bus *bus = fail_res->dev->bus; pci_bus_release_bridge_resources(fail_res->dev->bus,
unsigned long flags = fail_res->flags; fail_res->flags & type_mask,
pci_bus_release_bridge_resources(bus, flags & type_mask,
whole_subtree); whole_subtree);
}
/* restore size and flags */ /* restore size and flags */
list_for_each_entry(fail_res, &fail_head, list) { list_for_each_entry(fail_res, &fail_head, list) {
struct resource *res = fail_res->res; struct resource *res = fail_res->res;
...@@ -1615,7 +1616,6 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) ...@@ -1615,7 +1616,6 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
if (retval) if (retval)
dev_err(&bridge->dev, "Error reenabling bridge (%d)\n", retval); dev_err(&bridge->dev, "Error reenabling bridge (%d)\n", retval);
pci_set_master(bridge); pci_set_master(bridge);
pci_enable_bridges(parent);
} }
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
......
...@@ -91,7 +91,6 @@ int __ref cb_alloc(struct pcmcia_socket *s) ...@@ -91,7 +91,6 @@ int __ref cb_alloc(struct pcmcia_socket *s)
if (s->tune_bridge) if (s->tune_bridge)
s->tune_bridge(s, bus); s->tune_bridge(s, bus);
pci_enable_bridges(bus);
pci_bus_add_devices(bus); pci_bus_add_devices(bus);
return 0; return 0;
......
...@@ -675,7 +675,7 @@ struct pci_driver { ...@@ -675,7 +675,7 @@ struct pci_driver {
/* these external functions are only available when PCI support is enabled */ /* these external functions are only available when PCI support is enabled */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss); void pcie_bus_configure_settings(struct pci_bus *bus);
enum pcie_bus_config_types { enum pcie_bus_config_types {
PCIE_BUS_TUNE_OFF, PCIE_BUS_TUNE_OFF,
...@@ -914,6 +914,7 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev); ...@@ -914,6 +914,7 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev);
void pci_msi_off(struct pci_dev *dev); void pci_msi_off(struct pci_dev *dev);
int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size); int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask); int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
int pci_wait_for_pending_transaction(struct pci_dev *dev);
int pcix_get_max_mmrbc(struct pci_dev *dev); int pcix_get_max_mmrbc(struct pci_dev *dev);
int pcix_get_mmrbc(struct pci_dev *dev); int pcix_get_mmrbc(struct pci_dev *dev);
int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc); int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
...@@ -924,6 +925,11 @@ int pcie_set_mps(struct pci_dev *dev, int mps); ...@@ -924,6 +925,11 @@ int pcie_set_mps(struct pci_dev *dev, int mps);
int __pci_reset_function(struct pci_dev *dev); int __pci_reset_function(struct pci_dev *dev);
int __pci_reset_function_locked(struct pci_dev *dev); int __pci_reset_function_locked(struct pci_dev *dev);
int pci_reset_function(struct pci_dev *dev); int pci_reset_function(struct pci_dev *dev);
int pci_probe_reset_slot(struct pci_slot *slot);
int pci_reset_slot(struct pci_slot *slot);
int pci_probe_reset_bus(struct pci_bus *bus);
int pci_reset_bus(struct pci_bus *bus);
void pci_reset_bridge_secondary_bus(struct pci_dev *dev);
void pci_update_resource(struct pci_dev *dev, int resno); void pci_update_resource(struct pci_dev *dev, int resno);
int __must_check pci_assign_resource(struct pci_dev *dev, int i); int __must_check pci_assign_resource(struct pci_dev *dev, int i);
int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align); int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
...@@ -1003,6 +1009,7 @@ int pci_claim_resource(struct pci_dev *, int); ...@@ -1003,6 +1009,7 @@ int pci_claim_resource(struct pci_dev *, int);
void pci_assign_unassigned_resources(void); void pci_assign_unassigned_resources(void);
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge); void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
void pci_assign_unassigned_bus_resources(struct pci_bus *bus); void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus);
void pdev_enable_device(struct pci_dev *); void pdev_enable_device(struct pci_dev *);
int pci_enable_resources(struct pci_dev *, int mask); int pci_enable_resources(struct pci_dev *, int mask);
void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
...@@ -1043,7 +1050,6 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus, ...@@ -1043,7 +1050,6 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
resource_size_t, resource_size_t,
resource_size_t), resource_size_t),
void *alignf_data); void *alignf_data);
void pci_enable_bridges(struct pci_bus *bus);
/* Proper probing supporting hot-pluggable devices */ /* Proper probing supporting hot-pluggable devices */
int __must_check __pci_register_driver(struct pci_driver *, struct module *, int __must_check __pci_register_driver(struct pci_driver *, struct module *,
...@@ -1648,6 +1654,10 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, ...@@ -1648,6 +1654,10 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev,
int pcibios_add_device(struct pci_dev *dev); int pcibios_add_device(struct pci_dev *dev);
void pcibios_release_device(struct pci_dev *dev); void pcibios_release_device(struct pci_dev *dev);
#ifdef CONFIG_HIBERNATE_CALLBACKS
extern struct dev_pm_ops pcibios_pm_ops;
#endif
#ifdef CONFIG_PCI_MMCONFIG #ifdef CONFIG_PCI_MMCONFIG
void __init pci_mmcfg_early_init(void); void __init pci_mmcfg_early_init(void);
void __init pci_mmcfg_late_init(void); void __init pci_mmcfg_late_init(void);
......
...@@ -63,6 +63,9 @@ enum pcie_link_width { ...@@ -63,6 +63,9 @@ enum pcie_link_width {
* @get_adapter_status: Called to get see if an adapter is present in the slot or not. * @get_adapter_status: Called to get see if an adapter is present in the slot or not.
* If this field is NULL, the value passed in the struct hotplug_slot_info * If this field is NULL, the value passed in the struct hotplug_slot_info
* will be used when this value is requested by a user. * will be used when this value is requested by a user.
* @reset_slot: Optional interface to allow override of a bus reset for the
* slot for cases where a secondary bus reset can result in spurious
* hotplug events or where a slot can be reset independent of the bus.
* *
* The table of function pointers that is passed to the hotplug pci core by a * The table of function pointers that is passed to the hotplug pci core by a
* hotplug pci driver. These functions are called by the hotplug pci core when * hotplug pci driver. These functions are called by the hotplug pci core when
...@@ -80,6 +83,7 @@ struct hotplug_slot_ops { ...@@ -80,6 +83,7 @@ struct hotplug_slot_ops {
int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); int (*get_attention_status) (struct hotplug_slot *slot, u8 *value);
int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); int (*get_latch_status) (struct hotplug_slot *slot, u8 *value);
int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value);
int (*reset_slot) (struct hotplug_slot *slot, int probe);
}; };
/** /**
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment