Commit c75059c4 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull PCI changes from Bjorn Helgaas:
 "Here are the PCI changes intended for v3.19.  I don't think there's
  anything very exciting here, but there was a lot of MSI-related stuff
  coming via Thomas.

  Details:

  NUMA
    - Allow numa_node override via sysfs (Prarit Bhargava)

  Resource management
    - Restore detection of read-only BARs (Myron Stowe)
    - Shrink decoding-disabled window while sizing BARs (Myron Stowe)
    - Add informational printk for invalid BARs (Myron Stowe)
    - Remove fixed parameter in pci_iov_resource_bar() (Myron Stowe)

  MSI
    - Add pci_msi_ignore_mask to prevent writes to MSI/MSI-X Mask Bits (Yijing Wang)
    - Revert "PCI: Add x86_msi.msi_mask_irq() and msix_mask_irq()" (Yijing Wang)
    - s390/MSI: Use __msi_mask_irq() instead of default_msi_mask_irq() (Yijing Wang)

  Virtualization
    - xen: Process failure for pcifront_(re)scan_root() (Chen Gang)
    - Make FLR and AF FLR reset warning messages different (Gavin Shan)

  Generic host bridge driver
    - Allocate config space windows after limiting bus number range (Lorenzo Pieralisi)
    - Convert to DT resource parsing API (Lorenzo Pieralisi)

  Freescale Layerscape
    - Add Freescale Layerscape PCIe driver (Minghuan Lian)

  NVIDIA Tegra
    - Do not build on 64-bit ARM (Thierry Reding)
    - Add Kconfig help text (Thierry Reding)

  Renesas R-Car
    - Make rcar_pci static (Jingoo Han)

  Samsung Exynos
    - Add exynos prefix to add_pcie_port(), pcie_init() (Jingoo Han)

  ST Microelectronics SPEAr13xx
    - Add spear prefix to add_pcie_port(), pcie_init() (Jingoo Han)
    - Make spear13xx_add_pcie_port() __init (Jingoo Han)
    - Remove unnecessary OOM message (Jingoo Han)

  TI DRA7xx
    - Add dra7xx prefix to add_pcie_port() (Jingoo Han)
    - Make dra7xx_add_pcie_port() __init (Jingoo Han)

  TI Keystone
    - Make ks_dw_pcie_msi_domain_ops static (Jingoo Han)
    - Remove unnecessary OOM message (Jingoo Han)

  Miscellaneous
    - Delete unnecessary NULL pointer checks (Markus Elfring)
    - Remove unused to_hotplug_slot() (Gavin Shan)
    - Whitespace cleanup (Jingoo Han)
    - Simplify if-return sequences (Quentin Lambert)"

* tag 'pci-v3.19-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (28 commits)
  PCI: Remove fixed parameter in pci_iov_resource_bar()
  PCI: Add informational printk for invalid BARs
  PCI: tegra: Add Kconfig help text
  PCI: tegra: Do not build on 64-bit ARM
  PCI: spear: Remove unnecessary OOM message
  PCI: mvebu: Add a blank line after declarations
  PCI: designware: Add a blank line after declarations
  PCI: exynos: Remove unnecessary return statement
  PCI: imx6: Use tabs for indentation
  PCI: keystone: Remove unnecessary OOM message
  PCI: Remove unused and broken to_hotplug_slot()
  PCI: Make FLR and AF FLR reset warning messages different
  PCI: dra7xx: Add __init annotation to dra7xx_add_pcie_port()
  PCI: spear: Add __init annotation to spear13xx_add_pcie_port()
  PCI: spear: Rename add_pcie_port(), pcie_init() to spear13xx_add_pcie_port(), etc.
  PCI: dra7xx: Rename add_pcie_port() to dra7xx_add_pcie_port()
  PCI: layerscape: Add Freescale Layerscape PCIe driver
  PCI: Simplify if-return sequences
  PCI: Delete unnecessary NULL pointer checks
  PCI: Shrink decoding-disabled window while sizing BARs
  ...
