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

Pull PCI changes from Bjorn Helgaas:
 "Enumeration
    - Move domain assignment from arm64 to generic code (Lorenzo Pieralisi)
    - ARM: Remove artificial dependency on pci_sys_data domain (Lorenzo Pieralisi)
    - ARM: Move to generic PCI domains (Lorenzo Pieralisi)
    - Generate uppercase hex for modalias var in uevent (Ricardo Ribalda Delgado)
    - Add and use generic config accessors on ARM, PowerPC (Rob Herring)

  Resource management
    - Free resources on failure in of_pci_get_host_bridge_resources() (Lorenzo Pieralisi)
    - Fix infinite loop with ROM image of size 0 (Michel Dänzer)

  PCI device hotplug
    - Handle surprise add even if surprise removal isn't supported (Bjorn Helgaas)

  Virtualization
    - Mark AMD/ATI VGA devices that don't reset on D3hot->D0 transition (Alex Williamson)
    - Add DMA alias quirk for Adaptec 3405 (Alex Williamson)
    - Add Wellsburg (X99) to Intel PCH root port ACS quirk (Alex Williamson)
    - Add ACS quirk for Emulex NICs (Vasundhara Volam)

  MSI
    - Fail MSI-X mappings if there's no space assigned to MSI-X BAR (Yijing Wang)

  Freescale Layerscape host bridge driver
    - Fix platform_no_drv_owner.cocci warnings (Julia Lawall)

  NVIDIA Tegra host bridge driver
    - Remove unnecessary tegra_pcie_fixup_bridge() (Lucas Stach)

  Renesas R-Car host bridge driver
    - Fix error handling of irq_of_parse_and_map() (Dmitry Torokhov)

  TI Keystone host bridge driver
    - Fix error handling of irq_of_parse_and_map() (Dmitry Torokhov)
    - Fix misspelling of current function in debug output (Julia Lawall)

  Xilinx AXI host bridge driver
    - Fix harmless format string warning (Arnd Bergmann)

  Miscellaneous
    - Use standard parsing functions for ASPM sysfs setters (Chris J Arges)
    - Add pci_device_to_OF_node() stub for !CONFIG_OF (Kevin Hao)
    - Delete unnecessary NULL pointer checks (Markus Elfring)
    - Add and use defines for PCIe Max_Read_Request_Size (Rafał Miłecki)
    - Include clk.h instead of clk-private.h (Stephen Boyd)"

* tag 'pci-v3.20-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (48 commits)
  PCI: Add pci_device_to_OF_node() stub for !CONFIG_OF
  PCI: xilinx: Convert to use generic config accessors
  PCI: xgene: Convert to use generic config accessors
  PCI: tegra: Convert to use generic config accessors
  PCI: rcar: Convert to use generic config accessors
  PCI: generic: Convert to use generic config accessors
  powerpc/powermac: Convert PCI to use generic config accessors
  powerpc/fsl_pci: Convert PCI to use generic config accessors
  ARM: ks8695: Convert PCI to use generic config accessors
  ARM: sa1100: Convert PCI to use generic config accessors
  ARM: integrator: Convert PCI to use generic config accessors
  PCI: versatile: Add DT-based ARM Versatile PB PCIe host driver
  ARM: dts: versatile: add PCI controller binding
  of/pci: Free resources on failure in of_pci_get_host_bridge_resources()
  PCI: versatile: Add DT docs for ARM Versatile PB PCIe driver
  PCI: Fail MSI-X mappings if there's no space assigned to MSI-X BAR
  r8169: use PCI define for Max_Read_Request_Size
  [SCSI] esas2r: use PCI define for Max_Read_Request_Size
  tile: use PCI define for Max_Read_Request_Size
  rapidio/tsi721: use PCI define for Max_Read_Request_Size
  ...
This commit is contained in:
Linus Torvalds
2015-02-10 14:31:28 -08:00
51 changed files with 744 additions and 978 deletions

View File

@@ -67,6 +67,93 @@ EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);
int pci_generic_config_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
void __iomem *addr;
addr = bus->ops->map_bus(bus, devfn, where);
if (!addr) {
*val = ~0;
return PCIBIOS_DEVICE_NOT_FOUND;
}
if (size == 1)
*val = readb(addr);
else if (size == 2)
*val = readw(addr);
else
*val = readl(addr);
return PCIBIOS_SUCCESSFUL;
}
EXPORT_SYMBOL_GPL(pci_generic_config_read);
int pci_generic_config_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
void __iomem *addr;
addr = bus->ops->map_bus(bus, devfn, where);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
if (size == 1)
writeb(val, addr);
else if (size == 2)
writew(val, addr);
else
writel(val, addr);
return PCIBIOS_SUCCESSFUL;
}
EXPORT_SYMBOL_GPL(pci_generic_config_write);
int pci_generic_config_read32(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
void __iomem *addr;
addr = bus->ops->map_bus(bus, devfn, where & ~0x3);
if (!addr) {
*val = ~0;
return PCIBIOS_DEVICE_NOT_FOUND;
}
*val = readl(addr);
if (size <= 2)
*val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
return PCIBIOS_SUCCESSFUL;
}
EXPORT_SYMBOL_GPL(pci_generic_config_read32);
int pci_generic_config_write32(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
void __iomem *addr;
u32 mask, tmp;
addr = bus->ops->map_bus(bus, devfn, where & ~0x3);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
if (size == 4) {
writel(val, addr);
return PCIBIOS_SUCCESSFUL;
} else {
mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));
}
tmp = readl(addr) & mask;
tmp |= val << ((where & 0x3) * 8);
writel(tmp, addr);
return PCIBIOS_SUCCESSFUL;
}
EXPORT_SYMBOL_GPL(pci_generic_config_write32);
/**
* pci_bus_set_ops - Set raw operations of pci bus
* @bus: pci bus struct

View File

@@ -102,4 +102,8 @@ config PCI_LAYERSCAPE
help
Say Y here if you want PCIe controller support on Layerscape SoCs.
config PCI_VERSATILE
bool "ARM Versatile PB PCI controller"
depends on ARCH_VERSATILE
endmenu

View File

@@ -12,3 +12,4 @@ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o

View File

@@ -76,55 +76,9 @@ static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = {
.map_bus = gen_pci_map_cfg_bus_ecam,
};
static int gen_pci_config_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
void __iomem *addr;
struct pci_sys_data *sys = bus->sysdata;
struct gen_pci *pci = sys->private_data;
addr = pci->cfg.ops->map_bus(bus, devfn, where);
switch (size) {
case 1:
*val = readb(addr);
break;
case 2:
*val = readw(addr);
break;
default:
*val = readl(addr);
}
return PCIBIOS_SUCCESSFUL;
}
static int gen_pci_config_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
void __iomem *addr;
struct pci_sys_data *sys = bus->sysdata;
struct gen_pci *pci = sys->private_data;
addr = pci->cfg.ops->map_bus(bus, devfn, where);
switch (size) {
case 1:
writeb(val, addr);
break;
case 2:
writew(val, addr);
break;
default:
writel(val, addr);
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops gen_pci_ops = {
.read = gen_pci_config_read,
.write = gen_pci_config_write,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
};
static const struct of_device_id gen_pci_of_match[] = {
@@ -287,6 +241,7 @@ static int gen_pci_probe(struct platform_device *pdev)
of_id = of_match_node(gen_pci_of_match, np);
pci->cfg.ops = of_id->data;
gen_pci_ops.map_bus = pci->cfg.ops->map_bus;
pci->host.dev.parent = dev;
INIT_LIST_HEAD(&pci->host.windows);
INIT_LIST_HEAD(&pci->resources);

View File

@@ -119,7 +119,7 @@ static void ks_pcie_msi_irq_handler(unsigned int irq, struct irq_desc *desc)
struct pcie_port *pp = &ks_pcie->pp;
struct irq_chip *chip = irq_desc_get_chip(desc);
dev_dbg(pp->dev, "ks_pci_msi_irq_handler, irq %d\n", irq);
dev_dbg(pp->dev, "%s, irq %d\n", __func__, irq);
/*
* The chained irq handler installation would have replaced normal
@@ -197,7 +197,7 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie,
*/
for (temp = 0; temp < max_host_irqs; temp++) {
host_irqs[temp] = irq_of_parse_and_map(*np_temp, temp);
if (host_irqs[temp] < 0)
if (!host_irqs[temp])
break;
}
if (temp) {

View File

@@ -167,7 +167,6 @@ 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,
},
};

View File

@@ -101,9 +101,7 @@ struct mvebu_pcie {
struct mvebu_pcie_port *ports;
struct msi_controller *msi;
struct resource io;
char io_name[30];
struct resource realio;
char mem_name[30];
struct resource mem;
struct resource busn;
int nports;
@@ -723,18 +721,9 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
{
struct mvebu_pcie *pcie = sys_to_pcie(sys);
int i;
int domain = 0;
#ifdef CONFIG_PCI_DOMAINS
domain = sys->domain;
#endif
snprintf(pcie->mem_name, sizeof(pcie->mem_name), "PCI MEM %04x",
domain);
pcie->mem.name = pcie->mem_name;
snprintf(pcie->io_name, sizeof(pcie->io_name), "PCI I/O %04x", domain);
pcie->realio.name = pcie->io_name;
pcie->mem.name = "PCI MEM";
pcie->realio.name = "PCI I/O";
if (request_resource(&iomem_resource, &pcie->mem))
return 0;

View File

@@ -131,52 +131,6 @@ static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn,
return priv->reg + (slot >> 1) * 0x100 + where;
}
static int rcar_pci_read_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
void __iomem *reg = rcar_pci_cfg_base(bus, devfn, where);
if (!reg)
return PCIBIOS_DEVICE_NOT_FOUND;
switch (size) {
case 1:
*val = ioread8(reg);
break;
case 2:
*val = ioread16(reg);
break;
default:
*val = ioread32(reg);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int rcar_pci_write_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
void __iomem *reg = rcar_pci_cfg_base(bus, devfn, where);
if (!reg)
return PCIBIOS_DEVICE_NOT_FOUND;
switch (size) {
case 1:
iowrite8(val, reg);
break;
case 2:
iowrite16(val, reg);
break;
default:
iowrite32(val, reg);
break;
}
return PCIBIOS_SUCCESSFUL;
}
/* PCI interrupt mapping */
static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
@@ -325,8 +279,9 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
}
static struct pci_ops rcar_pci_ops = {
.read = rcar_pci_read_config,
.write = rcar_pci_write_config,
.map_bus = rcar_pci_cfg_base,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
};
static int rcar_pci_probe(struct platform_device *pdev)

View File

@@ -480,59 +480,10 @@ static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus,
return addr;
}
static int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *value)
{
void __iomem *addr;
addr = tegra_pcie_conf_address(bus, devfn, where);
if (!addr) {
*value = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
*value = readl(addr);
if (size == 1)
*value = (*value >> (8 * (where & 3))) & 0xff;
else if (size == 2)
*value = (*value >> (8 * (where & 3))) & 0xffff;
return PCIBIOS_SUCCESSFUL;
}
static int tegra_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 value)
{
void __iomem *addr;
u32 mask, tmp;
addr = tegra_pcie_conf_address(bus, devfn, where);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
if (size == 4) {
writel(value, addr);
return PCIBIOS_SUCCESSFUL;
}
if (size == 2)
mask = ~(0xffff << ((where & 0x3) * 8));
else if (size == 1)
mask = ~(0xff << ((where & 0x3) * 8));
else
return PCIBIOS_BAD_REGISTER_NUMBER;
tmp = readl(addr) & mask;
tmp |= value << ((where & 0x3) * 8);
writel(tmp, addr);
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops tegra_pcie_ops = {
.read = tegra_pcie_read_conf,
.write = tegra_pcie_write_conf,
.map_bus = tegra_pcie_conf_address,
.read = pci_generic_config_read32,
.write = pci_generic_config_write32,
};
static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port)
@@ -625,19 +576,6 @@ static void tegra_pcie_port_free(struct tegra_pcie_port *port)
devm_kfree(pcie->dev, port);
}
static void tegra_pcie_fixup_bridge(struct pci_dev *dev)
{
u16 reg;
if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
pci_read_config_word(dev, PCI_COMMAND, &reg);
reg |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
pci_write_config_word(dev, PCI_COMMAND, reg);
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_fixup_bridge);
/* Tegra PCIE root complex wrongly reports device class */
static void tegra_pcie_fixup_class(struct pci_dev *dev)
{

View File

@@ -0,0 +1,237 @@
/*
* Copyright 2004 Koninklijke Philips Electronics NV
*
* Conversion to platform driver and DT:
* Copyright 2014 Linaro Ltd.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 14/04/2005 Initial version, colin.king@philips.com
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
static void __iomem *versatile_pci_base;
static void __iomem *versatile_cfg_base[2];
#define PCI_IMAP(m) (versatile_pci_base + ((m) * 4))
#define PCI_SMAP(m) (versatile_pci_base + 0x14 + ((m) * 4))
#define PCI_SELFID (versatile_pci_base + 0xc)
#define VP_PCI_DEVICE_ID 0x030010ee
#define VP_PCI_CLASS_ID 0x0b400000
static u32 pci_slot_ignore;
static int __init versatile_pci_slot_ignore(char *str)
{
int retval;
int slot;
while ((retval = get_option(&str, &slot))) {
if ((slot < 0) || (slot > 31))
pr_err("Illegal slot value: %d\n", slot);
else
pci_slot_ignore |= (1 << slot);
}
return 1;
}
__setup("pci_slot_ignore=", versatile_pci_slot_ignore);
static void __iomem *versatile_map_bus(struct pci_bus *bus,
unsigned int devfn, int offset)
{
unsigned int busnr = bus->number;
if (pci_slot_ignore & (1 << PCI_SLOT(devfn)))
return NULL;
return versatile_cfg_base[1] + ((busnr << 16) | (devfn << 8) | offset);
}
static struct pci_ops pci_versatile_ops = {
.map_bus = versatile_map_bus,
.read = pci_generic_config_read32,
.write = pci_generic_config_write,
};
static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
struct list_head *res)
{
int err, mem = 1, res_valid = 0;
struct device_node *np = dev->of_node;
resource_size_t iobase;
struct pci_host_bridge_window *win;
err = of_pci_get_host_bridge_resources(np, 0, 0xff, res, &iobase);
if (err)
return err;
list_for_each_entry(win, res, list) {
struct resource *parent, *res = win->res;
switch (resource_type(res)) {
case IORESOURCE_IO:
parent = &ioport_resource;
err = pci_remap_iospace(res, iobase);
if (err) {
dev_warn(dev, "error %d: failed to map resource %pR\n",
err, res);
continue;
}
break;
case IORESOURCE_MEM:
parent = &iomem_resource;
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
writel(res->start >> 28, PCI_IMAP(mem));
writel(PHYS_OFFSET >> 28, PCI_SMAP(mem));
mem++;
break;
case IORESOURCE_BUS:
default:
continue;
}
err = devm_request_resource(dev, parent, res);
if (err)
goto out_release_res;
}
if (!res_valid) {
dev_err(dev, "non-prefetchable memory resource required\n");
err = -EINVAL;
goto out_release_res;
}
return 0;
out_release_res:
pci_free_resource_list(res);
return err;
}
/* Unused, temporary to satisfy ARM arch code */
struct pci_sys_data sys;
static int versatile_pci_probe(struct platform_device *pdev)
{
struct resource *res;
int ret, i, myslot = -1;
u32 val;
void __iomem *local_pci_cfg_base;
struct pci_bus *bus;
LIST_HEAD(pci_res);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
versatile_pci_base = devm_ioremap_resource(&pdev->dev, res);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res)
return -ENODEV;
versatile_cfg_base[0] = devm_ioremap_resource(&pdev->dev, res);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
if (!res)
return -ENODEV;
versatile_cfg_base[1] = devm_ioremap_resource(&pdev->dev, res);
ret = versatile_pci_parse_request_of_pci_ranges(&pdev->dev, &pci_res);
if (ret)
return ret;
/*
* We need to discover the PCI core first to configure itself
* before the main PCI probing is performed
*/
for (i = 0; i < 32; i++) {
if ((readl(versatile_cfg_base[0] + (i << 11) + PCI_VENDOR_ID) == VP_PCI_DEVICE_ID) &&
(readl(versatile_cfg_base[0] + (i << 11) + PCI_CLASS_REVISION) == VP_PCI_CLASS_ID)) {
myslot = i;
break;
}
}
if (myslot == -1) {
dev_err(&pdev->dev, "Cannot find PCI core!\n");
return -EIO;
}
/*
* Do not to map Versatile FPGA PCI device into memory space
*/
pci_slot_ignore |= (1 << myslot);
dev_info(&pdev->dev, "PCI core found (slot %d)\n", myslot);
writel(myslot, PCI_SELFID);
local_pci_cfg_base = versatile_cfg_base[1] + (myslot << 11);
val = readl(local_pci_cfg_base + PCI_COMMAND);
val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
writel(val, local_pci_cfg_base + PCI_COMMAND);
/*
* Configure the PCI inbound memory windows to be 1:1 mapped to SDRAM
*/
writel(PHYS_OFFSET, local_pci_cfg_base + PCI_BASE_ADDRESS_0);
writel(PHYS_OFFSET, local_pci_cfg_base + PCI_BASE_ADDRESS_1);
writel(PHYS_OFFSET, local_pci_cfg_base + PCI_BASE_ADDRESS_2);
/*
* For many years the kernel and QEMU were symbiotically buggy
* in that they both assumed the same broken IRQ mapping.
* QEMU therefore attempts to auto-detect old broken kernels
* so that they still work on newer QEMU as they did on old
* QEMU. Since we now use the correct (ie matching-hardware)
* IRQ mapping we write a definitely different value to a
* PCI_INTERRUPT_LINE register to tell QEMU that we expect
* real hardware behaviour and it need not be backwards
* compatible for us. This write is harmless on real hardware.
*/
writel(0, versatile_cfg_base[0] + PCI_INTERRUPT_LINE);
pci_add_flags(PCI_ENABLE_PROC_DOMAINS);
pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC);
bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, &sys, &pci_res);
if (!bus)
return -ENOMEM;
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
pci_assign_unassigned_bus_resources(bus);
return 0;
}
static const struct of_device_id versatile_pci_of_match[] = {
{ .compatible = "arm,versatile-pci", },
{ },
};
MODULE_DEVICE_TABLE(of, versatile_pci_of_match);
static struct platform_driver versatile_pci_driver = {
.driver = {
.name = "versatile-pci",
.of_match_table = versatile_pci_of_match,
},
.probe = versatile_pci_probe,
};
module_platform_driver(versatile_pci_driver);
MODULE_DESCRIPTION("Versatile PCI driver");
MODULE_LICENSE("GPL v2");

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
*/
#include <linux/clk-private.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/jiffies.h>
@@ -74,92 +74,6 @@ static inline u32 pcie_bar_low_val(u32 addr, u32 flags)
return (addr & PCI_BASE_ADDRESS_MEM_MASK) | flags;
}
/* PCIe Configuration Out/In */
static inline void xgene_pcie_cfg_out32(void __iomem *addr, int offset, u32 val)
{
writel(val, addr + offset);
}
static inline void xgene_pcie_cfg_out16(void __iomem *addr, int offset, u16 val)
{
u32 val32 = readl(addr + (offset & ~0x3));
switch (offset & 0x3) {
case 2:
val32 &= ~0xFFFF0000;
val32 |= (u32)val << 16;
break;
case 0:
default:
val32 &= ~0xFFFF;
val32 |= val;
break;
}
writel(val32, addr + (offset & ~0x3));
}
static inline void xgene_pcie_cfg_out8(void __iomem *addr, int offset, u8 val)
{
u32 val32 = readl(addr + (offset & ~0x3));
switch (offset & 0x3) {
case 0:
val32 &= ~0xFF;
val32 |= val;
break;
case 1:
val32 &= ~0xFF00;
val32 |= (u32)val << 8;
break;
case 2:
val32 &= ~0xFF0000;
val32 |= (u32)val << 16;
break;
case 3:
default:
val32 &= ~0xFF000000;
val32 |= (u32)val << 24;
break;
}
writel(val32, addr + (offset & ~0x3));
}
static inline void xgene_pcie_cfg_in32(void __iomem *addr, int offset, u32 *val)
{
*val = readl(addr + offset);
}
static inline void xgene_pcie_cfg_in16(void __iomem *addr, int offset, u32 *val)
{
*val = readl(addr + (offset & ~0x3));
switch (offset & 0x3) {
case 2:
*val >>= 16;
break;
}
*val &= 0xFFFF;
}
static inline void xgene_pcie_cfg_in8(void __iomem *addr, int offset, u32 *val)
{
*val = readl(addr + (offset & ~0x3));
switch (offset & 0x3) {
case 3:
*val = *val >> 24;
break;
case 2:
*val = *val >> 16;
break;
case 1:
*val = *val >> 8;
break;
}
*val &= 0xFF;
}
/*
* When the address bit [17:16] is 2'b01, the Configuration access will be
* treated as Type 1 and it will be forwarded to external PCIe device.
@@ -213,69 +127,23 @@ static bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset)
return false;
}
static int xgene_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
static int xgene_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
int offset)
{
struct xgene_pcie_port *port = bus->sysdata;
void __iomem *addr;
if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
return PCIBIOS_DEVICE_NOT_FOUND;
if (xgene_pcie_hide_rc_bars(bus, offset)) {
*val = 0;
return PCIBIOS_SUCCESSFUL;
}
if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up ||
xgene_pcie_hide_rc_bars(bus, offset))
return NULL;
xgene_pcie_set_rtdid_reg(bus, devfn);
addr = xgene_pcie_get_cfg_base(bus);
switch (len) {
case 1:
xgene_pcie_cfg_in8(addr, offset, val);
break;
case 2:
xgene_pcie_cfg_in16(addr, offset, val);
break;
default:
xgene_pcie_cfg_in32(addr, offset, val);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int xgene_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 val)
{
struct xgene_pcie_port *port = bus->sysdata;
void __iomem *addr;
if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
return PCIBIOS_DEVICE_NOT_FOUND;
if (xgene_pcie_hide_rc_bars(bus, offset))
return PCIBIOS_SUCCESSFUL;
xgene_pcie_set_rtdid_reg(bus, devfn);
addr = xgene_pcie_get_cfg_base(bus);
switch (len) {
case 1:
xgene_pcie_cfg_out8(addr, offset, (u8)val);
break;
case 2:
xgene_pcie_cfg_out16(addr, offset, (u16)val);
break;
default:
xgene_pcie_cfg_out32(addr, offset, val);
break;
}
return PCIBIOS_SUCCESSFUL;
return xgene_pcie_get_cfg_base(bus);
}
static struct pci_ops xgene_pcie_ops = {
.read = xgene_pcie_read_config,
.write = xgene_pcie_write_config
.map_bus = xgene_pcie_map_bus,
.read = pci_generic_config_read32,
.write = pci_generic_config_write32,
};
static u64 xgene_pcie_set_ib_mask(void __iomem *csr_base, u32 addr,

View File

@@ -511,9 +511,6 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
dw_pci.private_data = (void **)&pp;
pci_common_init_dev(pp->dev, &dw_pci);
#ifdef CONFIG_PCI_DOMAINS
dw_pci.domain++;
#endif
return 0;
}

View File

@@ -397,9 +397,6 @@ static void rcar_pcie_enable(struct rcar_pcie *pcie)
#endif
pci_common_init_dev(&pdev->dev, &rcar_pci);
#ifdef CONFIG_PCI_DOMAINS
rcar_pci.domain++;
#endif
}
static int phy_wait_for_ack(struct rcar_pcie *pcie)
@@ -757,7 +754,7 @@ static int rcar_pcie_get_resources(struct platform_device *pdev,
goto err_map_reg;
i = irq_of_parse_and_map(pdev->dev.of_node, 0);
if (i < 0) {
if (!i) {
dev_err(pcie->dev, "cannot get platform resources for msi interrupt\n");
err = -ENOENT;
goto err_map_reg;
@@ -765,7 +762,7 @@ static int rcar_pcie_get_resources(struct platform_device *pdev,
pcie->msi.irq1 = i;
i = irq_of_parse_and_map(pdev->dev.of_node, 1);
if (i < 0) {
if (!i) {
dev_err(pcie->dev, "cannot get platform resources for msi interrupt\n");
err = -ENOENT;
goto err_map_reg;

View File

@@ -148,10 +148,10 @@ static inline bool xilinx_pcie_link_is_up(struct xilinx_pcie_port *port)
*/
static void xilinx_pcie_clear_err_interrupts(struct xilinx_pcie_port *port)
{
u32 val = pcie_read(port, XILINX_PCIE_REG_RPEFR);
unsigned long val = pcie_read(port, XILINX_PCIE_REG_RPEFR);
if (val & XILINX_PCIE_RPEFR_ERR_VALID) {
dev_dbg(port->dev, "Requester ID %d\n",
dev_dbg(port->dev, "Requester ID %lu\n",
val & XILINX_PCIE_RPEFR_REQ_ID);
pcie_write(port, XILINX_PCIE_RPEFR_ALL_MASK,
XILINX_PCIE_REG_RPEFR);
@@ -189,7 +189,7 @@ static bool xilinx_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
}
/**
* xilinx_pcie_config_base - Get configuration base
* xilinx_pcie_map_bus - Get configuration base
* @bus: PCI Bus structure
* @devfn: Device/function
* @where: Offset from base
@@ -197,96 +197,26 @@ static bool xilinx_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
* Return: Base address of the configuration space needed to be
* accessed.
*/
static void __iomem *xilinx_pcie_config_base(struct pci_bus *bus,
unsigned int devfn, int where)
static void __iomem *xilinx_pcie_map_bus(struct pci_bus *bus,
unsigned int devfn, int where)
{
struct xilinx_pcie_port *port = sys_to_pcie(bus->sysdata);
int relbus;
if (!xilinx_pcie_valid_device(bus, devfn))
return NULL;
relbus = (bus->number << ECAM_BUS_NUM_SHIFT) |
(devfn << ECAM_DEV_NUM_SHIFT);
return port->reg_base + relbus + where;
}
/**
* xilinx_pcie_read_config - Read configuration space
* @bus: PCI Bus structure
* @devfn: Device/function
* @where: Offset from base
* @size: Byte/word/dword
* @val: Value to be read
*
* Return: PCIBIOS_SUCCESSFUL on success
* PCIBIOS_DEVICE_NOT_FOUND on failure
*/
static int xilinx_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
void __iomem *addr;
if (!xilinx_pcie_valid_device(bus, devfn)) {
*val = 0xFFFFFFFF;
return PCIBIOS_DEVICE_NOT_FOUND;
}
addr = xilinx_pcie_config_base(bus, devfn, where);
switch (size) {
case 1:
*val = readb(addr);
break;
case 2:
*val = readw(addr);
break;
default:
*val = readl(addr);
break;
}
return PCIBIOS_SUCCESSFUL;
}
/**
* xilinx_pcie_write_config - Write configuration space
* @bus: PCI Bus structure
* @devfn: Device/function
* @where: Offset from base
* @size: Byte/word/dword
* @val: Value to be written to device
*
* Return: PCIBIOS_SUCCESSFUL on success
* PCIBIOS_DEVICE_NOT_FOUND on failure
*/
static int xilinx_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
void __iomem *addr;
if (!xilinx_pcie_valid_device(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
addr = xilinx_pcie_config_base(bus, devfn, where);
switch (size) {
case 1:
writeb(val, addr);
break;
case 2:
writew(val, addr);
break;
default:
writel(val, addr);
break;
}
return PCIBIOS_SUCCESSFUL;
}
/* PCIe operations */
static struct pci_ops xilinx_pcie_ops = {
.read = xilinx_pcie_read_config,
.write = xilinx_pcie_write_config,
.map_bus = xilinx_pcie_map_bus,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
};
/* MSI functions */

View File

@@ -214,8 +214,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot);
if (slot->dev)
pci_dev_put(slot->dev);
pci_dev_put(slot->dev);
kfree(slot);
}

View File

@@ -532,8 +532,6 @@ static void interrupt_event_handler(struct work_struct *work)
pciehp_green_led_off(p_slot);
break;
case INT_PRESENCE_ON:
if (!HP_SUPR_RM(ctrl))
break;
ctrl_dbg(ctrl, "Surprise Insertion\n");
handle_surprise_event(p_slot);
break;

View File

@@ -694,11 +694,16 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries)
{
resource_size_t phys_addr;
u32 table_offset;
unsigned long flags;
u8 bir;
pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE,
&table_offset);
bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR);
flags = pci_resource_flags(dev, bir);
if (!flags || (flags & IORESOURCE_UNSET))
return NULL;
table_offset &= PCI_MSIX_TABLE_OFFSET;
phys_addr = pci_resource_start(dev, bir) + table_offset;

View File

@@ -1383,7 +1383,7 @@ static int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
return -ENOMEM;
if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X",
pdev->vendor, pdev->device,
pdev->subsystem_vendor, pdev->subsystem_device,
(u8)(pdev->class >> 16), (u8)(pdev->class >> 8),

View File

@@ -10,6 +10,8 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/slab.h>
@@ -3197,7 +3199,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
{
u16 csr;
if (!dev->pm_cap)
if (!dev->pm_cap || dev->dev_flags & PCI_DEV_FLAGS_NO_PM_RESET)
return -ENOTTY;
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr);
@@ -4471,6 +4473,53 @@ int pci_get_new_domain_nr(void)
{
return atomic_inc_return(&__domain_nr);
}
#ifdef CONFIG_PCI_DOMAINS_GENERIC
void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
{
static int use_dt_domains = -1;
int domain = of_get_pci_domain_nr(parent->of_node);
/*
* Check DT domain and use_dt_domains values.
*
* If DT domain property is valid (domain >= 0) and
* use_dt_domains != 0, the DT assignment is valid since this means
* we have not previously allocated a domain number by using
* pci_get_new_domain_nr(); we should also update use_dt_domains to
* 1, to indicate that we have just assigned a domain number from
* DT.
*
* If DT domain property value is not valid (ie domain < 0), and we
* have not previously assigned a domain number from DT
* (use_dt_domains != 1) we should assign a domain number by
* using the:
*
* pci_get_new_domain_nr()
*
* API and update the use_dt_domains value to keep track of method we
* are using to assign domain numbers (use_dt_domains = 0).
*
* All other combinations imply we have a platform that is trying
* to mix domain numbers obtained from DT and pci_get_new_domain_nr(),
* which is a recipe for domain mishandling and it is prevented by
* invalidating the domain value (domain = -1) and printing a
* corresponding error.
*/
if (domain >= 0 && use_dt_domains) {
use_dt_domains = 1;
} else if (domain < 0 && use_dt_domains != 1) {
use_dt_domains = 0;
domain = pci_get_new_domain_nr();
} else {
dev_err(parent, "Node %s has inconsistent \"linux,pci-domain\" property in DT\n",
parent->of_node->full_name);
domain = -1;
}
bus->domain_nr = domain;
}
#endif
#endif
/**

View File

@@ -859,7 +859,10 @@ static ssize_t link_state_store(struct device *dev,
{
struct pci_dev *pdev = to_pci_dev(dev);
struct pcie_link_state *link, *root = pdev->link_state->root;
u32 val = buf[0] - '0', state = 0;
u32 val, state = 0;
if (kstrtouint(buf, 10, &val))
return -EINVAL;
if (aspm_disabled)
return -EPERM;
@@ -900,15 +903,14 @@ static ssize_t clk_ctl_store(struct device *dev,
size_t n)
{
struct pci_dev *pdev = to_pci_dev(dev);
int state;
bool state;
if (n < 1)
if (strtobool(buf, &state))
return -EINVAL;
state = buf[0]-'0';
down_read(&pci_bus_sem);
mutex_lock(&aspm_lock);
pcie_set_clkpm_nocheck(pdev->link_state, !!state);
pcie_set_clkpm_nocheck(pdev->link_state, state);
mutex_unlock(&aspm_lock);
up_read(&pci_bus_sem);

View File

@@ -3076,6 +3076,27 @@ static void quirk_no_bus_reset(struct pci_dev *dev)
*/
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
static void quirk_no_pm_reset(struct pci_dev *dev)
{
/*
* We can't do a bus reset on root bus devices, but an ineffective
* PM reset may be better than nothing.
*/
if (!pci_is_root_bus(dev->bus))
dev->dev_flags |= PCI_DEV_FLAGS_NO_PM_RESET;
}
/*
* Some AMD/ATI GPUS (HD8570 - Oland) report that a D3hot->D0 transition
* causes a reset (i.e., they advertise NoSoftRst-). This transition seems
* to have no effect on the device: it retains the framebuffer contents and
* monitor sync. Advertising this support makes other layers, like VFIO,
* assume pci_reset_function() is viable for this device. Mark it as
* unavailable to skip it when testing reset methods.
*/
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
PCI_CLASS_DISPLAY_VGA, 8, quirk_no_pm_reset);
#ifdef CONFIG_ACPI
/*
* Apple: Shutdown Cactus Ridge Thunderbolt controller.
@@ -3575,6 +3596,44 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JMICRON,
PCI_DEVICE_ID_JMICRON_JMB388_ESD,
quirk_dma_func1_alias);
/*
* Some devices DMA with the wrong devfn, not just the wrong function.
* quirk_fixed_dma_alias() uses this table to create fixed aliases, where
* the alias is "fixed" and independent of the device devfn.
*
* For example, the Adaptec 3405 is a PCIe card with an Intel 80333 I/O
* processor. To software, this appears as a PCIe-to-PCI/X bridge with a
* single device on the secondary bus. In reality, the single exposed
* device at 0e.0 is the Address Translation Unit (ATU) of the controller
* that provides a bridge to the internal bus of the I/O processor. The
* controller supports private devices, which can be hidden from PCI config
* space. In the case of the Adaptec 3405, a private device at 01.0
* appears to be the DMA engine, which therefore needs to become a DMA
* alias for the device.
*/
static const struct pci_device_id fixed_dma_alias_tbl[] = {
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x0285,
PCI_VENDOR_ID_ADAPTEC2, 0x02bb), /* Adaptec 3405 */
.driver_data = PCI_DEVFN(1, 0) },
{ 0 }
};
static void quirk_fixed_dma_alias(struct pci_dev *dev)
{
const struct pci_device_id *id;
id = pci_match_id(fixed_dma_alias_tbl, dev);
if (id) {
dev->dma_alias_devfn = id->driver_data;
dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n",
PCI_SLOT(dev->dma_alias_devfn),
PCI_FUNC(dev->dma_alias_devfn));
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ADAPTEC2, 0x0285, quirk_fixed_dma_alias);
/*
* A few PCIe-to-PCI bridges fail to expose a PCIe capability, resulting in
* using the wrong DMA alias for the device. Some of these devices can be
@@ -3678,6 +3737,9 @@ static const u16 pci_quirk_intel_pch_acs_ids[] = {
0x9c98, 0x9c99, 0x9c9a, 0x9c9b,
/* Patsburg (X79) PCH */
0x1d10, 0x1d12, 0x1d14, 0x1d16, 0x1d18, 0x1d1a, 0x1d1c, 0x1d1e,
/* Wellsburg (X99) PCH */
0x8d10, 0x8d11, 0x8d12, 0x8d13, 0x8d14, 0x8d15, 0x8d16, 0x8d17,
0x8d18, 0x8d19, 0x8d1a, 0x8d1b, 0x8d1c, 0x8d1d, 0x8d1e,
};
static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev)
@@ -3761,6 +3823,8 @@ static const struct pci_dev_acs_enabled {
{ PCI_VENDOR_ID_INTEL, 0x1551, pci_quirk_mf_endpoint_acs },
{ PCI_VENDOR_ID_INTEL, 0x1558, pci_quirk_mf_endpoint_acs },
{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
{ 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */
{ 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */
{ 0 }
};

View File

@@ -71,6 +71,7 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
{
void __iomem *image;
int last_image;
unsigned length;
image = rom;
do {
@@ -93,9 +94,9 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
if (readb(pds + 3) != 'R')
break;
last_image = readb(pds + 21) & 0x80;
/* this length is reliable */
image += readw(pds + 16) * 512;
} while (!last_image);
length = readw(pds + 16);
image += length * 512;
} while (length && !last_image);
/* never return a size larger than the PCI resource window */
/* there are known ROMs that get the size wrong */