提交 a9238741 编写于 作者: L 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
  ...
...@@ -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 @@ ...@@ -248,6 +248,7 @@
#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 @@ ...@@ -267,5 +268,6 @@
#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
if (!pci_soc_mode) * SoC/non-SoC kernel we don't want to mangle d3 on non-SoC devices.
return; */
/* true pci devices in lincroft should allow type 1 access, the rest if (!pci_soc_mode)
* are langwell fake pci devices. return;
/*
* 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
/*
* PCIe host controller driver for Samsung EXYNOS SoCs
*
* 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.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/resource.h>
#include <linux/signal.h>
#include <linux/types.h>
#include "pcie-designware.h"
#define to_exynos_pcie(x) container_of(x, struct exynos_pcie, pp)
struct exynos_pcie {
void __iomem *elbi_base;
void __iomem *phy_base;
void __iomem *block_base;
int reset_gpio;
struct clk *clk;
struct clk *bus_clk;
struct pcie_port pp;
};
/* PCIe ELBI registers */
#define PCIE_IRQ_PULSE 0x000
#define IRQ_INTA_ASSERT (0x1 << 0)
#define IRQ_INTB_ASSERT (0x1 << 2)
#define IRQ_INTC_ASSERT (0x1 << 4)
#define IRQ_INTD_ASSERT (0x1 << 6)
#define PCIE_IRQ_LEVEL 0x004
#define PCIE_IRQ_SPECIAL 0x008
#define PCIE_IRQ_EN_PULSE 0x00c
#define PCIE_IRQ_EN_LEVEL 0x010
#define PCIE_IRQ_EN_SPECIAL 0x014
#define PCIE_PWR_RESET 0x018
#define PCIE_CORE_RESET 0x01c
#define PCIE_CORE_RESET_ENABLE (0x1 << 0)
#define PCIE_STICKY_RESET 0x020
#define PCIE_NONSTICKY_RESET 0x024
#define PCIE_APP_INIT_RESET 0x028
#define PCIE_APP_LTSSM_ENABLE 0x02c
#define PCIE_ELBI_RDLH_LINKUP 0x064
#define PCIE_ELBI_LTSSM_ENABLE 0x1
#define PCIE_ELBI_SLV_AWMISC 0x11c
#define PCIE_ELBI_SLV_ARMISC 0x120
#define PCIE_ELBI_SLV_DBI_ENABLE (0x1 << 21)
/* PCIe Purple registers */
#define PCIE_PHY_GLOBAL_RESET 0x000
#define PCIE_PHY_COMMON_RESET 0x004
#define PCIE_PHY_CMN_REG 0x008
#define PCIE_PHY_MAC_RESET 0x00c
#define PCIE_PHY_PLL_LOCKED 0x010
#define PCIE_PHY_TRSVREG_RESET 0x020
#define PCIE_PHY_TRSV_RESET 0x024
/* PCIe PHY registers */
#define PCIE_PHY_IMPEDANCE 0x004
#define PCIE_PHY_PLL_DIV_0 0x008
#define PCIE_PHY_PLL_BIAS 0x00c
#define PCIE_PHY_DCC_FEEDBACK 0x014
#define PCIE_PHY_PLL_DIV_1 0x05c
#define PCIE_PHY_TRSV0_EMP_LVL 0x084
#define PCIE_PHY_TRSV0_DRV_LVL 0x088
#define PCIE_PHY_TRSV0_RXCDR 0x0ac
#define PCIE_PHY_TRSV0_LVCC 0x0dc
#define PCIE_PHY_TRSV1_EMP_LVL 0x144
#define PCIE_PHY_TRSV1_RXCDR 0x16c
#define PCIE_PHY_TRSV1_LVCC 0x19c
#define PCIE_PHY_TRSV2_EMP_LVL 0x204
#define PCIE_PHY_TRSV2_RXCDR 0x22c
#define PCIE_PHY_TRSV2_LVCC 0x25c
#define PCIE_PHY_TRSV3_EMP_LVL 0x2c4
#define PCIE_PHY_TRSV3_RXCDR 0x2ec
#define PCIE_PHY_TRSV3_LVCC 0x31c
static inline void exynos_elb_writel(struct exynos_pcie *pcie, u32 val, u32 reg)
{
writel(val, pcie->elbi_base + reg);
}
static inline u32 exynos_elb_readl(struct exynos_pcie *pcie, u32 reg)
{
return readl(pcie->elbi_base + reg);
}
static inline void exynos_phy_writel(struct exynos_pcie *pcie, u32 val, u32 reg)
{
writel(val, pcie->phy_base + reg);
}
static inline u32 exynos_phy_readl(struct exynos_pcie *pcie, u32 reg)
{
return readl(pcie->phy_base + reg);
}
static inline void exynos_blk_writel(struct exynos_pcie *pcie, u32 val, u32 reg)
{
writel(val, pcie->block_base + reg);
}
static inline u32 exynos_blk_readl(struct exynos_pcie *pcie, u32 reg)
{
return readl(pcie->block_base + reg);
}
static void exynos_pcie_sideband_dbi_w_mode(struct pcie_port *pp, bool on)
{
u32 val;
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
if (on) {
val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_AWMISC);
val |= PCIE_ELBI_SLV_DBI_ENABLE;
exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_AWMISC);
} else {
val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_AWMISC);
val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_AWMISC);
}
}
static void exynos_pcie_sideband_dbi_r_mode(struct pcie_port *pp, bool on)
{
u32 val;
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
if (on) {
val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_ARMISC);
val |= PCIE_ELBI_SLV_DBI_ENABLE;
exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_ARMISC);
} else {
val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_ARMISC);
val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_ARMISC);
}
}
static void exynos_pcie_assert_core_reset(struct pcie_port *pp)
{
u32 val;
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET);
val &= ~PCIE_CORE_RESET_ENABLE;
exynos_elb_writel(exynos_pcie, val, PCIE_CORE_RESET);
exynos_elb_writel(exynos_pcie, 0, PCIE_PWR_RESET);
exynos_elb_writel(exynos_pcie, 0, PCIE_STICKY_RESET);
exynos_elb_writel(exynos_pcie, 0, PCIE_NONSTICKY_RESET);
}
static void exynos_pcie_deassert_core_reset(struct pcie_port *pp)
{
u32 val;
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET);
val |= PCIE_CORE_RESET_ENABLE;
exynos_elb_writel(exynos_pcie, val, PCIE_CORE_RESET);
exynos_elb_writel(exynos_pcie, 1, PCIE_STICKY_RESET);
exynos_elb_writel(exynos_pcie, 1, PCIE_NONSTICKY_RESET);
exynos_elb_writel(exynos_pcie, 1, PCIE_APP_INIT_RESET);
exynos_elb_writel(exynos_pcie, 0, PCIE_APP_INIT_RESET);
exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_MAC_RESET);
}
static void exynos_pcie_assert_phy_reset(struct pcie_port *pp)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_MAC_RESET);
exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_GLOBAL_RESET);
}
static void exynos_pcie_deassert_phy_reset(struct pcie_port *pp)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_GLOBAL_RESET);
exynos_elb_writel(exynos_pcie, 1, PCIE_PWR_RESET);
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_CMN_REG);
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSVREG_RESET);
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET);
}
static void exynos_pcie_init_phy(struct pcie_port *pp)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
/* DCC feedback control off */
exynos_phy_writel(exynos_pcie, 0x29, PCIE_PHY_DCC_FEEDBACK);
/* set TX/RX impedance */
exynos_phy_writel(exynos_pcie, 0xd5, PCIE_PHY_IMPEDANCE);
/* set 50Mhz PHY clock */
exynos_phy_writel(exynos_pcie, 0x14, PCIE_PHY_PLL_DIV_0);
exynos_phy_writel(exynos_pcie, 0x12, PCIE_PHY_PLL_DIV_1);
/* set TX Differential output for lane 0 */
exynos_phy_writel(exynos_pcie, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
/* set TX Pre-emphasis Level Control for lane 0 to minimum */
exynos_phy_writel(exynos_pcie, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
/* set RX clock and data recovery bandwidth */
exynos_phy_writel(exynos_pcie, 0xe7, PCIE_PHY_PLL_BIAS);
exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV0_RXCDR);
exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV1_RXCDR);
exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV2_RXCDR);
exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV3_RXCDR);
/* change TX Pre-emphasis Level Control for lanes */
exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
/* set LVCC */
exynos_phy_writel(exynos_pcie, 0x20, PCIE_PHY_TRSV0_LVCC);
exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV1_LVCC);
exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV2_LVCC);
exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV3_LVCC);
}
static void exynos_pcie_assert_reset(struct pcie_port *pp)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
if (exynos_pcie->reset_gpio >= 0)
devm_gpio_request_one(pp->dev, exynos_pcie->reset_gpio,
GPIOF_OUT_INIT_HIGH, "RESET");
return;
}
static int exynos_pcie_establish_link(struct pcie_port *pp)
{
u32 val;
int count = 0;
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
if (dw_pcie_link_up(pp)) {
dev_err(pp->dev, "Link already up\n");
return 0;
}
/* assert reset signals */
exynos_pcie_assert_core_reset(pp);
exynos_pcie_assert_phy_reset(pp);
/* de-assert phy reset */
exynos_pcie_deassert_phy_reset(pp);
/* initialize phy */
exynos_pcie_init_phy(pp);
/* pulse for common reset */
exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_COMMON_RESET);
udelay(500);
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
/* de-assert core reset */
exynos_pcie_deassert_core_reset(pp);
/* setup root complex */
dw_pcie_setup_rc(pp);
/* assert reset signal */
exynos_pcie_assert_reset(pp);
/* assert LTSSM enable */
exynos_elb_writel(exynos_pcie, PCIE_ELBI_LTSSM_ENABLE,
PCIE_APP_LTSSM_ENABLE);
/* check if the link is up or not */
while (!dw_pcie_link_up(pp)) {
mdelay(100);
count++;
if (count == 10) {
while (exynos_phy_readl(exynos_pcie,
PCIE_PHY_PLL_LOCKED) == 0) {
val = exynos_blk_readl(exynos_pcie,
PCIE_PHY_PLL_LOCKED);
dev_info(pp->dev, "PLL Locked: 0x%x\n", val);
}
dev_err(pp->dev, "PCIe Link Fail\n");
return -EINVAL;
}
}
dev_info(pp->dev, "Link up\n");
return 0;
}
static void exynos_pcie_clear_irq_pulse(struct pcie_port *pp)
{
u32 val;
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE);
exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE);
return;
}
static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp)
{
u32 val;
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
/* enable INTX interrupt */
val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT |
IRQ_INTC_ASSERT | IRQ_INTD_ASSERT,
exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE);
return;
}
static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
{
struct pcie_port *pp = arg;
exynos_pcie_clear_irq_pulse(pp);
return IRQ_HANDLED;
}
static void exynos_pcie_enable_interrupts(struct pcie_port *pp)
{
exynos_pcie_enable_irq_pulse(pp);
return;
}
static inline void exynos_pcie_readl_rc(struct pcie_port *pp,
void __iomem *dbi_base, u32 *val)
{
exynos_pcie_sideband_dbi_r_mode(pp, true);
*val = readl(dbi_base);
exynos_pcie_sideband_dbi_r_mode(pp, false);
return;
}
static inline void exynos_pcie_writel_rc(struct pcie_port *pp,
u32 val, void __iomem *dbi_base)
{
exynos_pcie_sideband_dbi_w_mode(pp, true);
writel(val, dbi_base);
exynos_pcie_sideband_dbi_w_mode(pp, false);
return;
}
static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
u32 *val)
{
int ret;
exynos_pcie_sideband_dbi_r_mode(pp, true);
ret = cfg_read(pp->dbi_base + (where & ~0x3), where, size, val);
exynos_pcie_sideband_dbi_r_mode(pp, false);
return ret;
}
static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
u32 val)
{
int ret;
exynos_pcie_sideband_dbi_w_mode(pp, true);
ret = cfg_write(pp->dbi_base + (where & ~0x3), where, size, val);
exynos_pcie_sideband_dbi_w_mode(pp, false);
return ret;
}
static int exynos_pcie_link_up(struct pcie_port *pp)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
u32 val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_RDLH_LINKUP);
if (val == PCIE_ELBI_LTSSM_ENABLE)
return 1;
return 0;
}
static void exynos_pcie_host_init(struct pcie_port *pp)
{
exynos_pcie_establish_link(pp);
exynos_pcie_enable_interrupts(pp);
}
static struct pcie_host_ops exynos_pcie_host_ops = {
.readl_rc = exynos_pcie_readl_rc,
.writel_rc = exynos_pcie_writel_rc,
.rd_own_conf = exynos_pcie_rd_own_conf,
.wr_own_conf = exynos_pcie_wr_own_conf,
.link_up = exynos_pcie_link_up,
.host_init = exynos_pcie_host_init,
};
static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)
{
int ret;
pp->irq = platform_get_irq(pdev, 1);
if (!pp->irq) {
dev_err(&pdev->dev, "failed to get irq\n");
return -ENODEV;
}
ret = devm_request_irq(&pdev->dev, pp->irq, exynos_pcie_irq_handler,
IRQF_SHARED, "exynos-pcie", pp);
if (ret) {
dev_err(&pdev->dev, "failed to request irq\n");
return ret;
}
pp->root_bus_nr = -1;
pp->ops = &exynos_pcie_host_ops;
spin_lock_init(&pp->conf_lock);
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(&pdev->dev, "failed to initialize host\n");
return ret;
}
return 0;
}
static int __init exynos_pcie_probe(struct platform_device *pdev)
{
struct exynos_pcie *exynos_pcie;
struct pcie_port *pp;
struct device_node *np = pdev->dev.of_node;
struct resource *elbi_base;
struct resource *phy_base;
struct resource *block_base;
int ret;
exynos_pcie = devm_kzalloc(&pdev->dev, sizeof(*exynos_pcie),
GFP_KERNEL);
if (!exynos_pcie) {
dev_err(&pdev->dev, "no memory for exynos pcie\n");
return -ENOMEM;
}
pp = &exynos_pcie->pp;
pp->dev = &pdev->dev;
exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
exynos_pcie->clk = devm_clk_get(&pdev->dev, "pcie");
if (IS_ERR(exynos_pcie->clk)) {
dev_err(&pdev->dev, "Failed to get pcie rc clock\n");
return PTR_ERR(exynos_pcie->clk);
}
ret = clk_prepare_enable(exynos_pcie->clk);
if (ret)
return ret;
exynos_pcie->bus_clk = devm_clk_get(&pdev->dev, "pcie_bus");
if (IS_ERR(exynos_pcie->bus_clk)) {
dev_err(&pdev->dev, "Failed to get pcie bus clock\n");
ret = PTR_ERR(exynos_pcie->bus_clk);
goto fail_clk;
}
ret = clk_prepare_enable(exynos_pcie->bus_clk);
if (ret)
goto fail_clk;
elbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
exynos_pcie->elbi_base = devm_ioremap_resource(&pdev->dev, elbi_base);
if (IS_ERR(exynos_pcie->elbi_base))
return PTR_ERR(exynos_pcie->elbi_base);
phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 1);
exynos_pcie->phy_base = devm_ioremap_resource(&pdev->dev, phy_base);
if (IS_ERR(exynos_pcie->phy_base))
return PTR_ERR(exynos_pcie->phy_base);
block_base = platform_get_resource(pdev, IORESOURCE_MEM, 2);
exynos_pcie->block_base = devm_ioremap_resource(&pdev->dev, block_base);
if (IS_ERR(exynos_pcie->block_base))
return PTR_ERR(exynos_pcie->block_base);
ret = add_pcie_port(pp, pdev);
if (ret < 0)
goto fail_bus_clk;
platform_set_drvdata(pdev, exynos_pcie);
return 0;
fail_bus_clk:
clk_disable_unprepare(exynos_pcie->bus_clk);
fail_clk:
clk_disable_unprepare(exynos_pcie->clk);
return ret;
}
static int __exit exynos_pcie_remove(struct platform_device *pdev)
{
struct exynos_pcie *exynos_pcie = platform_get_drvdata(pdev);
clk_disable_unprepare(exynos_pcie->bus_clk);
clk_disable_unprepare(exynos_pcie->clk);
return 0;
}
static const struct of_device_id exynos_pcie_of_match[] = {
{ .compatible = "samsung,exynos5440-pcie", },
{},
};
MODULE_DEVICE_TABLE(of, exynos_pcie_of_match);
static struct platform_driver exynos_pcie_driver = {
.remove = __exit_p(exynos_pcie_remove),
.driver = {
.name = "exynos-pcie",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(exynos_pcie_of_match),
},
};
/* Exynos PCIe driver does not allow module unload */
static int __init pcie_init(void)
{
return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe);
}
subsys_initcall(pcie_init);
MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
MODULE_DESCRIPTION("Samsung PCIe host controller driver");
MODULE_LICENSE("GPL v2");
...@@ -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;
} }
......
此差异已折叠。
/*
* 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
......
此差异已折叠。
...@@ -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);
pci_write_config_word(dev, PCI_COMMAND, if (orig_cmd & PCI_COMMAND_DECODE_ENABLE) {
orig_cmd & ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO)); pci_write_config_word(dev, PCI_COMMAND,
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) int i;
return; bool *unassigned = data;
for_each_pci_dev(dev) {
int i;
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,15 +1471,17 @@ pci_assign_unassigned_resources(void) ...@@ -1470,15 +1471,17 @@ 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_depth, pci_try_num); "max bus depth: %d pci_try_num: %d\n",
max_depth, pci_try_num);
} }
again: again:
...@@ -1490,32 +1493,30 @@ pci_assign_unassigned_resources(void) ...@@ -1490,32 +1493,30 @@ 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));
tried_times++; tried_times++;
/* 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,14 +1545,17 @@ pci_assign_unassigned_resources(void) ...@@ -1545,14 +1545,17 @@ 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)
...@@ -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);
}; };
/** /**
......
...@@ -421,24 +421,24 @@ ...@@ -421,24 +421,24 @@
#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */ #define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */
#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */ #define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */
#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ #define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ #define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCIe to PCI/PCI-X Bridge */
#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIE Bridge */ #define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIe Bridge */
#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */ #define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */
#define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */ #define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */
#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ #define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ #define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
#define PCI_EXP_DEVCAP 4 /* Device capabilities */ #define PCI_EXP_DEVCAP 4 /* Device capabilities */
#define PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */ #define PCI_EXP_DEVCAP_PAYLOAD 0x00000007 /* Max_Payload_Size */
#define PCI_EXP_DEVCAP_PHANTOM 0x18 /* Phantom functions */ #define PCI_EXP_DEVCAP_PHANTOM 0x00000018 /* Phantom functions */
#define PCI_EXP_DEVCAP_EXT_TAG 0x20 /* Extended tags */ #define PCI_EXP_DEVCAP_EXT_TAG 0x00000020 /* Extended tags */
#define PCI_EXP_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */ #define PCI_EXP_DEVCAP_L0S 0x000001c0 /* L0s Acceptable Latency */
#define PCI_EXP_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */ #define PCI_EXP_DEVCAP_L1 0x00000e00 /* L1 Acceptable Latency */
#define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */ #define PCI_EXP_DEVCAP_ATN_BUT 0x00001000 /* Attention Button Present */
#define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */ #define PCI_EXP_DEVCAP_ATN_IND 0x00002000 /* Attention Indicator Present */
#define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */ #define PCI_EXP_DEVCAP_PWR_IND 0x00004000 /* Power Indicator Present */
#define PCI_EXP_DEVCAP_RBER 0x8000 /* Role-Based Error Reporting */ #define PCI_EXP_DEVCAP_RBER 0x00008000 /* Role-Based Error Reporting */
#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ #define PCI_EXP_DEVCAP_PWR_VAL 0x03fc0000 /* Slot Power Limit Value */
#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ #define PCI_EXP_DEVCAP_PWR_SCL 0x0c000000 /* Slot Power Limit Scale */
#define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ #define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */
#define PCI_EXP_DEVCTL 8 /* Device Control */ #define PCI_EXP_DEVCTL 8 /* Device Control */
#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ #define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */
...@@ -454,16 +454,16 @@ ...@@ -454,16 +454,16 @@
#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ #define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */ #define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */
#define PCI_EXP_DEVSTA 10 /* Device Status */ #define PCI_EXP_DEVSTA 10 /* Device Status */
#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */ #define PCI_EXP_DEVSTA_CED 0x0001 /* Correctable Error Detected */
#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */ #define PCI_EXP_DEVSTA_NFED 0x0002 /* Non-Fatal Error Detected */
#define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */ #define PCI_EXP_DEVSTA_FED 0x0004 /* Fatal Error Detected */
#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */ #define PCI_EXP_DEVSTA_URD 0x0008 /* Unsupported Request Detected */
#define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */ #define PCI_EXP_DEVSTA_AUXPD 0x0010 /* AUX Power Detected */
#define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */ #define PCI_EXP_DEVSTA_TRPND 0x0020 /* Transactions Pending */
#define PCI_EXP_LNKCAP 12 /* Link Capabilities */ #define PCI_EXP_LNKCAP 12 /* Link Capabilities */
#define PCI_EXP_LNKCAP_SLS 0x0000000f /* Supported Link Speeds */ #define PCI_EXP_LNKCAP_SLS 0x0000000f /* Supported Link Speeds */
#define PCI_EXP_LNKCAP_SLS_2_5GB 0x1 /* LNKCAP2 SLS Vector bit 0 (2.5GT/s) */ #define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0 */
#define PCI_EXP_LNKCAP_SLS_5_0GB 0x2 /* LNKCAP2 SLS Vector bit 1 (5.0GT/s) */ #define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */
#define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */ #define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */
#define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */ #define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */
#define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */ #define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */
...@@ -475,21 +475,21 @@ ...@@ -475,21 +475,21 @@
#define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */ #define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */
#define PCI_EXP_LNKCTL 16 /* Link Control */ #define PCI_EXP_LNKCTL 16 /* Link Control */
#define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */ #define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */
#define PCI_EXP_LNKCTL_ASPM_L0S 0x01 /* L0s Enable */ #define PCI_EXP_LNKCTL_ASPM_L0S 0x0001 /* L0s Enable */
#define PCI_EXP_LNKCTL_ASPM_L1 0x02 /* L1 Enable */ #define PCI_EXP_LNKCTL_ASPM_L1 0x0002 /* L1 Enable */
#define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */ #define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */
#define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */ #define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */
#define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */ #define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */
#define PCI_EXP_LNKCTL_CCC 0x0040 /* Common Clock Configuration */ #define PCI_EXP_LNKCTL_CCC 0x0040 /* Common Clock Configuration */
#define PCI_EXP_LNKCTL_ES 0x0080 /* Extended Synch */ #define PCI_EXP_LNKCTL_ES 0x0080 /* Extended Synch */
#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */ #define PCI_EXP_LNKCTL_CLKREQ_EN 0x0100 /* Enable clkreq */
#define PCI_EXP_LNKCTL_HAWD 0x0200 /* Hardware Autonomous Width Disable */ #define PCI_EXP_LNKCTL_HAWD 0x0200 /* Hardware Autonomous Width Disable */
#define PCI_EXP_LNKCTL_LBMIE 0x0400 /* Link Bandwidth Management Interrupt Enable */ #define PCI_EXP_LNKCTL_LBMIE 0x0400 /* Link Bandwidth Management Interrupt Enable */
#define PCI_EXP_LNKCTL_LABIE 0x0800 /* Lnk Autonomous Bandwidth Interrupt Enable */ #define PCI_EXP_LNKCTL_LABIE 0x0800 /* Lnk Autonomous Bandwidth Interrupt Enable */
#define PCI_EXP_LNKSTA 18 /* Link Status */ #define PCI_EXP_LNKSTA 18 /* Link Status */
#define PCI_EXP_LNKSTA_CLS 0x000f /* Current Link Speed */ #define PCI_EXP_LNKSTA_CLS 0x000f /* Current Link Speed */
#define PCI_EXP_LNKSTA_CLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */ #define PCI_EXP_LNKSTA_CLS_2_5GB 0x0001 /* Current Link Speed 2.5GT/s */
#define PCI_EXP_LNKSTA_CLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */ #define PCI_EXP_LNKSTA_CLS_5_0GB 0x0002 /* Current Link Speed 5.0GT/s */
#define PCI_EXP_LNKSTA_NLW 0x03f0 /* Nogotiated Link Width */ #define PCI_EXP_LNKSTA_NLW 0x03f0 /* Nogotiated Link Width */
#define PCI_EXP_LNKSTA_NLW_SHIFT 4 /* start of NLW mask in link status */ #define PCI_EXP_LNKSTA_NLW_SHIFT 4 /* start of NLW mask in link status */
#define PCI_EXP_LNKSTA_LT 0x0800 /* Link Training */ #define PCI_EXP_LNKSTA_LT 0x0800 /* Link Training */
...@@ -534,44 +534,49 @@ ...@@ -534,44 +534,49 @@
#define PCI_EXP_SLTSTA_EIS 0x0080 /* Electromechanical Interlock Status */ #define PCI_EXP_SLTSTA_EIS 0x0080 /* Electromechanical Interlock Status */
#define PCI_EXP_SLTSTA_DLLSC 0x0100 /* Data Link Layer State Changed */ #define PCI_EXP_SLTSTA_DLLSC 0x0100 /* Data Link Layer State Changed */
#define PCI_EXP_RTCTL 28 /* Root Control */ #define PCI_EXP_RTCTL 28 /* Root Control */
#define PCI_EXP_RTCTL_SECEE 0x01 /* System Error on Correctable Error */ #define PCI_EXP_RTCTL_SECEE 0x0001 /* System Error on Correctable Error */
#define PCI_EXP_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Error */ #define PCI_EXP_RTCTL_SENFEE 0x0002 /* System Error on Non-Fatal Error */
#define PCI_EXP_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */ #define PCI_EXP_RTCTL_SEFEE 0x0004 /* System Error on Fatal Error */
#define PCI_EXP_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */ #define PCI_EXP_RTCTL_PMEIE 0x0008 /* PME Interrupt Enable */
#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */ #define PCI_EXP_RTCTL_CRSSVE 0x0010 /* CRS Software Visibility Enable */
#define PCI_EXP_RTCAP 30 /* Root Capabilities */ #define PCI_EXP_RTCAP 30 /* Root Capabilities */
#define PCI_EXP_RTSTA 32 /* Root Status */ #define PCI_EXP_RTSTA 32 /* Root Status */
#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ #define PCI_EXP_RTSTA_PME 0x00010000 /* PME status */
#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ #define PCI_EXP_RTSTA_PENDING 0x00020000 /* PME pending */
/* /*
* Note that the following PCI Express 'Capability Structure' registers * The Device Capabilities 2, Device Status 2, Device Control 2,
* were introduced with 'Capability Version' 0x2 (v2). These registers * Link Capabilities 2, Link Status 2, Link Control 2,
* do not exist on devices with Capability Version 1. Use pci_pcie_cap2() * Slot Capabilities 2, Slot Status 2, and Slot Control 2 registers
* to use these fields safely. * are only present on devices with PCIe Capability version 2.
* Use pcie_capability_read_word() and similar interfaces to use them
* safely.
*/ */
#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */ #define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */ #define PCI_EXP_DEVCAP2_ARI 0x00000020 /* Alternative Routing-ID */
#define PCI_EXP_DEVCAP2_LTR 0x800 /* Latency tolerance reporting */ #define PCI_EXP_DEVCAP2_LTR 0x00000800 /* Latency tolerance reporting */
#define PCI_EXP_OBFF_MASK 0xc0000 /* OBFF support mechanism */ #define PCI_EXP_DEVCAP2_OBFF_MASK 0x000c0000 /* OBFF support mechanism */
#define PCI_EXP_OBFF_MSG 0x40000 /* New message signaling */ #define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */
#define PCI_EXP_OBFF_WAKE 0x80000 /* Re-use WAKE# for OBFF */ #define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000 /* Re-use WAKE# for OBFF */
#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ #define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */ #define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */
#define PCI_EXP_IDO_REQ_EN 0x100 /* ID-based ordering request enable */ #define PCI_EXP_DEVCTL2_IDO_REQ_EN 0x0100 /* Allow IDO for requests */
#define PCI_EXP_IDO_CMP_EN 0x200 /* ID-based ordering completion enable */ #define PCI_EXP_DEVCTL2_IDO_CMP_EN 0x0200 /* Allow IDO for completions */
#define PCI_EXP_LTR_EN 0x400 /* Latency tolerance reporting */ #define PCI_EXP_DEVCTL2_LTR_EN 0x0400 /* Enable LTR mechanism */
#define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */ #define PCI_EXP_DEVCTL2_OBFF_MSGA_EN 0x2000 /* Enable OBFF Message type A */
#define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ #define PCI_EXP_DEVCTL2_OBFF_MSGB_EN 0x4000 /* Enable OBFF Message type B */
#define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ #define PCI_EXP_DEVCTL2_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */
#define PCI_EXP_DEVSTA2 42 /* Device Status 2 */
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */ #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */
#define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */ #define PCI_EXP_LNKCAP2 44 /* Link Capabilities 2 */
#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x02 /* Supported Link Speed 2.5GT/s */ #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x00000002 /* Supported Speed 2.5GT/s */
#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x04 /* Supported Link Speed 5.0GT/s */ #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x00000004 /* Supported Speed 5.0GT/s */
#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x08 /* Supported Link Speed 8.0GT/s */ #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x00000008 /* Supported Speed 8.0GT/s */
#define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */ #define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100 /* Crosslink supported */
#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
#define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */
#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */
#define PCI_EXP_SLTSTA2 58 /* Slot Status 2 */
/* Extended Capabilities (PCI-X 2.0 and Express) */ /* Extended Capabilities (PCI-X 2.0 and Express) */
#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) #define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册