parents f74ea368 14979279
...@@ -281,3 +281,16 @@ Description: ...@@ -281,3 +281,16 @@ Description:
opt-out of driver binding using a driver_override name such as opt-out of driver binding using a driver_override name such as
"none". Only a single driver may be specified in the override, "none". Only a single driver may be specified in the override,
there is no support for parsing delimiters. there is no support for parsing delimiters.
What: /sys/bus/pci/devices/.../numa_node
Date: Oct 2014
Contact: Prarit Bhargava <prarit@redhat.com>
Description:
This file contains the NUMA node to which the PCI device is
attached, or -1 if the node is unknown. The initial value
comes from an ACPI _PXM method or a similar firmware
source. If that is missing or incorrect, this file can be
written to override the node. In that case, please report
a firmware bug to the system vendor. Writing to this file
taints the kernel with TAINT_FIRMWARE_WORKAROUND, which
reduces the supportability of your system.
Freescale Layerscape PCIe controller
This PCIe host controller is based on the Synopsis Designware PCIe IP
and thus inherits all the common properties defined in designware-pcie.txt.
Required properties:
- compatible: should contain the platform identifier such as "fsl,ls1021a-pcie"
- reg: base addresses and lengths of the PCIe controller
- interrupts: A list of interrupt outputs of the controller. Must contain an
entry for each entry in the interrupt-names property.
- interrupt-names: Must include the following entries:
"intr": The interrupt that is asserted for controller interrupts
- fsl,pcie-scfg: Must include two entries.
The first entry must be a link to the SCFG device node
The second entry must be '0' or '1' based on physical PCIe controller index.
This is used to get SCFG PEXN registers
Example:
pcie@3400000 {
compatible = "fsl,ls1021a-pcie", "snps,dw-pcie";
reg = <0x00 0x03400000 0x0 0x00010000 /* controller registers */
0x40 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
interrupt-names = "intr";
fsl,pcie-scfg = <&scfg 0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
num-lanes = <4>;
bus-range = <0x0 0xff>;
ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000 /* downstream I/O */
0xc2000000 0x0 0x20000000 0x40 0x20000000 0x0 0x20000000 /* prefetchable memory */
0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0000 0 0 1 &gic GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
<0000 0 0 2 &gic GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>,
<0000 0 0 3 &gic GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
<0000 0 0 4 &gic GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
};
...@@ -7086,6 +7086,16 @@ S: Maintained ...@@ -7086,6 +7086,16 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/xgene-pci.txt F: Documentation/devicetree/bindings/pci/xgene-pci.txt
F: drivers/pci/host/pci-xgene.c F: drivers/pci/host/pci-xgene.c
PCI DRIVER FOR FREESCALE LAYERSCAPE
M: Minghuan Lian <minghuan.Lian@freescale.com>
M: Mingkai Hu <mingkai.hu@freescale.com>
M: Roy Zang <tie-fei.zang@freescale.com>
L: linuxppc-dev@lists.ozlabs.org
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: drivers/pci/host/*layerscape*
PCI DRIVER FOR IMX6 PCI DRIVER FOR IMX6
M: Richard Zhu <r65037@freescale.com> M: Richard Zhu <r65037@freescale.com>
M: Lucas Stach <l.stach@pengutronix.de> M: Lucas Stach <l.stach@pengutronix.de>
......
...@@ -32,7 +32,10 @@ config PCI_IMX6 ...@@ -32,7 +32,10 @@ config PCI_IMX6
config PCI_TEGRA config PCI_TEGRA
bool "NVIDIA Tegra PCIe controller" bool "NVIDIA Tegra PCIe controller"
depends on ARCH_TEGRA depends on ARCH_TEGRA && !ARM64
help
Say Y here if you want support for the PCIe host controller found
on NVIDIA Tegra SoCs.
config PCI_RCAR_GEN2 config PCI_RCAR_GEN2
bool "Renesas R-Car Gen2 Internal PCI controller" bool "Renesas R-Car Gen2 Internal PCI controller"
...@@ -91,4 +94,12 @@ config PCI_XGENE ...@@ -91,4 +94,12 @@ config PCI_XGENE
There are 5 internal PCIe ports available. Each port is GEN3 capable There are 5 internal PCIe ports available. Each port is GEN3 capable
and have varied lanes from x1 to x8. and have varied lanes from x1 to x8.
config PCI_LAYERSCAPE
bool "Freescale Layerscape PCIe controller"
depends on OF && ARM
select PCIE_DW
select MFD_SYSCON
help
Say Y here if you want PCIe controller support on Layerscape SoCs.
endmenu endmenu
...@@ -11,3 +11,4 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o ...@@ -11,3 +11,4 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
obj-$(CONFIG_PCI_XGENE) += pci-xgene.o obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
...@@ -270,8 +270,8 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg) ...@@ -270,8 +270,8 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int add_pcie_port(struct dra7xx_pcie *dra7xx, static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
struct platform_device *pdev) struct platform_device *pdev)
{ {
int ret; int ret;
struct pcie_port *pp; struct pcie_port *pp;
...@@ -398,7 +398,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) ...@@ -398,7 +398,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dra7xx); platform_set_drvdata(pdev, dra7xx);
ret = add_pcie_port(dra7xx, pdev); ret = dra7xx_add_pcie_port(dra7xx, pdev);
if (ret < 0) if (ret < 0)
goto err_add_port; goto err_add_port;
......
...@@ -312,7 +312,6 @@ static void exynos_pcie_assert_reset(struct pcie_port *pp) ...@@ -312,7 +312,6 @@ static void exynos_pcie_assert_reset(struct pcie_port *pp)
if (exynos_pcie->reset_gpio >= 0) if (exynos_pcie->reset_gpio >= 0)
devm_gpio_request_one(pp->dev, exynos_pcie->reset_gpio, devm_gpio_request_one(pp->dev, exynos_pcie->reset_gpio,
GPIOF_OUT_INIT_HIGH, "RESET"); GPIOF_OUT_INIT_HIGH, "RESET");
return;
} }
static int exynos_pcie_establish_link(struct pcie_port *pp) static int exynos_pcie_establish_link(struct pcie_port *pp)
...@@ -388,7 +387,6 @@ static void exynos_pcie_clear_irq_pulse(struct pcie_port *pp) ...@@ -388,7 +387,6 @@ static void exynos_pcie_clear_irq_pulse(struct pcie_port *pp)
val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE); val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE);
exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE); exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE);
return;
} }
static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp)
...@@ -400,7 +398,6 @@ static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) ...@@ -400,7 +398,6 @@ static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp)
val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT |
IRQ_INTC_ASSERT | IRQ_INTD_ASSERT, IRQ_INTC_ASSERT | IRQ_INTD_ASSERT,
exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE); exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE);
return;
} }
static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
...@@ -429,7 +426,6 @@ static void exynos_pcie_msi_init(struct pcie_port *pp) ...@@ -429,7 +426,6 @@ static void exynos_pcie_msi_init(struct pcie_port *pp)
val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL); val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL);
val |= IRQ_MSI_ENABLE; val |= IRQ_MSI_ENABLE;
exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL); exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL);
return;
} }
static void exynos_pcie_enable_interrupts(struct pcie_port *pp) static void exynos_pcie_enable_interrupts(struct pcie_port *pp)
...@@ -438,8 +434,6 @@ static void exynos_pcie_enable_interrupts(struct pcie_port *pp) ...@@ -438,8 +434,6 @@ static void exynos_pcie_enable_interrupts(struct pcie_port *pp)
if (IS_ENABLED(CONFIG_PCI_MSI)) if (IS_ENABLED(CONFIG_PCI_MSI))
exynos_pcie_msi_init(pp); exynos_pcie_msi_init(pp);
return;
} }
static inline void exynos_pcie_readl_rc(struct pcie_port *pp, static inline void exynos_pcie_readl_rc(struct pcie_port *pp,
...@@ -448,7 +442,6 @@ static inline void exynos_pcie_readl_rc(struct pcie_port *pp, ...@@ -448,7 +442,6 @@ static inline void exynos_pcie_readl_rc(struct pcie_port *pp,
exynos_pcie_sideband_dbi_r_mode(pp, true); exynos_pcie_sideband_dbi_r_mode(pp, true);
*val = readl(dbi_base); *val = readl(dbi_base);
exynos_pcie_sideband_dbi_r_mode(pp, false); exynos_pcie_sideband_dbi_r_mode(pp, false);
return;
} }
static inline void exynos_pcie_writel_rc(struct pcie_port *pp, static inline void exynos_pcie_writel_rc(struct pcie_port *pp,
...@@ -457,7 +450,6 @@ static inline void exynos_pcie_writel_rc(struct pcie_port *pp, ...@@ -457,7 +450,6 @@ static inline void exynos_pcie_writel_rc(struct pcie_port *pp,
exynos_pcie_sideband_dbi_w_mode(pp, true); exynos_pcie_sideband_dbi_w_mode(pp, true);
writel(val, dbi_base); writel(val, dbi_base);
exynos_pcie_sideband_dbi_w_mode(pp, false); exynos_pcie_sideband_dbi_w_mode(pp, false);
return;
} }
static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
...@@ -509,8 +501,8 @@ static struct pcie_host_ops exynos_pcie_host_ops = { ...@@ -509,8 +501,8 @@ static struct pcie_host_ops exynos_pcie_host_ops = {
.host_init = exynos_pcie_host_init, .host_init = exynos_pcie_host_init,
}; };
static int __init add_pcie_port(struct pcie_port *pp, static int __init exynos_add_pcie_port(struct pcie_port *pp,
struct platform_device *pdev) struct platform_device *pdev)
{ {
int ret; int ret;
...@@ -615,7 +607,7 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) ...@@ -615,7 +607,7 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
goto fail_bus_clk; goto fail_bus_clk;
} }
ret = add_pcie_port(pp, pdev); ret = exynos_add_pcie_port(pp, pdev);
if (ret < 0) if (ret < 0)
goto fail_bus_clk; goto fail_bus_clk;
...@@ -656,11 +648,11 @@ static struct platform_driver exynos_pcie_driver = { ...@@ -656,11 +648,11 @@ static struct platform_driver exynos_pcie_driver = {
/* Exynos PCIe driver does not allow module unload */ /* Exynos PCIe driver does not allow module unload */
static int __init pcie_init(void) static int __init exynos_pcie_init(void)
{ {
return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe);
} }
subsys_initcall(pcie_init); subsys_initcall(exynos_pcie_init);
MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
MODULE_DESCRIPTION("Samsung PCIe host controller driver"); MODULE_DESCRIPTION("Samsung PCIe host controller driver");
......
...@@ -32,7 +32,7 @@ struct gen_pci_cfg_bus_ops { ...@@ -32,7 +32,7 @@ struct gen_pci_cfg_bus_ops {
struct gen_pci_cfg_windows { struct gen_pci_cfg_windows {
struct resource res; struct resource res;
struct resource bus_range; struct resource *bus_range;
void __iomem **win; void __iomem **win;
const struct gen_pci_cfg_bus_ops *ops; const struct gen_pci_cfg_bus_ops *ops;
...@@ -50,7 +50,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus, ...@@ -50,7 +50,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
{ {
struct pci_sys_data *sys = bus->sysdata; struct pci_sys_data *sys = bus->sysdata;
struct gen_pci *pci = sys->private_data; struct gen_pci *pci = sys->private_data;
resource_size_t idx = bus->number - pci->cfg.bus_range.start; resource_size_t idx = bus->number - pci->cfg.bus_range->start;
return pci->cfg.win[idx] + ((devfn << 8) | where); return pci->cfg.win[idx] + ((devfn << 8) | where);
} }
...@@ -66,7 +66,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus, ...@@ -66,7 +66,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
{ {
struct pci_sys_data *sys = bus->sysdata; struct pci_sys_data *sys = bus->sysdata;
struct gen_pci *pci = sys->private_data; struct gen_pci *pci = sys->private_data;
resource_size_t idx = bus->number - pci->cfg.bus_range.start; resource_size_t idx = bus->number - pci->cfg.bus_range->start;
return pci->cfg.win[idx] + ((devfn << 12) | where); return pci->cfg.win[idx] + ((devfn << 12) | where);
} }
...@@ -138,106 +138,50 @@ static const struct of_device_id gen_pci_of_match[] = { ...@@ -138,106 +138,50 @@ static const struct of_device_id gen_pci_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, gen_pci_of_match); MODULE_DEVICE_TABLE(of, gen_pci_of_match);
static int gen_pci_calc_io_offset(struct device *dev,
struct of_pci_range *range,
struct resource *res,
resource_size_t *offset)
{
static atomic_t wins = ATOMIC_INIT(0);
int err, idx, max_win;
unsigned int window;
if (!PAGE_ALIGNED(range->cpu_addr))
return -EINVAL;
max_win = (IO_SPACE_LIMIT + 1) / SZ_64K;
idx = atomic_inc_return(&wins);
if (idx > max_win)
return -ENOSPC;
window = (idx - 1) * SZ_64K;
err = pci_ioremap_io(window, range->cpu_addr);
if (err)
return err;
of_pci_range_to_resource(range, dev->of_node, res);
res->start = window;
res->end = res->start + range->size - 1;
*offset = window - range->pci_addr;
return 0;
}
static int gen_pci_calc_mem_offset(struct device *dev,
struct of_pci_range *range,
struct resource *res,
resource_size_t *offset)
{
of_pci_range_to_resource(range, dev->of_node, res);
*offset = range->cpu_addr - range->pci_addr;
return 0;
}
static void gen_pci_release_of_pci_ranges(struct gen_pci *pci) static void gen_pci_release_of_pci_ranges(struct gen_pci *pci)
{ {
struct pci_host_bridge_window *win;
list_for_each_entry(win, &pci->resources, list)
release_resource(win->res);
pci_free_resource_list(&pci->resources); pci_free_resource_list(&pci->resources);
} }
static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci) static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
{ {
struct of_pci_range range;
struct of_pci_range_parser parser;
int err, res_valid = 0; int err, res_valid = 0;
struct device *dev = pci->host.dev.parent; struct device *dev = pci->host.dev.parent;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
resource_size_t iobase;
struct pci_host_bridge_window *win;
if (of_pci_range_parser_init(&parser, np)) { err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
dev_err(dev, "missing \"ranges\" property\n"); &iobase);
return -EINVAL; if (err)
} return err;
for_each_of_pci_range(&parser, &range) {
struct resource *parent, *res;
resource_size_t offset;
u32 restype = range.flags & IORESOURCE_TYPE_BITS;
res = devm_kmalloc(dev, sizeof(*res), GFP_KERNEL); list_for_each_entry(win, &pci->resources, list) {
if (!res) { struct resource *parent, *res = win->res;
err = -ENOMEM;
goto out_release_res;
}
switch (restype) { switch (resource_type(res)) {
case IORESOURCE_IO: case IORESOURCE_IO:
parent = &ioport_resource; parent = &ioport_resource;
err = gen_pci_calc_io_offset(dev, &range, res, &offset); err = pci_remap_iospace(res, iobase);
if (err) {
dev_warn(dev, "error %d: failed to map resource %pR\n",
err, res);
continue;
}
break; break;
case IORESOURCE_MEM: case IORESOURCE_MEM:
parent = &iomem_resource; parent = &iomem_resource;
err = gen_pci_calc_mem_offset(dev, &range, res, &offset); res_valid |= !(res->flags & IORESOURCE_PREFETCH);
res_valid |= !(res->flags & IORESOURCE_PREFETCH || err);
break; break;
case IORESOURCE_BUS:
pci->cfg.bus_range = res;
default: default:
err = -EINVAL;
continue;
}
if (err) {
dev_warn(dev,
"error %d: failed to add resource [type 0x%x, %lld bytes]\n",
err, restype, range.size);
continue; continue;
} }
err = request_resource(parent, res); err = devm_request_resource(dev, parent, res);
if (err) if (err)
goto out_release_res; goto out_release_res;
pci_add_resource_offset(&pci->resources, res, offset);
} }
if (!res_valid) { if (!res_valid) {
...@@ -262,38 +206,30 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) ...@@ -262,38 +206,30 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
struct device *dev = pci->host.dev.parent; struct device *dev = pci->host.dev.parent;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
if (of_pci_parse_bus_range(np, &pci->cfg.bus_range))
pci->cfg.bus_range = (struct resource) {
.name = np->name,
.start = 0,
.end = 0xff,
.flags = IORESOURCE_BUS,
};
err = of_address_to_resource(np, 0, &pci->cfg.res); err = of_address_to_resource(np, 0, &pci->cfg.res);
if (err) { if (err) {
dev_err(dev, "missing \"reg\" property\n"); dev_err(dev, "missing \"reg\" property\n");
return err; return err;
} }
pci->cfg.win = devm_kcalloc(dev, resource_size(&pci->cfg.bus_range), /* Limit the bus-range to fit within reg */
bus_max = pci->cfg.bus_range->start +
(resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
pci->cfg.bus_range->end = min_t(resource_size_t,
pci->cfg.bus_range->end, bus_max);
pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range),
sizeof(*pci->cfg.win), GFP_KERNEL); sizeof(*pci->cfg.win), GFP_KERNEL);
if (!pci->cfg.win) if (!pci->cfg.win)
return -ENOMEM; return -ENOMEM;
/* Limit the bus-range to fit within reg */
bus_max = pci->cfg.bus_range.start +
(resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
pci->cfg.bus_range.end = min_t(resource_size_t, pci->cfg.bus_range.end,
bus_max);
/* Map our Configuration Space windows */ /* Map our Configuration Space windows */
if (!devm_request_mem_region(dev, pci->cfg.res.start, if (!devm_request_mem_region(dev, pci->cfg.res.start,
resource_size(&pci->cfg.res), resource_size(&pci->cfg.res),
"Configuration Space")) "Configuration Space"))
return -ENOMEM; return -ENOMEM;
bus_range = &pci->cfg.bus_range; bus_range = pci->cfg.bus_range;
for (busn = bus_range->start; busn <= bus_range->end; ++busn) { for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
u32 idx = busn - bus_range->start; u32 idx = busn - bus_range->start;
u32 sz = 1 << pci->cfg.ops->bus_shift; u32 sz = 1 << pci->cfg.ops->bus_shift;
...@@ -305,8 +241,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) ...@@ -305,8 +241,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
return -ENOMEM; return -ENOMEM;
} }
/* Register bus resource */
pci_add_resource(&pci->resources, bus_range);
return 0; return 0;
} }
......
...@@ -533,8 +533,8 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp, ...@@ -533,8 +533,8 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
} }
ret = devm_request_irq(&pdev->dev, pp->msi_irq, ret = devm_request_irq(&pdev->dev, pp->msi_irq,
imx6_pcie_msi_handler, imx6_pcie_msi_handler,
IRQF_SHARED, "mx6-pcie-msi", pp); IRQF_SHARED, "mx6-pcie-msi", pp);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to request MSI irq\n"); dev_err(&pdev->dev, "failed to request MSI irq\n");
return -ENODEV; return -ENODEV;
......
...@@ -201,7 +201,7 @@ static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, ...@@ -201,7 +201,7 @@ static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
return 0; return 0;
} }
const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = { static const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = {
.map = ks_dw_pcie_msi_map, .map = ks_dw_pcie_msi_map,
}; };
......
...@@ -353,10 +353,9 @@ static int __init ks_pcie_probe(struct platform_device *pdev) ...@@ -353,10 +353,9 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
ks_pcie = devm_kzalloc(&pdev->dev, sizeof(*ks_pcie), ks_pcie = devm_kzalloc(&pdev->dev, sizeof(*ks_pcie),
GFP_KERNEL); GFP_KERNEL);
if (!ks_pcie) { if (!ks_pcie)
dev_err(dev, "no memory for keystone pcie\n");
return -ENOMEM; return -ENOMEM;
}
pp = &ks_pcie->pp; pp = &ks_pcie->pp;
/* initialize SerDes Phy if present */ /* initialize SerDes Phy if present */
......
/*
* PCIe host controller driver for Freescale Layerscape SoCs
*
* Copyright (C) 2014 Freescale Semiconductor.
*
* Author: Minghuan Lian <Minghuan.Lian@freescale.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/kernel.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/resource.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "pcie-designware.h"
/* PEX1/2 Misc Ports Status Register */
#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4)
#define LTSSM_STATE_SHIFT 20
#define LTSSM_STATE_MASK 0x3f
#define LTSSM_PCIE_L0 0x11 /* L0 state */
/* Symbol Timer Register and Filter Mask Register 1 */
#define PCIE_STRFMR1 0x71c
struct ls_pcie {
struct list_head node;
struct device *dev;
struct pci_bus *bus;
void __iomem *dbi;
struct regmap *scfg;
struct pcie_port pp;
int index;
int msi_irq;
};
#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp)
static int ls_pcie_link_up(struct pcie_port *pp)
{
u32 state;
struct ls_pcie *pcie = to_ls_pcie(pp);
regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state);
state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
if (state < LTSSM_PCIE_L0)
return 0;
return 1;
}
static void ls_pcie_host_init(struct pcie_port *pp)
{
struct ls_pcie *pcie = to_ls_pcie(pp);
int count = 0;
u32 val;
dw_pcie_setup_rc(pp);
while (!ls_pcie_link_up(pp)) {
usleep_range(100, 1000);
count++;
if (count >= 200) {
dev_err(pp->dev, "phy link never came up\n");
return;
}
}
/*
* LS1021A Workaround for internal TKT228622
* to fix the INTx hang issue
*/
val = ioread32(pcie->dbi + PCIE_STRFMR1);
val &= 0xffff;
iowrite32(val, pcie->dbi + PCIE_STRFMR1);
}
static struct pcie_host_ops ls_pcie_host_ops = {
.link_up = ls_pcie_link_up,
.host_init = ls_pcie_host_init,
};
static int ls_add_pcie_port(struct ls_pcie *pcie)
{
struct pcie_port *pp;
int ret;
pp = &pcie->pp;
pp->dev = pcie->dev;
pp->dbi_base = pcie->dbi;
pp->root_bus_nr = -1;
pp->ops = &ls_pcie_host_ops;
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(pp->dev, "failed to initialize host\n");
return ret;
}
return 0;
}
static int __init ls_pcie_probe(struct platform_device *pdev)
{
struct ls_pcie *pcie;
struct resource *dbi_base;
u32 index[2];
int ret;
pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
return -ENOMEM;
pcie->dev = &pdev->dev;
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
if (!dbi_base) {
dev_err(&pdev->dev, "missing *regs* space\n");
return -ENODEV;
}
pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base);
if (IS_ERR(pcie->dbi))
return PTR_ERR(pcie->dbi);
pcie->scfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"fsl,pcie-scfg");
if (IS_ERR(pcie->scfg)) {
dev_err(&pdev->dev, "No syscfg phandle specified\n");
return PTR_ERR(pcie->scfg);
}
ret = of_property_read_u32_array(pdev->dev.of_node,
"fsl,pcie-scfg", index, 2);
if (ret)
return ret;
pcie->index = index[1];
ret = ls_add_pcie_port(pcie);
if (ret < 0)
return ret;
platform_set_drvdata(pdev, pcie);
return 0;
}
static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1021a-pcie" },
{ },
};
MODULE_DEVICE_TABLE(of, ls_pcie_of_match);
static struct platform_driver ls_pcie_driver = {
.driver = {
.name = "layerscape-pcie",
.owner = THIS_MODULE,
.of_match_table = ls_pcie_of_match,
},
};
module_platform_driver_probe(ls_pcie_driver, ls_pcie_probe);
MODULE_AUTHOR("Minghuan Lian <Minghuan.Lian@freescale.com>");
MODULE_DESCRIPTION("Freescale Layerscape PCIe host controller driver");
MODULE_LICENSE("GPL v2");
...@@ -622,6 +622,7 @@ static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie, ...@@ -622,6 +622,7 @@ static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
for (i = 0; i < pcie->nports; i++) { for (i = 0; i < pcie->nports; i++) {
struct mvebu_pcie_port *port = &pcie->ports[i]; struct mvebu_pcie_port *port = &pcie->ports[i];
if (bus->number == 0 && port->devfn == devfn) if (bus->number == 0 && port->devfn == devfn)
return port; return port;
if (bus->number != 0 && if (bus->number != 0 &&
...@@ -751,6 +752,7 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) ...@@ -751,6 +752,7 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
for (i = 0; i < pcie->nports; i++) { for (i = 0; i < pcie->nports; i++) {
struct mvebu_pcie_port *port = &pcie->ports[i]; struct mvebu_pcie_port *port = &pcie->ports[i];
if (!port->base) if (!port->base)
continue; continue;
mvebu_pcie_setup_hw(port); mvebu_pcie_setup_hw(port);
......
...@@ -380,6 +380,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp) ...@@ -380,6 +380,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
/* Get the I/O and memory ranges from DT */ /* Get the I/O and memory ranges from DT */
for_each_of_pci_range(&parser, &range) { for_each_of_pci_range(&parser, &range) {
unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
if (restype == IORESOURCE_IO) { if (restype == IORESOURCE_IO) {
of_pci_range_to_resource(&range, np, &pp->io); of_pci_range_to_resource(&range, np, &pp->io);
pp->io.name = "I/O"; pp->io.name = "I/O";
......
...@@ -380,7 +380,7 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys) ...@@ -380,7 +380,7 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
return 1; return 1;
} }
struct hw_pci rcar_pci = { static struct hw_pci rcar_pci = {
.setup = rcar_pcie_setup, .setup = rcar_pcie_setup,
.map_irq = of_irq_parse_and_map_pci, .map_irq = of_irq_parse_and_map_pci,
.ops = &rcar_pcie_ops, .ops = &rcar_pcie_ops,
......
...@@ -269,7 +269,8 @@ static struct pcie_host_ops spear13xx_pcie_host_ops = { ...@@ -269,7 +269,8 @@ static struct pcie_host_ops spear13xx_pcie_host_ops = {
.host_init = spear13xx_pcie_host_init, .host_init = spear13xx_pcie_host_init,
}; };
static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev) static int __init spear13xx_add_pcie_port(struct pcie_port *pp,
struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int ret; int ret;
...@@ -308,10 +309,8 @@ static int __init spear13xx_pcie_probe(struct platform_device *pdev) ...@@ -308,10 +309,8 @@ static int __init spear13xx_pcie_probe(struct platform_device *pdev)
int ret; int ret;
spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL); spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL);
if (!spear13xx_pcie) { if (!spear13xx_pcie)
dev_err(dev, "no memory for SPEAr13xx pcie\n");
return -ENOMEM; return -ENOMEM;
}
spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy"); spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy");
if (IS_ERR(spear13xx_pcie->phy)) { if (IS_ERR(spear13xx_pcie->phy)) {
...@@ -352,7 +351,7 @@ static int __init spear13xx_pcie_probe(struct platform_device *pdev) ...@@ -352,7 +351,7 @@ static int __init spear13xx_pcie_probe(struct platform_device *pdev)
if (of_property_read_bool(np, "st,pcie-is-gen1")) if (of_property_read_bool(np, "st,pcie-is-gen1"))
spear13xx_pcie->is_gen1 = true; spear13xx_pcie->is_gen1 = true;
ret = add_pcie_port(pp, pdev); ret = spear13xx_add_pcie_port(pp, pdev);
if (ret < 0) if (ret < 0)
goto fail_clk; goto fail_clk;
...@@ -382,11 +381,11 @@ static struct platform_driver spear13xx_pcie_driver __initdata = { ...@@ -382,11 +381,11 @@ static struct platform_driver spear13xx_pcie_driver __initdata = {
/* SPEAr13xx PCIe driver does not allow module unload */ /* SPEAr13xx PCIe driver does not allow module unload */
static int __init pcie_init(void) static int __init spear13xx_pcie_init(void)
{ {
return platform_driver_register(&spear13xx_pcie_driver); return platform_driver_register(&spear13xx_pcie_driver);
} }
module_init(pcie_init); module_init(spear13xx_pcie_init);
MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver"); MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver");
MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>"); MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
......
...@@ -376,10 +376,7 @@ int __init ibmphp_rsrc_init (void) ...@@ -376,10 +376,7 @@ int __init ibmphp_rsrc_init (void)
if (rc) if (rc)
return rc; return rc;
} }
rc = once_over (); /* This is to align ranges (so no -1) */ return once_over (); /* This is to align ranges (so no -1) */
if (rc)
return rc;
return 0;
} }
/******************************************************************************** /********************************************************************************
......
...@@ -479,20 +479,16 @@ void pci_iov_release(struct pci_dev *dev) ...@@ -479,20 +479,16 @@ void pci_iov_release(struct pci_dev *dev)
* pci_iov_resource_bar - get position of the SR-IOV BAR * pci_iov_resource_bar - get position of the SR-IOV BAR
* @dev: the PCI device * @dev: the PCI device
* @resno: the resource number * @resno: the resource number
* @type: the BAR type to be filled in
* *
* Returns position of the BAR encapsulated in the SR-IOV capability. * Returns position of the BAR encapsulated in the SR-IOV capability.
*/ */
int pci_iov_resource_bar(struct pci_dev *dev, int resno, int pci_iov_resource_bar(struct pci_dev *dev, int resno)
enum pci_bar_type *type)
{ {
if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END) if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END)
return 0; return 0;
BUG_ON(!dev->is_physfn); BUG_ON(!dev->is_physfn);
*type = pci_bar_unknown;
return dev->sriov->pos + PCI_SRIOV_BAR + return dev->sriov->pos + PCI_SRIOV_BAR +
4 * (resno - PCI_IOV_RESOURCES); 4 * (resno - PCI_IOV_RESOURCES);
} }
...@@ -510,13 +506,12 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno, ...@@ -510,13 +506,12 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno,
resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno) resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
{ {
struct resource tmp; struct resource tmp;
enum pci_bar_type type; int reg = pci_iov_resource_bar(dev, resno);
int reg = pci_iov_resource_bar(dev, resno, &type);
if (!reg) if (!reg)
return 0; return 0;
__pci_read_base(dev, type, &tmp, reg); __pci_read_base(dev, pci_bar_unknown, &tmp, reg);
return resource_alignment(&tmp); return resource_alignment(&tmp);
} }
......
...@@ -322,8 +322,7 @@ static void pci_acpi_wake_dev(struct work_struct *work) ...@@ -322,8 +322,7 @@ static void pci_acpi_wake_dev(struct work_struct *work)
pci_wakeup_event(pci_dev); pci_wakeup_event(pci_dev);
pm_runtime_resume(&pci_dev->dev); pm_runtime_resume(&pci_dev->dev);
if (pci_dev->subordinate) pci_pme_wakeup_bus(pci_dev->subordinate);
pci_pme_wakeup_bus(pci_dev->subordinate);
} }
/** /**
......
...@@ -221,12 +221,37 @@ static ssize_t enable_show(struct device *dev, struct device_attribute *attr, ...@@ -221,12 +221,37 @@ static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RW(enable); static DEVICE_ATTR_RW(enable);
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
static ssize_t numa_node_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
int node, ret;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
ret = kstrtoint(buf, 0, &node);
if (ret)
return ret;
if (!node_online(node))
return -EINVAL;
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
dev_alert(&pdev->dev, FW_BUG "Overriding NUMA node to %d. Contact your vendor for updates.",
node);
dev->numa_node = node;
return count;
}
static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
return sprintf(buf, "%d\n", dev->numa_node); return sprintf(buf, "%d\n", dev->numa_node);
} }
static DEVICE_ATTR_RO(numa_node); static DEVICE_ATTR_RW(numa_node);
#endif #endif
static ssize_t dma_mask_bits_show(struct device *dev, static ssize_t dma_mask_bits_show(struct device *dev,
......
...@@ -1012,11 +1012,7 @@ int pci_save_state(struct pci_dev *dev) ...@@ -1012,11 +1012,7 @@ int pci_save_state(struct pci_dev *dev)
if (i != 0) if (i != 0)
return i; return i;
i = pci_save_vc_state(dev); return pci_save_vc_state(dev);
if (i != 0)
return i;
return 0;
} }
EXPORT_SYMBOL(pci_save_state); EXPORT_SYMBOL(pci_save_state);
...@@ -3144,12 +3140,10 @@ static int pcie_flr(struct pci_dev *dev, int probe) ...@@ -3144,12 +3140,10 @@ static int pcie_flr(struct pci_dev *dev, int probe)
return 0; return 0;
if (!pci_wait_for_pending_transaction(dev)) if (!pci_wait_for_pending_transaction(dev))
dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n"); dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
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);
return 0; return 0;
} }
...@@ -3174,16 +3168,12 @@ static int pci_af_flr(struct pci_dev *dev, int probe) ...@@ -3174,16 +3168,12 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
* is used, so we use the conrol offset rather than status and shift * is used, so we use the conrol offset rather than status and shift
* the test bit to match. * the test bit to match.
*/ */
if (pci_wait_for_pending(dev, pos + PCI_AF_CTRL, if (!pci_wait_for_pending(dev, pos + PCI_AF_CTRL,
PCI_AF_STATUS_TP << 8)) PCI_AF_STATUS_TP << 8))
goto clear; dev_err(&dev->dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n");
dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
clear:
pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
msleep(100); msleep(100);
return 0; return 0;
} }
...@@ -4180,7 +4170,8 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) ...@@ -4180,7 +4170,8 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
return dev->rom_base_reg; return dev->rom_base_reg;
} else if (resno < PCI_BRIDGE_RESOURCES) { } else if (resno < PCI_BRIDGE_RESOURCES) {
/* device specific resource */ /* device specific resource */
reg = pci_iov_resource_bar(dev, resno, type); *type = pci_bar_unknown;
reg = pci_iov_resource_bar(dev, resno);
if (reg) if (reg)
return reg; return reg;
} }
......
...@@ -253,8 +253,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev) ...@@ -253,8 +253,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev)
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
int pci_iov_init(struct pci_dev *dev); int pci_iov_init(struct pci_dev *dev);
void pci_iov_release(struct pci_dev *dev); void pci_iov_release(struct pci_dev *dev);
int pci_iov_resource_bar(struct pci_dev *dev, int resno, int pci_iov_resource_bar(struct pci_dev *dev, int resno);
enum pci_bar_type *type);
resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno); resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
void pci_restore_iov_state(struct pci_dev *dev); void pci_restore_iov_state(struct pci_dev *dev);
int pci_iov_bus_range(struct pci_bus *bus); int pci_iov_bus_range(struct pci_bus *bus);
...@@ -268,8 +267,7 @@ static inline void pci_iov_release(struct pci_dev *dev) ...@@ -268,8 +267,7 @@ static inline void pci_iov_release(struct pci_dev *dev)
{ {
} }
static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno, static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno)
enum pci_bar_type *type)
{ {
return 0; return 0;
} }
......
...@@ -87,8 +87,7 @@ static void release_pcibus_dev(struct device *dev) ...@@ -87,8 +87,7 @@ static void release_pcibus_dev(struct device *dev)
{ {
struct pci_bus *pci_bus = to_pci_bus(dev); struct pci_bus *pci_bus = to_pci_bus(dev);
if (pci_bus->bridge) put_device(pci_bus->bridge);
put_device(pci_bus->bridge);
pci_bus_remove_resources(pci_bus); pci_bus_remove_resources(pci_bus);
pci_release_bus_of_node(pci_bus); pci_release_bus_of_node(pci_bus);
kfree(pci_bus); kfree(pci_bus);
...@@ -175,7 +174,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -175,7 +174,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
u64 l64, sz64, mask64; u64 l64, sz64, mask64;
u16 orig_cmd; u16 orig_cmd;
struct pci_bus_region region, inverted_region; struct pci_bus_region region, inverted_region;
bool bar_too_big = false, bar_too_high = false, bar_invalid = false;
mask = type ? PCI_ROM_ADDRESS_MASK : ~0; mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
...@@ -201,8 +199,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -201,8 +199,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
* memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit
* 1 must be clear. * 1 must be clear.
*/ */
if (!sz || sz == 0xffffffff) if (sz == 0xffffffff)
goto fail; sz = 0;
/* /*
* I don't know how l can have all bits set. Copied from old code. * I don't know how l can have all bits set. Copied from old code.
...@@ -215,23 +213,22 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -215,23 +213,22 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags = decode_bar(dev, l); res->flags = decode_bar(dev, l);
res->flags |= IORESOURCE_SIZEALIGN; res->flags |= IORESOURCE_SIZEALIGN;
if (res->flags & IORESOURCE_IO) { if (res->flags & IORESOURCE_IO) {
l &= PCI_BASE_ADDRESS_IO_MASK; l64 = l & PCI_BASE_ADDRESS_IO_MASK;
mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; sz64 = sz & PCI_BASE_ADDRESS_IO_MASK;
mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT;
} else { } else {
l &= PCI_BASE_ADDRESS_MEM_MASK; l64 = l & PCI_BASE_ADDRESS_MEM_MASK;
mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK;
mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
} }
} else { } else {
res->flags |= (l & IORESOURCE_ROM_ENABLE); res->flags |= (l & IORESOURCE_ROM_ENABLE);
l &= PCI_ROM_ADDRESS_MASK; l64 = l & PCI_ROM_ADDRESS_MASK;
mask = (u32)PCI_ROM_ADDRESS_MASK; sz64 = sz & PCI_ROM_ADDRESS_MASK;
mask64 = (u32)PCI_ROM_ADDRESS_MASK;
} }
if (res->flags & IORESOURCE_MEM_64) { if (res->flags & IORESOURCE_MEM_64) {
l64 = l;
sz64 = sz;
mask64 = mask | (u64)~0 << 32;
pci_read_config_dword(dev, pos + 4, &l); pci_read_config_dword(dev, pos + 4, &l);
pci_write_config_dword(dev, pos + 4, ~0); pci_write_config_dword(dev, pos + 4, ~0);
pci_read_config_dword(dev, pos + 4, &sz); pci_read_config_dword(dev, pos + 4, &sz);
...@@ -239,18 +236,30 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -239,18 +236,30 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
l64 |= ((u64)l << 32); l64 |= ((u64)l << 32);
sz64 |= ((u64)sz << 32); sz64 |= ((u64)sz << 32);
mask64 |= ((u64)~0 << 32);
}
sz64 = pci_size(l64, sz64, mask64); if (!dev->mmio_always_on && (orig_cmd & PCI_COMMAND_DECODE_ENABLE))
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
if (!sz64) if (!sz64)
goto fail; goto fail;
sz64 = pci_size(l64, sz64, mask64);
if (!sz64) {
dev_info(&dev->dev, FW_BUG "reg 0x%x: invalid BAR (can't size)\n",
pos);
goto fail;
}
if (res->flags & IORESOURCE_MEM_64) {
if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) &&
sz64 > 0x100000000ULL) { sz64 > 0x100000000ULL) {
res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
res->start = 0; res->start = 0;
res->end = 0; res->end = 0;
bar_too_big = true; dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
pos, (unsigned long long)sz64);
goto out; goto out;
} }
...@@ -259,22 +268,15 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -259,22 +268,15 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags |= IORESOURCE_UNSET; res->flags |= IORESOURCE_UNSET;
res->start = 0; res->start = 0;
res->end = sz64; res->end = sz64;
bar_too_high = true; dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4GB (bus address %#010llx)\n",
pos, (unsigned long long)l64);
goto out; goto out;
} else {
region.start = l64;
region.end = l64 + sz64;
} }
} else {
sz = pci_size(l, sz, mask);
if (!sz)
goto fail;
region.start = l;
region.end = l + sz;
} }
region.start = l64;
region.end = l64 + sz64;
pcibios_bus_to_resource(dev->bus, res, &region); pcibios_bus_to_resource(dev->bus, res, &region);
pcibios_resource_to_bus(dev->bus, &inverted_region, res); pcibios_resource_to_bus(dev->bus, &inverted_region, res);
...@@ -293,7 +295,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -293,7 +295,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags |= IORESOURCE_UNSET; res->flags |= IORESOURCE_UNSET;
res->start = 0; res->start = 0;
res->end = region.end - region.start; res->end = region.end - region.start;
bar_invalid = true; dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n",
pos, (unsigned long long)region.start);
} }
goto out; goto out;
...@@ -302,19 +305,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -302,19 +305,6 @@ 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 &&
(orig_cmd & PCI_COMMAND_DECODE_ENABLE))
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
if (bar_too_big)
dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
pos, (unsigned long long) sz64);
if (bar_too_high)
dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4G (bus address %#010llx)\n",
pos, (unsigned long long) l64);
if (bar_invalid)
dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n",
pos, (unsigned long long) region.start);
if (res->flags) if (res->flags)
dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
......
...@@ -271,8 +271,7 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, ...@@ -271,8 +271,7 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
match_pci_dev_by_id); match_pci_dev_by_id);
if (dev) if (dev)
pdev = to_pci_dev(dev); pdev = to_pci_dev(dev);
if (from) pci_dev_put(from);
pci_dev_put(from);
return pdev; return pdev;
} }
......
...@@ -596,8 +596,7 @@ static pci_ers_result_t pcifront_common_process(int cmd, ...@@ -596,8 +596,7 @@ static pci_ers_result_t pcifront_common_process(int cmd,
pcidev = pci_get_bus_and_slot(bus, devfn); pcidev = pci_get_bus_and_slot(bus, devfn);
if (!pcidev || !pcidev->driver) { if (!pcidev || !pcidev->driver) {
dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n");
if (pcidev) pci_dev_put(pcidev);
pci_dev_put(pcidev);
return result; return result;
} }
pdrv = pcidev->driver; pdrv = pcidev->driver;
...@@ -866,6 +865,11 @@ static int pcifront_try_connect(struct pcifront_device *pdev) ...@@ -866,6 +865,11 @@ static int pcifront_try_connect(struct pcifront_device *pdev)
xenbus_dev_error(pdev->xdev, err, xenbus_dev_error(pdev->xdev, err,
"No PCI Roots found, trying 0000:00"); "No PCI Roots found, trying 0000:00");
err = pcifront_scan_root(pdev, 0, 0); err = pcifront_scan_root(pdev, 0, 0);
if (err) {
xenbus_dev_fatal(pdev->xdev, err,
"Error scanning PCI root 0000:00");
goto out;
}
num_roots = 0; num_roots = 0;
} else if (err != 1) { } else if (err != 1) {
if (err == 0) if (err == 0)
...@@ -947,6 +951,11 @@ static int pcifront_attach_devices(struct pcifront_device *pdev) ...@@ -947,6 +951,11 @@ static int pcifront_attach_devices(struct pcifront_device *pdev)
xenbus_dev_error(pdev->xdev, err, xenbus_dev_error(pdev->xdev, err,
"No PCI Roots found, trying 0000:00"); "No PCI Roots found, trying 0000:00");
err = pcifront_rescan_root(pdev, 0, 0); err = pcifront_rescan_root(pdev, 0, 0);
if (err) {
xenbus_dev_fatal(pdev->xdev, err,
"Error scanning PCI root 0000:00");
goto out;
}
num_roots = 0; num_roots = 0;
} else if (err != 1) { } else if (err != 1) {
if (err == 0) if (err == 0)
......
...@@ -109,7 +109,6 @@ struct hotplug_slot { ...@@ -109,7 +109,6 @@ struct hotplug_slot {
struct list_head slot_list; struct list_head slot_list;
struct pci_slot *pci_slot; struct pci_slot *pci_slot;
}; };
#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj)
static inline const char *hotplug_slot_name(const struct hotplug_slot *slot) static inline const char *hotplug_slot_name(const struct hotplug_slot *slot)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment