diff options
Diffstat (limited to 'drivers')
53 files changed, 1018 insertions, 901 deletions
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index d19cd88ed2d3..0b122f903b8a 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -466,7 +466,8 @@ static void ali_init_chipset(struct pci_dev *pdev) tmp |= 0x01; /* CD_ROM enable for DMA */ pci_write_config_byte(pdev, 0x53, tmp); } - north = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); + north = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), 0, + PCI_DEVFN(0, 0)); if (north && north->vendor == PCI_VENDOR_ID_AL && ali_isa_bridge) { /* Configure the ALi bridge logic. For non ALi rely on BIOS. Set the south bridge enable bit */ diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 828b34445203..623205bcd04a 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c @@ -340,11 +340,17 @@ static int agp_nvidia_probe(struct pci_dev *pdev, u8 cap_ptr; nvidia_private.dev_1 = - pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); + pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), + (unsigned int)pdev->bus->number, + PCI_DEVFN(0, 1)); nvidia_private.dev_2 = - pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2)); + pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), + (unsigned int)pdev->bus->number, + PCI_DEVFN(0, 2)); nvidia_private.dev_3 = - pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0)); + pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), + (unsigned int)pdev->bus->number, + PCI_DEVFN(30, 0)); if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) { printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 " diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 03be4ac79b0d..4dbdd3bc9bb8 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -474,7 +474,8 @@ static int agp_serverworks_probe(struct pci_dev *pdev, } /* Everything is on func 1 here so we are hardcoding function one */ - bridge_dev = pci_get_bus_and_slot((unsigned int)pdev->bus->number, + bridge_dev = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), + (unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); if (!bridge_dev) { dev_info(&pdev->dev, "can't find secondary device\n"); diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index e22957665808..60a8f1363a10 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -669,10 +669,10 @@ edd_get_pci_dev(struct edd_device *edev) struct edd_info *info = edd_dev_get_info(edev); if (edd_dev_is_type(edev, "PCI") || edd_dev_is_type(edev, "XPRS")) { - return pci_get_bus_and_slot(info->params.interface_path.pci.bus, - PCI_DEVFN(info->params.interface_path.pci.slot, - info->params.interface_path.pci. - function)); + return pci_get_domain_bus_and_slot(0, + info->params.interface_path.pci.bus, + PCI_DEVFN(info->params.interface_path.pci.slot, + info->params.interface_path.pci.function)); } return NULL; } diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index 14042a64bdd5..6bc8e6640d71 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c @@ -719,8 +719,9 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header, * executes only devices which are in domain 0. Furthermore, the * iBFT spec doesn't have a domain id field :-( */ - pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8, - (nic->pci_bdf & 0xff)); + pci_dev = pci_get_domain_bus_and_slot(0, + (nic->pci_bdf & 0xff00) >> 8, + (nic->pci_bdf & 0xff)); if (pci_dev) { rc = sysfs_create_link(&boot_kobj->kobj, &pci_dev->dev.kobj, "device"); diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 8745971a7680..3a3bf752e03a 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -185,21 +185,22 @@ static int cdv_backlight_init(struct drm_device *dev) * for this and the MID devices. */ -static inline u32 CDV_MSG_READ32(uint port, uint offset) +static inline u32 CDV_MSG_READ32(int domain, uint port, uint offset) { int mcr = (0x10<<24) | (port << 16) | (offset << 8); uint32_t ret_val = 0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0); pci_write_config_dword(pci_root, 0xD0, mcr); pci_read_config_dword(pci_root, 0xD4, &ret_val); pci_dev_put(pci_root); return ret_val; } -static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value) +static inline void CDV_MSG_WRITE32(int domain, uint port, uint offset, + u32 value) { int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0); pci_write_config_dword(pci_root, 0xD4, value); pci_write_config_dword(pci_root, 0xD0, mcr); pci_dev_put(pci_root); @@ -216,11 +217,12 @@ static void cdv_init_pm(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; u32 pwr_cnt; + int domain = pci_domain_nr(dev->pdev->bus); int i; - dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, + dev_priv->apm_base = CDV_MSG_READ32(domain, PSB_PUNIT_PORT, PSB_APMBA) & 0xFFFF; - dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, + dev_priv->ospm_base = CDV_MSG_READ32(domain, PSB_PUNIT_PORT, PSB_OSPMBA) & 0xFFFF; /* Power status */ @@ -251,7 +253,7 @@ static void cdv_errata(struct drm_device *dev) * Bonus Launch to work around the issue, by degrading * performance. */ - CDV_MSG_WRITE32(3, 0x30, 0x08027108); + CDV_MSG_WRITE32(pci_domain_nr(dev->pdev->bus), 3, 0x30, 0x08027108); } /** diff --git a/drivers/gpu/drm/gma500/gma_device.c b/drivers/gpu/drm/gma500/gma_device.c index 4a295f9ba067..a7fb6de4dd15 100644 --- a/drivers/gpu/drm/gma500/gma_device.c +++ b/drivers/gpu/drm/gma500/gma_device.c @@ -19,7 +19,9 @@ void gma_get_core_freq(struct drm_device *dev) { uint32_t clock; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); + struct pci_dev *pci_root = + pci_get_domain_bus_and_slot(pci_domain_nr(dev->pdev->bus), + 0, 0); struct drm_psb_private *dev_priv = dev->dev_private; /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/ diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c index 1fa163373a47..7171b7475f58 100644 --- a/drivers/gpu/drm/gma500/mid_bios.c +++ b/drivers/gpu/drm/gma500/mid_bios.c @@ -32,7 +32,9 @@ static void mid_get_fuse_settings(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); + struct pci_dev *pci_root = + pci_get_domain_bus_and_slot(pci_domain_nr(dev->pdev->bus), + 0, 0); uint32_t fuse_value = 0; uint32_t fuse_value_tmp = 0; @@ -104,7 +106,9 @@ static void mid_get_fuse_settings(struct drm_device *dev) static void mid_get_pci_revID(struct drm_psb_private *dev_priv) { uint32_t platform_rev_id = 0; - struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); + int domain = pci_domain_nr(dev_priv->dev->pdev->bus); + struct pci_dev *pci_gfx_root = + pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(2, 0)); if (pci_gfx_root == NULL) { WARN_ON(1); @@ -281,7 +285,9 @@ static void mid_get_vbt_data(struct drm_psb_private *dev_priv) u32 addr; u8 __iomem *vbt_virtual; struct mid_vbt_header vbt_header; - struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); + struct pci_dev *pci_gfx_root = + pci_get_domain_bus_and_slot(pci_domain_nr(dev->pdev->bus), + 0, PCI_DEVFN(2, 0)); int ret = -1; /* Get the address of the platform config vbt */ diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 37a3be71acd9..99d6527923de 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -261,7 +261,11 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) goto out_err; if (IS_MRST(dev)) { - dev_priv->aux_pdev = pci_get_bus_and_slot(0, PCI_DEVFN(3, 0)); + int domain = pci_domain_nr(dev->pdev->bus); + + dev_priv->aux_pdev = + pci_get_domain_bus_and_slot(domain, 0, + PCI_DEVFN(3, 0)); if (dev_priv->aux_pdev) { resource_start = pci_resource_start(dev_priv->aux_pdev, @@ -281,7 +285,9 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) } dev_priv->gmbus_reg = dev_priv->aux_reg; - dev_priv->lpc_pdev = pci_get_bus_and_slot(0, PCI_DEVFN(31, 0)); + dev_priv->lpc_pdev = + pci_get_domain_bus_and_slot(domain, 0, + PCI_DEVFN(31, 0)); if (dev_priv->lpc_pdev) { pci_read_config_word(dev_priv->lpc_pdev, PSB_LPC_GBA, &dev_priv->lpc_gpio_base); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 821497dbd3fc..d409e02bf540 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -781,38 +781,40 @@ extern const struct psb_ops cdv_chip_ops; extern int drm_idle_check_interval; /* Utilities */ -static inline u32 MRST_MSG_READ32(uint port, uint offset) +static inline u32 MRST_MSG_READ32(int domain, uint port, uint offset) { int mcr = (0xD0<<24) | (port << 16) | (offset << 8); uint32_t ret_val = 0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0); pci_write_config_dword(pci_root, 0xD0, mcr); pci_read_config_dword(pci_root, 0xD4, &ret_val); pci_dev_put(pci_root); return ret_val; } -static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value) +static inline void MRST_MSG_WRITE32(int domain, uint port, uint offset, + u32 value) { int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0); pci_write_config_dword(pci_root, 0xD4, value); pci_write_config_dword(pci_root, 0xD0, mcr); pci_dev_put(pci_root); } -static inline u32 MDFLD_MSG_READ32(uint port, uint offset) +static inline u32 MDFLD_MSG_READ32(int domain, uint port, uint offset) { int mcr = (0x10<<24) | (port << 16) | (offset << 8); uint32_t ret_val = 0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0); pci_write_config_dword(pci_root, 0xD0, mcr); pci_read_config_dword(pci_root, 0xD4, &ret_val); pci_dev_put(pci_root); return ret_val; } -static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value) +static inline void MDFLD_MSG_WRITE32(int domain, uint port, uint offset, + u32 value) { int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0); pci_write_config_dword(pci_root, 0xD4, value); pci_write_config_dword(pci_root, 0xD0, mcr); pci_dev_put(pci_root); diff --git a/drivers/gpu/drm/nouveau/dispnv04/arb.c b/drivers/gpu/drm/nouveau/dispnv04/arb.c index 90075b676256..c79160c37f84 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/arb.c +++ b/drivers/gpu/drm/nouveau/dispnv04/arb.c @@ -213,8 +213,10 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, if ((dev->pdev->device & 0xffff) == 0x01a0 /*CHIPSET_NFORCE*/ || (dev->pdev->device & 0xffff) == 0x01f0 /*CHIPSET_NFORCE2*/) { uint32_t type; + int domain = pci_domain_nr(dev->pdev->bus); - pci_read_config_dword(pci_get_bus_and_slot(0, 1), 0x7c, &type); + pci_read_config_dword(pci_get_domain_bus_and_slot(domain, 0, 1), + 0x7c, &type); sim_data.memory_type = (type >> 12) & 1; sim_data.memory_width = 64; diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c index b98599002831..0c9bdf023f5b 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/hw.c +++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c @@ -216,12 +216,15 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype) { struct nvkm_pll_vals pllvals; int ret; + int domain; + + domain = pci_domain_nr(dev->pdev->bus); if (plltype == PLL_MEMORY && (dev->pdev->device & 0x0ff0) == CHIPSET_NFORCE) { uint32_t mpllP; - - pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP); + pci_read_config_dword(pci_get_domain_bus_and_slot(domain, 0, 3), + 0x6c, &mpllP); mpllP = (mpllP >> 8) & 0xf; if (!mpllP) mpllP = 4; @@ -232,7 +235,8 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype) (dev->pdev->device & 0xff0) == CHIPSET_NFORCE2) { uint32_t clock; - pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock); + pci_read_config_dword(pci_get_domain_bus_and_slot(domain, 0, 5), + 0x4c, &clock); return clock / 1000; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 8d4a5be3b913..33b6139c1bf1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -524,7 +524,8 @@ nouveau_get_hdmi_dev(struct nouveau_drm *drm) } /* subfunction one is a hdmi audio device? */ - drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number, + drm->hdmi_device = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), + (unsigned int)pdev->bus->number, PCI_DEVFN(PCI_SLOT(pdev->devfn), 1)); if (!drm->hdmi_device) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c index 4c07d10bb976..18241c6ba5fa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c @@ -28,8 +28,16 @@ nv1a_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { struct pci_dev *bridge; u32 mem, mib; + int domain = 0; + struct pci_dev *pdev = NULL; - bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); + if (dev_is_pci(fb->subdev.device->dev)) + pdev = to_pci_dev(fb->subdev.device->dev); + + if (pdev) + domain = pci_domain_nr(pdev->bus); + + bridge = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 1)); if (!bridge) { nvkm_error(&fb->subdev, "no bridge device\n"); return -ENODEV; diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index 8755df3330a0..3300dac56390 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c @@ -239,8 +239,9 @@ static u8 sl82c105_bridge_revision(struct pci_dev *dev) /* * The bridge should be part of the same device, but function 0. */ - bridge = pci_get_bus_and_slot(dev->bus->number, - PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); + bridge = pci_get_domain_bus_and_slot(pci_domain_nr(dev->bus), + dev->bus->number, + PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); if (!bridge) return -1; diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c index 50812b33291b..b3786474e84a 100644 --- a/drivers/infiniband/hw/qedr/main.c +++ b/drivers/infiniband/hw/qedr/main.c @@ -430,59 +430,16 @@ static void qedr_remove_sysfiles(struct qedr_dev *dev) static void qedr_pci_set_atomic(struct qedr_dev *dev, struct pci_dev *pdev) { - struct pci_dev *bridge; - u32 ctl2, cap2; - u16 flags; - int rc; - - bridge = pdev->bus->self; - if (!bridge) - goto disable; - - /* Check atomic routing support all the way to root complex */ - while (bridge->bus->parent) { - rc = pcie_capability_read_word(bridge, PCI_EXP_FLAGS, &flags); - if (rc || ((flags & PCI_EXP_FLAGS_VERS) < 2)) - goto disable; - - rc = pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap2); - if (rc) - goto disable; + int rc = pci_enable_atomic_ops_to_root(pdev, + PCI_EXP_DEVCAP2_ATOMIC_COMP64); - rc = pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, &ctl2); - if (rc) - goto disable; - - if (!(cap2 & PCI_EXP_DEVCAP2_ATOMIC_ROUTE) || - (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK)) - goto disable; - bridge = bridge->bus->parent->self; + if (rc) { + dev->atomic_cap = IB_ATOMIC_NONE; + DP_DEBUG(dev, QEDR_MSG_INIT, "Atomic capability disabled\n"); + } else { + dev->atomic_cap = IB_ATOMIC_GLOB; + DP_DEBUG(dev, QEDR_MSG_INIT, "Atomic capability enabled\n"); } - - rc = pcie_capability_read_word(bridge, PCI_EXP_FLAGS, &flags); - if (rc || ((flags & PCI_EXP_FLAGS_VERS) < 2)) - goto disable; - - rc = pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap2); - if (rc || !(cap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP64)) - goto disable; - - /* Set atomic operations */ - pcie_capability_set_word(pdev, PCI_EXP_DEVCTL2, - PCI_EXP_DEVCTL2_ATOMIC_REQ); - dev->atomic_cap = IB_ATOMIC_GLOB; - - DP_DEBUG(dev, QEDR_MSG_INIT, "Atomic capability enabled\n"); - - return; - -disable: - pcie_capability_clear_word(pdev, PCI_EXP_DEVCTL2, - PCI_EXP_DEVCTL2_ATOMIC_REQ); - dev->atomic_cap = IB_ATOMIC_NONE; - - DP_DEBUG(dev, QEDR_MSG_INIT, "Atomic capability disabled\n"); - } static const struct qed_rdma_ops *qed_ops; diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 7d5eb004091d..821547b23c65 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -527,7 +527,8 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id, struct iommu_dev_data *dev_data = NULL; struct pci_dev *pdev; - pdev = pci_get_bus_and_slot(PCI_BUS_NUM(devid), devid & 0xff); + pdev = pci_get_domain_bus_and_slot(0, PCI_BUS_NUM(devid), + devid & 0xff); if (pdev) dev_data = get_dev_data(&pdev->dev); diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 6fe2d0346073..4e4a615bf13f 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1697,8 +1697,8 @@ static int iommu_init_pci(struct amd_iommu *iommu) u32 range, misc, low, high; int ret; - iommu->dev = pci_get_bus_and_slot(PCI_BUS_NUM(iommu->devid), - iommu->devid & 0xff); + iommu->dev = pci_get_domain_bus_and_slot(0, PCI_BUS_NUM(iommu->devid), + iommu->devid & 0xff); if (!iommu->dev) return -ENODEV; @@ -1764,8 +1764,9 @@ static int iommu_init_pci(struct amd_iommu *iommu) if (is_rd890_iommu(iommu->dev)) { int i, j; - iommu->root_pdev = pci_get_bus_and_slot(iommu->dev->bus->number, - PCI_DEVFN(0, 0)); + iommu->root_pdev = + pci_get_domain_bus_and_slot(0, iommu->dev->bus->number, + PCI_DEVFN(0, 0)); /* * Some rd890 systems may not be fully reconfigured by the diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 7d94e1d39e5e..8696382be837 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c @@ -564,7 +564,8 @@ static int ppr_notifier(struct notifier_block *nb, unsigned long e, void *data) finish = (iommu_fault->tag >> 9) & 1; devid = iommu_fault->device_id; - pdev = pci_get_bus_and_slot(PCI_BUS_NUM(devid), devid & 0xff); + pdev = pci_get_domain_bus_and_slot(0, PCI_BUS_NUM(devid), + devid & 0xff); if (!pdev) return -ENODEV; dev_data = get_dev_data(&pdev->dev); diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index c4c2b3b85ebc..3e8b3b68dcb4 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -1799,7 +1799,7 @@ static int powerbook_sleep_grackle(void) struct adb_request req; struct pci_dev *grackle; - grackle = pci_get_bus_and_slot(0, 0); + grackle = pci_get_domain_bus_and_slot(0, 0, 0); if (!grackle) return -ENODEV; diff --git a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c index a142b9dc0feb..ea40a24947ba 100644 --- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c @@ -102,7 +102,6 @@ struct ttusb { unsigned int isoc_in_pipe; void *iso_buffer; - dma_addr_t iso_dma_handle; struct urb *iso_urb[ISO_BUF_COUNT]; @@ -792,26 +791,17 @@ static void ttusb_free_iso_urbs(struct ttusb *ttusb) for (i = 0; i < ISO_BUF_COUNT; i++) usb_free_urb(ttusb->iso_urb[i]); - - pci_free_consistent(NULL, - ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * - ISO_BUF_COUNT, ttusb->iso_buffer, - ttusb->iso_dma_handle); + kfree(ttusb->iso_buffer); } static int ttusb_alloc_iso_urbs(struct ttusb *ttusb) { int i; - ttusb->iso_buffer = pci_zalloc_consistent(NULL, - ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT, - &ttusb->iso_dma_handle); - - if (!ttusb->iso_buffer) { - dprintk("%s: pci_alloc_consistent - not enough memory\n", - __func__); + ttusb->iso_buffer = kcalloc(FRAMES_PER_ISO_BUF * ISO_BUF_COUNT, + ISO_FRAME_SIZE, GFP_KERNEL); + if (!ttusb->iso_buffer) return -ENOMEM; - } for (i = 0; i < ISO_BUF_COUNT; i++) { struct urb *urb; diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index cdefb5dfbbdc..4d5acdf578a6 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c @@ -127,7 +127,6 @@ struct ttusb_dec { struct urb *irq_urb; dma_addr_t irq_dma_handle; void *iso_buffer; - dma_addr_t iso_dma_handle; struct urb *iso_urb[ISO_BUF_COUNT]; int iso_stream_count; struct mutex iso_mutex; @@ -1185,11 +1184,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec) for (i = 0; i < ISO_BUF_COUNT; i++) usb_free_urb(dec->iso_urb[i]); - - pci_free_consistent(NULL, - ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * - ISO_BUF_COUNT), - dec->iso_buffer, dec->iso_dma_handle); + kfree(dec->iso_buffer); } static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) @@ -1198,15 +1193,10 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) dprintk("%s\n", __func__); - dec->iso_buffer = pci_zalloc_consistent(NULL, - ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT), - &dec->iso_dma_handle); - - if (!dec->iso_buffer) { - dprintk("%s: pci_alloc_consistent - not enough memory\n", - __func__); + dec->iso_buffer = kcalloc(FRAMES_PER_ISO_BUF * ISO_BUF_COUNT, + ISO_FRAME_SIZE, GFP_KERNEL); + if (!dec->iso_buffer) return -ENOMEM; - } for (i = 0; i < ISO_BUF_COUNT; i++) { struct urb *urb; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 3591077a5f6b..ffa7959f6b31 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -812,7 +812,7 @@ static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid) if (!vf) return false; - dev = pci_get_bus_and_slot(vf->bus, vf->devfn); + dev = pci_get_domain_bus_and_slot(vf->domain, vf->bus, vf->devfn); if (dev) return bnx2x_is_pcie_pending(dev); return false; @@ -1041,6 +1041,13 @@ void bnx2x_iov_init_dmae(struct bnx2x *bp) REG_WR(bp, DMAE_REG_BACKWARD_COMP_EN, 0); } +static int bnx2x_vf_domain(struct bnx2x *bp, int vfid) +{ + struct pci_dev *dev = bp->pdev; + + return pci_domain_nr(dev->bus); +} + static int bnx2x_vf_bus(struct bnx2x *bp, int vfid) { struct pci_dev *dev = bp->pdev; @@ -1606,6 +1613,7 @@ int bnx2x_iov_nic_init(struct bnx2x *bp) struct bnx2x_virtf *vf = BP_VF(bp, vfid); /* fill in the BDF and bars */ + vf->domain = bnx2x_vf_domain(bp, vfid); vf->bus = bnx2x_vf_bus(bp, vfid); vf->devfn = bnx2x_vf_devfn(bp, vfid); bnx2x_vf_set_bars(bp, vf); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 53466f6cebab..eb814c65152f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -182,6 +182,7 @@ struct bnx2x_virtf { u32 error; /* 0 means all's-well */ /* BDF */ + unsigned int domain; unsigned int bus; unsigned int devfn; diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 40e52ffb732f..7cd494611a74 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -2594,8 +2594,10 @@ static int pch_gbe_probe(struct pci_dev *pdev, if (adapter->pdata && adapter->pdata->platform_init) adapter->pdata->platform_init(pdev); - adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number, - PCI_DEVFN(12, 4)); + adapter->ptp_pdev = + pci_get_domain_bus_and_slot(pci_domain_nr(adapter->pdev->bus), + adapter->pdev->bus->number, + PCI_DEVFN(12, 4)); netdev->netdev_ops = &pch_gbe_netdev_ops; netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD; diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index 0624b71ab5d4..edcd1e60b30d 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c @@ -152,6 +152,8 @@ struct tsi108_prv_data { u32 msg_enable; /* debug message level */ struct mii_if_info mii_if; unsigned int init_media; + + struct platform_device *pdev; }; /* Structure for a device driver */ @@ -703,17 +705,18 @@ static int tsi108_send_packet(struct sk_buff * skb, struct net_device *dev) data->txskbs[tx] = skb; if (i == 0) { - data->txring[tx].buf0 = dma_map_single(NULL, skb->data, - skb_headlen(skb), DMA_TO_DEVICE); + data->txring[tx].buf0 = dma_map_single(&data->pdev->dev, + skb->data, skb_headlen(skb), + DMA_TO_DEVICE); data->txring[tx].len = skb_headlen(skb); misc |= TSI108_TX_SOF; } else { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; - data->txring[tx].buf0 = skb_frag_dma_map(NULL, frag, - 0, - skb_frag_size(frag), - DMA_TO_DEVICE); + data->txring[tx].buf0 = + skb_frag_dma_map(&data->pdev->dev, frag, + 0, skb_frag_size(frag), + DMA_TO_DEVICE); data->txring[tx].len = skb_frag_size(frag); } @@ -808,9 +811,9 @@ static int tsi108_refill_rx(struct net_device *dev, int budget) if (!skb) break; - data->rxring[rx].buf0 = dma_map_single(NULL, skb->data, - TSI108_RX_SKB_SIZE, - DMA_FROM_DEVICE); + data->rxring[rx].buf0 = dma_map_single(&data->pdev->dev, + skb->data, TSI108_RX_SKB_SIZE, + DMA_FROM_DEVICE); /* Sometimes the hardware sets blen to zero after packet * reception, even though the manual says that it's only ever @@ -1308,15 +1311,15 @@ static int tsi108_open(struct net_device *dev) data->id, dev->irq, dev->name); } - data->rxring = dma_zalloc_coherent(NULL, rxring_size, &data->rxdma, - GFP_KERNEL); + data->rxring = dma_zalloc_coherent(&data->pdev->dev, rxring_size, + &data->rxdma, GFP_KERNEL); if (!data->rxring) return -ENOMEM; - data->txring = dma_zalloc_coherent(NULL, txring_size, &data->txdma, - GFP_KERNEL); + data->txring = dma_zalloc_coherent(&data->pdev->dev, txring_size, + &data->txdma, GFP_KERNEL); if (!data->txring) { - pci_free_consistent(NULL, rxring_size, data->rxring, + dma_free_coherent(&data->pdev->dev, rxring_size, data->rxring, data->rxdma); return -ENOMEM; } @@ -1428,10 +1431,10 @@ static int tsi108_close(struct net_device *dev) dev_kfree_skb(skb); } - dma_free_coherent(0, + dma_free_coherent(&data->pdev->dev, TSI108_RXRING_LEN * sizeof(rx_desc), data->rxring, data->rxdma); - dma_free_coherent(0, + dma_free_coherent(&data->pdev->dev, TSI108_TXRING_LEN * sizeof(tx_desc), data->txring, data->txdma); @@ -1576,6 +1579,7 @@ tsi108_init_one(struct platform_device *pdev) printk("tsi108_eth%d: probe...\n", pdev->id); data = netdev_priv(dev); data->dev = dev; + data->pdev = pdev; pr_debug("tsi108_eth%d:regs:phyresgs:phy:irq_num=0x%x:0x%x:0x%x:0x%x\n", pdev->id, einfo->regs, einfo->phyregs, diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index ad9a9578f9c4..ee244c2e8c2b 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -62,10 +62,6 @@ config OF_DYNAMIC config OF_ADDRESS def_bool y depends on !SPARC && HAS_IOMEM - select OF_ADDRESS_PCI if PCI - -config OF_ADDRESS_PCI - bool config OF_IRQ def_bool y @@ -82,18 +78,6 @@ config OF_MDIO help OpenFirmware MDIO bus (Ethernet PHY) accessors -config OF_PCI - def_tristate PCI - depends on PCI - help - OpenFirmware PCI bus accessors - -config OF_PCI_IRQ - def_tristate PCI - depends on OF_PCI && OF_IRQ - help - OpenFirmware PCI IRQ routing helpers - config OF_RESERVED_MEM depends on OF_EARLY_FLATTREE bool diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 63a4be62ce19..663a4af0cccd 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -10,8 +10,6 @@ obj-$(CONFIG_OF_IRQ) += irq.o obj-$(CONFIG_OF_NET) += of_net.o obj-$(CONFIG_OF_UNITTEST) += unittest.o obj-$(CONFIG_OF_MDIO) += of_mdio.o -obj-$(CONFIG_OF_PCI) += of_pci.o -obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o obj-$(CONFIG_OF_RESOLVE) += resolver.o obj-$(CONFIG_OF_OVERLAY) += overlay.o diff --git a/drivers/of/address.c b/drivers/of/address.c index fa6cabfc3cb9..8591afbdfe99 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -96,7 +96,7 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr) return IORESOURCE_MEM; } -#ifdef CONFIG_OF_ADDRESS_PCI +#ifdef CONFIG_PCI /* * PCI bus specific translator */ @@ -171,9 +171,7 @@ static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) { return of_bus_default_translate(addr + 1, offset, na - 1); } -#endif /* CONFIG_OF_ADDRESS_PCI */ -#ifdef CONFIG_PCI const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, unsigned int *flags) { @@ -426,7 +424,7 @@ static unsigned int of_bus_isa_get_flags(const __be32 *addr) */ static struct of_bus of_busses[] = { -#ifdef CONFIG_OF_ADDRESS_PCI +#ifdef CONFIG_PCI /* PCI */ { .name = "pci", @@ -437,7 +435,7 @@ static struct of_bus of_busses[] = { .translate = of_bus_pci_translate, .get_flags = of_bus_pci_get_flags, }, -#endif /* CONFIG_OF_ADDRESS_PCI */ +#endif /* CONFIG_PCI */ /* ISA */ { .name = "isa", diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c deleted file mode 100644 index a7b1cb6c2f65..000000000000 --- a/drivers/of/of_pci.c +++ /dev/null @@ -1,384 +0,0 @@ -#define pr_fmt(fmt) "OF: PCI: " fmt - -#include <linux/kernel.h> -#include <linux/export.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_pci.h> -#include <linux/slab.h> - -static inline int __of_pci_pci_compare(struct device_node *node, - unsigned int data) -{ - int devfn; - - devfn = of_pci_get_devfn(node); - if (devfn < 0) - return 0; - - return devfn == data; -} - -struct device_node *of_pci_find_child_device(struct device_node *parent, - unsigned int devfn) -{ - struct device_node *node, *node2; - - for_each_child_of_node(parent, node) { - if (__of_pci_pci_compare(node, devfn)) - return node; - /* - * Some OFs create a parent node "multifunc-device" as - * a fake root for all functions of a multi-function - * device we go down them as well. - */ - if (!strcmp(node->name, "multifunc-device")) { - for_each_child_of_node(node, node2) { - if (__of_pci_pci_compare(node2, devfn)) { - of_node_put(node); - return node2; - } - } - } - } - return NULL; -} -EXPORT_SYMBOL_GPL(of_pci_find_child_device); - -/** - * of_pci_get_devfn() - Get device and function numbers for a device node - * @np: device node - * - * Parses a standard 5-cell PCI resource and returns an 8-bit value that can - * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device - * and function numbers respectively. On error a negative error code is - * returned. - */ -int of_pci_get_devfn(struct device_node *np) -{ - u32 reg[5]; - int error; - - error = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg)); - if (error) - return error; - - return (reg[0] >> 8) & 0xff; -} -EXPORT_SYMBOL_GPL(of_pci_get_devfn); - -/** - * of_pci_parse_bus_range() - parse the bus-range property of a PCI device - * @node: device node - * @res: address to a struct resource to return the bus-range - * - * Returns 0 on success or a negative error-code on failure. - */ -int of_pci_parse_bus_range(struct device_node *node, struct resource *res) -{ - u32 bus_range[2]; - int error; - - error = of_property_read_u32_array(node, "bus-range", bus_range, - ARRAY_SIZE(bus_range)); - if (error) - return error; - - res->name = node->name; - res->start = bus_range[0]; - res->end = bus_range[1]; - res->flags = IORESOURCE_BUS; - - return 0; -} -EXPORT_SYMBOL_GPL(of_pci_parse_bus_range); - -/** - * This function will try to obtain the host bridge domain number by - * finding a property called "linux,pci-domain" of the given device node. - * - * @node: device tree node with the domain information - * - * Returns the associated domain number from DT in the range [0-0xffff], or - * a negative value if the required property is not found. - */ -int of_get_pci_domain_nr(struct device_node *node) -{ - u32 domain; - int error; - - error = of_property_read_u32(node, "linux,pci-domain", &domain); - if (error) - return error; - - return (u16)domain; -} -EXPORT_SYMBOL_GPL(of_get_pci_domain_nr); - -/** - * This function will try to find the limitation of link speed by finding - * a property called "max-link-speed" of the given device node. - * - * @node: device tree node with the max link speed information - * - * Returns the associated max link speed from DT, or a negative value if the - * required property is not found or is invalid. - */ -int of_pci_get_max_link_speed(struct device_node *node) -{ - u32 max_link_speed; - - if (of_property_read_u32(node, "max-link-speed", &max_link_speed) || - max_link_speed > 4) - return -EINVAL; - - return max_link_speed; -} -EXPORT_SYMBOL_GPL(of_pci_get_max_link_speed); - -/** - * of_pci_check_probe_only - Setup probe only mode if linux,pci-probe-only - * is present and valid - */ -void of_pci_check_probe_only(void) -{ - u32 val; - int ret; - - ret = of_property_read_u32(of_chosen, "linux,pci-probe-only", &val); - if (ret) { - if (ret == -ENODATA || ret == -EOVERFLOW) - pr_warn("linux,pci-probe-only without valid value, ignoring\n"); - return; - } - - if (val) - pci_add_flags(PCI_PROBE_ONLY); - else - pci_clear_flags(PCI_PROBE_ONLY); - - pr_info("PROBE_ONLY %sabled\n", val ? "en" : "dis"); -} -EXPORT_SYMBOL_GPL(of_pci_check_probe_only); - -#if defined(CONFIG_OF_ADDRESS) -/** - * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT - * @dev: device node of the host bridge having the range property - * @busno: bus number associated with the bridge root bus - * @bus_max: maximum number of buses for this bridge - * @resources: list where the range of resources will be added after DT parsing - * @io_base: pointer to a variable that will contain on return the physical - * address for the start of the I/O range. Can be NULL if the caller doesn't - * expect IO ranges to be present in the device tree. - * - * It is the caller's job to free the @resources list. - * - * This function will parse the "ranges" property of a PCI host bridge device - * node and setup the resource mapping based on its content. It is expected - * that the property conforms with the Power ePAPR document. - * - * It returns zero if the range parsing has been successful or a standard error - * value if it failed. - */ -int of_pci_get_host_bridge_resources(struct device_node *dev, - unsigned char busno, unsigned char bus_max, - struct list_head *resources, resource_size_t *io_base) -{ - struct resource_entry *window; - struct resource *res; - struct resource *bus_range; - struct of_pci_range range; - struct of_pci_range_parser parser; - char range_type[4]; - int err; - - if (io_base) - *io_base = (resource_size_t)OF_BAD_ADDR; - - bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL); - if (!bus_range) - return -ENOMEM; - - pr_info("host bridge %pOF ranges:\n", dev); - - err = of_pci_parse_bus_range(dev, bus_range); - if (err) { - bus_range->start = busno; - bus_range->end = bus_max; - bus_range->flags = IORESOURCE_BUS; - pr_info(" No bus range found for %pOF, using %pR\n", - dev, bus_range); - } else { - if (bus_range->end > bus_range->start + bus_max) - bus_range->end = bus_range->start + bus_max; - } - pci_add_resource(resources, bus_range); - - /* Check for ranges property */ - err = of_pci_range_parser_init(&parser, dev); - if (err) - goto parse_failed; - - pr_debug("Parsing ranges property...\n"); - for_each_of_pci_range(&parser, &range) { - /* Read next ranges element */ - if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO) - snprintf(range_type, 4, " IO"); - else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM) - snprintf(range_type, 4, "MEM"); - else - snprintf(range_type, 4, "err"); - pr_info(" %s %#010llx..%#010llx -> %#010llx\n", range_type, - range.cpu_addr, range.cpu_addr + range.size - 1, - range.pci_addr); - - /* - * If we failed translation or got a zero-sized region - * then skip this range - */ - if (range.cpu_addr == OF_BAD_ADDR || range.size == 0) - continue; - - res = kzalloc(sizeof(struct resource), GFP_KERNEL); - if (!res) { - err = -ENOMEM; - goto parse_failed; - } - - err = of_pci_range_to_resource(&range, dev, res); - if (err) { - kfree(res); - continue; - } - - if (resource_type(res) == IORESOURCE_IO) { - if (!io_base) { - pr_err("I/O range found for %pOF. Please provide an io_base pointer to save CPU base address\n", - dev); - err = -EINVAL; - goto conversion_failed; - } - if (*io_base != (resource_size_t)OF_BAD_ADDR) - pr_warn("More than one I/O resource converted for %pOF. CPU base address for old range lost!\n", - dev); - *io_base = range.cpu_addr; - } - - pci_add_resource_offset(resources, res, res->start - range.pci_addr); - } - - return 0; - -conversion_failed: - kfree(res); -parse_failed: - resource_list_for_each_entry(window, resources) - kfree(window->res); - pci_free_resource_list(resources); - return err; -} -EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources); -#endif /* CONFIG_OF_ADDRESS */ - -/** - * of_pci_map_rid - Translate a requester ID through a downstream mapping. - * @np: root complex device node. - * @rid: PCI requester ID to map. - * @map_name: property name of the map to use. - * @map_mask_name: optional property name of the mask to use. - * @target: optional pointer to a target device node. - * @id_out: optional pointer to receive the translated ID. - * - * Given a PCI requester ID, look up the appropriate implementation-defined - * platform ID and/or the target device which receives transactions on that - * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or - * @id_out may be NULL if only the other is required. If @target points to - * a non-NULL device node pointer, only entries targeting that node will be - * matched; if it points to a NULL value, it will receive the device node of - * the first matching target phandle, with a reference held. - * - * Return: 0 on success or a standard error code on failure. - */ -int of_pci_map_rid(struct device_node *np, u32 rid, - const char *map_name, const char *map_mask_name, - struct device_node **target, u32 *id_out) -{ - u32 map_mask, masked_rid; - int map_len; - const __be32 *map = NULL; - - if (!np || !map_name || (!target && !id_out)) - return -EINVAL; - - map = of_get_property(np, map_name, &map_len); - if (!map) { - if (target) - return -ENODEV; - /* Otherwise, no map implies no translation */ - *id_out = rid; - return 0; - } - - if (!map_len || map_len % (4 * sizeof(*map))) { - pr_err("%pOF: Error: Bad %s length: %d\n", np, - map_name, map_len); - return -EINVAL; - } - - /* The default is to select all bits. */ - map_mask = 0xffffffff; - - /* - * Can be overridden by "{iommu,msi}-map-mask" property. - * If of_property_read_u32() fails, the default is used. - */ - if (map_mask_name) - of_property_read_u32(np, map_mask_name, &map_mask); - - masked_rid = map_mask & rid; - for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) { - struct device_node *phandle_node; - u32 rid_base = be32_to_cpup(map + 0); - u32 phandle = be32_to_cpup(map + 1); - u32 out_base = be32_to_cpup(map + 2); - u32 rid_len = be32_to_cpup(map + 3); - - if (rid_base & ~map_mask) { - pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores rid-base (0x%x)\n", - np, map_name, map_name, - map_mask, rid_base); - return -EFAULT; - } - - if (masked_rid < rid_base || masked_rid >= rid_base + rid_len) - continue; - - phandle_node = of_find_node_by_phandle(phandle); - if (!phandle_node) - return -ENODEV; - - if (target) { - if (*target) - of_node_put(phandle_node); - else - *target = phandle_node; - - if (*target != phandle_node) - continue; - } - - if (id_out) - *id_out = masked_rid - rid_base + out_base; - - pr_debug("%pOF: %s, using mask %08x, rid-base: %08x, out-base: %08x, length: %08x, rid: %08x -> %08x\n", - np, map_name, map_mask, rid_base, out_base, - rid_len, rid, masked_rid - rid_base + out_base); - return 0; - } - - pr_err("%pOF: Invalid %s translation - no match for rid 0x%x on %pOF\n", - np, map_name, rid, target && *target ? *target : NULL); - return -EFAULT; -} diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c deleted file mode 100644 index 3a05568f65df..000000000000 --- a/drivers/of/of_pci_irq.c +++ /dev/null @@ -1,131 +0,0 @@ -#include <linux/kernel.h> -#include <linux/of_pci.h> -#include <linux/of_irq.h> -#include <linux/export.h> - -/** - * of_irq_parse_pci - Resolve the interrupt for a PCI device - * @pdev: the device whose interrupt is to be resolved - * @out_irq: structure of_irq filled by this function - * - * This function resolves the PCI interrupt for a given PCI device. If a - * device-node exists for a given pci_dev, it will use normal OF tree - * walking. If not, it will implement standard swizzling and walk up the - * PCI tree until an device-node is found, at which point it will finish - * resolving using the OF tree walking. - */ -int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq) -{ - struct device_node *dn, *ppnode; - struct pci_dev *ppdev; - __be32 laddr[3]; - u8 pin; - int rc; - - /* Check if we have a device node, if yes, fallback to standard - * device tree parsing - */ - dn = pci_device_to_OF_node(pdev); - if (dn) { - rc = of_irq_parse_one(dn, 0, out_irq); - if (!rc) - return rc; - } - - /* Ok, we don't, time to have fun. Let's start by building up an - * interrupt spec. we assume #interrupt-cells is 1, which is standard - * for PCI. If you do different, then don't use that routine. - */ - rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); - if (rc != 0) - goto err; - /* No pin, exit with no error message. */ - if (pin == 0) - return -ENODEV; - - /* Now we walk up the PCI tree */ - for (;;) { - /* Get the pci_dev of our parent */ - ppdev = pdev->bus->self; - - /* Ouch, it's a host bridge... */ - if (ppdev == NULL) { - ppnode = pci_bus_to_OF_node(pdev->bus); - - /* No node for host bridge ? give up */ - if (ppnode == NULL) { - rc = -EINVAL; - goto err; - } - } else { - /* We found a P2P bridge, check if it has a node */ - ppnode = pci_device_to_OF_node(ppdev); - } - - /* Ok, we have found a parent with a device-node, hand over to - * the OF parsing code. - * We build a unit address from the linux device to be used for - * resolution. Note that we use the linux bus number which may - * not match your firmware bus numbering. - * Fortunately, in most cases, interrupt-map-mask doesn't - * include the bus number as part of the matching. - * You should still be careful about that though if you intend - * to rely on this function (you ship a firmware that doesn't - * create device nodes for all PCI devices). - */ - if (ppnode) - break; - - /* We can only get here if we hit a P2P bridge with no node, - * let's do standard swizzling and try again - */ - pin = pci_swizzle_interrupt_pin(pdev, pin); - pdev = ppdev; - } - - out_irq->np = ppnode; - out_irq->args_count = 1; - out_irq->args[0] = pin; - laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); - laddr[1] = laddr[2] = cpu_to_be32(0); - rc = of_irq_parse_raw(laddr, out_irq); - if (rc) - goto err; - return 0; -err: - if (rc == -ENOENT) { - dev_warn(&pdev->dev, - "%s: no interrupt-map found, INTx interrupts not available\n", - __func__); - pr_warn_once("%s: possibly some PCI slots don't have level triggered interrupts capability\n", - __func__); - } else { - dev_err(&pdev->dev, "%s: failed with rc=%d\n", __func__, rc); - } - return rc; -} -EXPORT_SYMBOL_GPL(of_irq_parse_pci); - -/** - * of_irq_parse_and_map_pci() - Decode a PCI irq from the device tree and map to a virq - * @dev: The pci device needing an irq - * @slot: PCI slot number; passed when used as map_irq callback. Unused - * @pin: PCI irq pin number; passed when used as map_irq callback. Unused - * - * @slot and @pin are unused, but included in the function so that this - * function can be used directly as the map_irq callback to - * pci_assign_irq() and struct pci_host_bridge.map_irq pointer - */ -int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin) -{ - struct of_phandle_args oirq; - int ret; - - ret = of_irq_parse_pci(dev, &oirq); - if (ret) - return 0; /* Proper return code 0 == NO_IRQ */ - - return irq_create_of_mapping(&oirq); -} -EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci); - diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index e220d49307bd..8897a7775b8c 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c @@ -89,7 +89,9 @@ int cpqhp_configure_device(struct controller *ctrl, struct pci_func *func) pci_lock_rescan_remove(); if (func->pci_dev == NULL) - func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function)); + func->pci_dev = pci_get_domain_bus_and_slot(0, func->bus, + PCI_DEVFN(func->device, + func->function)); /* No pci device, we need to create it then */ if (func->pci_dev == NULL) { @@ -99,7 +101,9 @@ int cpqhp_configure_device(struct controller *ctrl, struct pci_func *func) if (num) pci_bus_add_devices(ctrl->pci_dev->bus); - func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function)); + func->pci_dev = pci_get_domain_bus_and_slot(0, func->bus, + PCI_DEVFN(func->device, + func->function)); if (func->pci_dev == NULL) { dbg("ERROR: pci_dev still null\n"); goto out; @@ -129,7 +133,10 @@ int cpqhp_unconfigure_device(struct pci_func *func) pci_lock_rescan_remove(); for (j = 0; j < 8 ; j++) { - struct pci_dev *temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j)); + struct pci_dev *temp = pci_get_domain_bus_and_slot(0, + func->bus, + PCI_DEVFN(func->device, + j)); if (temp) { pci_dev_put(temp); pci_stop_and_remove_bus_device(temp); @@ -319,6 +326,7 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug) int cloop = 0; int stop_it; int index; + u16 devfn; /* Decide which slots are supported */ @@ -416,7 +424,9 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug) new_slot->switch_save = 0x10; /* In case of unsupported board */ new_slot->status = DevError; - new_slot->pci_dev = pci_get_bus_and_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function); + devfn = (new_slot->device << 3) | new_slot->function; + new_slot->pci_dev = pci_get_domain_bus_and_slot(0, + new_slot->bus, devfn); for (cloop = 0; cloop < 0x20; cloop++) { rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) &(new_slot->config_space[cloop])); diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 73cf84645c82..92dd88296817 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -707,7 +707,8 @@ static void ibm_unconfigure_device(struct pci_func *func) pci_lock_rescan_remove(); for (j = 0; j < 0x08; j++) { - temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j); + temp = pci_get_domain_bus_and_slot(0, func->busno, + (func->device << 3) | j); if (temp) { pci_stop_and_remove_bus_device(temp); pci_dev_put(temp); @@ -780,7 +781,7 @@ static int ibm_configure_device(struct pci_func *func) if (!(bus_structure_fixup(func->busno))) flag = 1; if (func->dev == NULL) - func->dev = pci_get_bus_and_slot(func->busno, + func->dev = pci_get_domain_bus_and_slot(0, func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { @@ -793,7 +794,7 @@ static int ibm_configure_device(struct pci_func *func) if (num) pci_bus_add_devices(bus); - func->dev = pci_get_bus_and_slot(func->busno, + func->dev = pci_get_domain_bus_and_slot(0, func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { err("ERROR... : pci_dev still NULL\n"); diff --git a/drivers/pci/of.c b/drivers/pci/of.c index e112da11630e..e81835bdf4fa 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -8,12 +8,14 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#define pr_fmt(fmt) "PCI: OF: " fmt #include <linux/irqdomain.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/of.h> #include <linux/of_irq.h> +#include <linux/of_address.h> #include <linux/of_pci.h> #include "pci.h" @@ -51,8 +53,9 @@ struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus) if (WARN_ON(bus->self || bus->parent)) return NULL; - /* Look for a node pointer in either the intermediary device we - * create above the root bus or it's own parent. Normally only + /* + * Look for a node pointer in either the intermediary device we + * create above the root bus or its own parent. Normally only * the later is populated. */ if (bus->bridge->of_node) @@ -88,3 +91,510 @@ struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus) return NULL; #endif } + + +static inline int __of_pci_pci_compare(struct device_node *node, + unsigned int data) +{ + int devfn; + + devfn = of_pci_get_devfn(node); + if (devfn < 0) + return 0; + + return devfn == data; +} + +struct device_node *of_pci_find_child_device(struct device_node *parent, + unsigned int devfn) +{ + struct device_node *node, *node2; + + for_each_child_of_node(parent, node) { + if (__of_pci_pci_compare(node, devfn)) + return node; + /* + * Some OFs create a parent node "multifunc-device" as + * a fake root for all functions of a multi-function + * device we go down them as well. + */ + if (!strcmp(node->name, "multifunc-device")) { + for_each_child_of_node(node, node2) { + if (__of_pci_pci_compare(node2, devfn)) { + of_node_put(node); + return node2; + } + } + } + } + return NULL; +} +EXPORT_SYMBOL_GPL(of_pci_find_child_device); + +/** + * of_pci_get_devfn() - Get device and function numbers for a device node + * @np: device node + * + * Parses a standard 5-cell PCI resource and returns an 8-bit value that can + * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device + * and function numbers respectively. On error a negative error code is + * returned. + */ +int of_pci_get_devfn(struct device_node *np) +{ + u32 reg[5]; + int error; + + error = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg)); + if (error) + return error; + + return (reg[0] >> 8) & 0xff; +} +EXPORT_SYMBOL_GPL(of_pci_get_devfn); + +/** + * of_pci_parse_bus_range() - parse the bus-range property of a PCI device + * @node: device node + * @res: address to a struct resource to return the bus-range + * + * Returns 0 on success or a negative error-code on failure. + */ +int of_pci_parse_bus_range(struct device_node *node, struct resource *res) +{ + u32 bus_range[2]; + int error; + + error = of_property_read_u32_array(node, "bus-range", bus_range, + ARRAY_SIZE(bus_range)); + if (error) + return error; + + res->name = node->name; + res->start = bus_range[0]; + res->end = bus_range[1]; + res->flags = IORESOURCE_BUS; + + return 0; +} +EXPORT_SYMBOL_GPL(of_pci_parse_bus_range); + +/** + * This function will try to obtain the host bridge domain number by + * finding a property called "linux,pci-domain" of the given device node. + * + * @node: device tree node with the domain information + * + * Returns the associated domain number from DT in the range [0-0xffff], or + * a negative value if the required property is not found. + */ +int of_get_pci_domain_nr(struct device_node *node) +{ + u32 domain; + int error; + + error = of_property_read_u32(node, "linux,pci-domain", &domain); + if (error) + return error; + + return (u16)domain; +} +EXPORT_SYMBOL_GPL(of_get_pci_domain_nr); + +/** + * This function will try to find the limitation of link speed by finding + * a property called "max-link-speed" of the given device node. + * + * @node: device tree node with the max link speed information + * + * Returns the associated max link speed from DT, or a negative value if the + * required property is not found or is invalid. + */ +int of_pci_get_max_link_speed(struct device_node *node) +{ + u32 max_link_speed; + + if (of_property_read_u32(node, "max-link-speed", &max_link_speed) || + max_link_speed > 4) + return -EINVAL; + + return max_link_speed; +} +EXPORT_SYMBOL_GPL(of_pci_get_max_link_speed); + +/** + * of_pci_check_probe_only - Setup probe only mode if linux,pci-probe-only + * is present and valid + */ +void of_pci_check_probe_only(void) +{ + u32 val; + int ret; + + ret = of_property_read_u32(of_chosen, "linux,pci-probe-only", &val); + if (ret) { + if (ret == -ENODATA || ret == -EOVERFLOW) + pr_warn("linux,pci-probe-only without valid value, ignoring\n"); + return; + } + + if (val) + pci_add_flags(PCI_PROBE_ONLY); + else + pci_clear_flags(PCI_PROBE_ONLY); + + pr_info("PROBE_ONLY %sabled\n", val ? "en" : "dis"); +} +EXPORT_SYMBOL_GPL(of_pci_check_probe_only); + +#if defined(CONFIG_OF_ADDRESS) +/** + * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT + * @dev: device node of the host bridge having the range property + * @busno: bus number associated with the bridge root bus + * @bus_max: maximum number of buses for this bridge + * @resources: list where the range of resources will be added after DT parsing + * @io_base: pointer to a variable that will contain on return the physical + * address for the start of the I/O range. Can be NULL if the caller doesn't + * expect I/O ranges to be present in the device tree. + * + * It is the caller's job to free the @resources list. + * + * This function will parse the "ranges" property of a PCI host bridge device + * node and setup the resource mapping based on its content. It is expected + * that the property conforms with the Power ePAPR document. + * + * It returns zero if the range parsing has been successful or a standard error + * value if it failed. + */ +int of_pci_get_host_bridge_resources(struct device_node *dev, + unsigned char busno, unsigned char bus_max, + struct list_head *resources, resource_size_t *io_base) +{ + struct resource_entry *window; + struct resource *res; + struct resource *bus_range; + struct of_pci_range range; + struct of_pci_range_parser parser; + char range_type[4]; + int err; + + if (io_base) + *io_base = (resource_size_t)OF_BAD_ADDR; + + bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL); + if (!bus_range) + return -ENOMEM; + + pr_info("host bridge %pOF ranges:\n", dev); + + err = of_pci_parse_bus_range(dev, bus_range); + if (err) { + bus_range->start = busno; + bus_range->end = bus_max; + bus_range->flags = IORESOURCE_BUS; + pr_info(" No bus range found for %pOF, using %pR\n", + dev, bus_range); + } else { + if (bus_range->end > bus_range->start + bus_max) + bus_range->end = bus_range->start + bus_max; + } + pci_add_resource(resources, bus_range); + + /* Check for ranges property */ + err = of_pci_range_parser_init(&parser, dev); + if (err) + goto parse_failed; + + pr_debug("Parsing ranges property...\n"); + for_each_of_pci_range(&parser, &range) { + /* Read next ranges element */ + if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO) + snprintf(range_type, 4, " IO"); + else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM) + snprintf(range_type, 4, "MEM"); + else + snprintf(range_type, 4, "err"); + pr_info(" %s %#010llx..%#010llx -> %#010llx\n", range_type, + range.cpu_addr, range.cpu_addr + range.size - 1, + range.pci_addr); + + /* + * If we failed translation or got a zero-sized region + * then skip this range + */ + if (range.cpu_addr == OF_BAD_ADDR || range.size == 0) + continue; + + res = kzalloc(sizeof(struct resource), GFP_KERNEL); + if (!res) { + err = -ENOMEM; + goto parse_failed; + } + + err = of_pci_range_to_resource(&range, dev, res); + if (err) { + kfree(res); + continue; + } + + if (resource_type(res) == IORESOURCE_IO) { + if (!io_base) { + pr_err("I/O range found for %pOF. Please provide an io_base pointer to save CPU base address\n", + dev); + err = -EINVAL; + goto conversion_failed; + } + if (*io_base != (resource_size_t)OF_BAD_ADDR) + pr_warn("More than one I/O resource converted for %pOF. CPU base address for old range lost!\n", + dev); + *io_base = range.cpu_addr; + } + + pci_add_resource_offset(resources, res, res->start - range.pci_addr); + } + + return 0; + +conversion_failed: + kfree(res); +parse_failed: + resource_list_for_each_entry(window, resources) + kfree(window->res); + pci_free_resource_list(resources); + return err; +} +EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources); +#endif /* CONFIG_OF_ADDRESS */ + +/** + * of_pci_map_rid - Translate a requester ID through a downstream mapping. + * @np: root complex device node. + * @rid: PCI requester ID to map. + * @map_name: property name of the map to use. + * @map_mask_name: optional property name of the mask to use. + * @target: optional pointer to a target device node. + * @id_out: optional pointer to receive the translated ID. + * + * Given a PCI requester ID, look up the appropriate implementation-defined + * platform ID and/or the target device which receives transactions on that + * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or + * @id_out may be NULL if only the other is required. If @target points to + * a non-NULL device node pointer, only entries targeting that node will be + * matched; if it points to a NULL value, it will receive the device node of + * the first matching target phandle, with a reference held. + * + * Return: 0 on success or a standard error code on failure. + */ +int of_pci_map_rid(struct device_node *np, u32 rid, + const char *map_name, const char *map_mask_name, + struct device_node **target, u32 *id_out) +{ + u32 map_mask, masked_rid; + int map_len; + const __be32 *map = NULL; + + if (!np || !map_name || (!target && !id_out)) + return -EINVAL; + + map = of_get_property(np, map_name, &map_len); + if (!map) { + if (target) + return -ENODEV; + /* Otherwise, no map implies no translation */ + *id_out = rid; + return 0; + } + + if (!map_len || map_len % (4 * sizeof(*map))) { + pr_err("%pOF: Error: Bad %s length: %d\n", np, + map_name, map_len); + return -EINVAL; + } + + /* The default is to select all bits. */ + map_mask = 0xffffffff; + + /* + * Can be overridden by "{iommu,msi}-map-mask" property. + * If of_property_read_u32() fails, the default is used. + */ + if (map_mask_name) + of_property_read_u32(np, map_mask_name, &map_mask); + + masked_rid = map_mask & rid; + for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) { + struct device_node *phandle_node; + u32 rid_base = be32_to_cpup(map + 0); + u32 phandle = be32_to_cpup(map + 1); + u32 out_base = be32_to_cpup(map + 2); + u32 rid_len = be32_to_cpup(map + 3); + + if (rid_base & ~map_mask) { + pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores rid-base (0x%x)\n", + np, map_name, map_name, + map_mask, rid_base); + return -EFAULT; + } + + if (masked_rid < rid_base || masked_rid >= rid_base + rid_len) + continue; + + phandle_node = of_find_node_by_phandle(phandle); + if (!phandle_node) + return -ENODEV; + + if (target) { + if (*target) + of_node_put(phandle_node); + else + *target = phandle_node; + + if (*target != phandle_node) + continue; + } + + if (id_out) + *id_out = masked_rid - rid_base + out_base; + + pr_debug("%pOF: %s, using mask %08x, rid-base: %08x, out-base: %08x, length: %08x, rid: %08x -> %08x\n", + np, map_name, map_mask, rid_base, out_base, + rid_len, rid, masked_rid - rid_base + out_base); + return 0; + } + + pr_err("%pOF: Invalid %s translation - no match for rid 0x%x on %pOF\n", + np, map_name, rid, target && *target ? *target : NULL); + return -EFAULT; +} + +#if IS_ENABLED(CONFIG_OF_IRQ) +/** + * of_irq_parse_pci - Resolve the interrupt for a PCI device + * @pdev: the device whose interrupt is to be resolved + * @out_irq: structure of_irq filled by this function + * + * This function resolves the PCI interrupt for a given PCI device. If a + * device-node exists for a given pci_dev, it will use normal OF tree + * walking. If not, it will implement standard swizzling and walk up the + * PCI tree until an device-node is found, at which point it will finish + * resolving using the OF tree walking. + */ +static int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq) +{ + struct device_node *dn, *ppnode; + struct pci_dev *ppdev; + __be32 laddr[3]; + u8 pin; + int rc; + + /* + * Check if we have a device node, if yes, fallback to standard + * device tree parsing + */ + dn = pci_device_to_OF_node(pdev); + if (dn) { + rc = of_irq_parse_one(dn, 0, out_irq); + if (!rc) + return rc; + } + + /* + * Ok, we don't, time to have fun. Let's start by building up an + * interrupt spec. we assume #interrupt-cells is 1, which is standard + * for PCI. If you do different, then don't use that routine. + */ + rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); + if (rc != 0) + goto err; + /* No pin, exit with no error message. */ + if (pin == 0) + return -ENODEV; + + /* Now we walk up the PCI tree */ + for (;;) { + /* Get the pci_dev of our parent */ + ppdev = pdev->bus->self; + + /* Ouch, it's a host bridge... */ + if (ppdev == NULL) { + ppnode = pci_bus_to_OF_node(pdev->bus); + + /* No node for host bridge ? give up */ + if (ppnode == NULL) { + rc = -EINVAL; + goto err; + } + } else { + /* We found a P2P bridge, check if it has a node */ + ppnode = pci_device_to_OF_node(ppdev); + } + + /* + * Ok, we have found a parent with a device-node, hand over to + * the OF parsing code. + * We build a unit address from the linux device to be used for + * resolution. Note that we use the linux bus number which may + * not match your firmware bus numbering. + * Fortunately, in most cases, interrupt-map-mask doesn't + * include the bus number as part of the matching. + * You should still be careful about that though if you intend + * to rely on this function (you ship a firmware that doesn't + * create device nodes for all PCI devices). + */ + if (ppnode) + break; + + /* + * We can only get here if we hit a P2P bridge with no node; + * let's do standard swizzling and try again + */ + pin = pci_swizzle_interrupt_pin(pdev, pin); + pdev = ppdev; + } + + out_irq->np = ppnode; + out_irq->args_count = 1; + out_irq->args[0] = pin; + laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); + laddr[1] = laddr[2] = cpu_to_be32(0); + rc = of_irq_parse_raw(laddr, out_irq); + if (rc) + goto err; + return 0; +err: + if (rc == -ENOENT) { + dev_warn(&pdev->dev, + "%s: no interrupt-map found, INTx interrupts not available\n", + __func__); + pr_warn_once("%s: possibly some PCI slots don't have level triggered interrupts capability\n", + __func__); + } else { + dev_err(&pdev->dev, "%s: failed with rc=%d\n", __func__, rc); + } + return rc; +} + +/** + * of_irq_parse_and_map_pci() - Decode a PCI IRQ from the device tree and map to a VIRQ + * @dev: The PCI device needing an IRQ + * @slot: PCI slot number; passed when used as map_irq callback. Unused + * @pin: PCI IRQ pin number; passed when used as map_irq callback. Unused + * + * @slot and @pin are unused, but included in the function so that this + * function can be used directly as the map_irq callback to + * pci_assign_irq() and struct pci_host_bridge.map_irq pointer + */ +int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin) +{ + struct of_phandle_args oirq; + int ret; + + ret = of_irq_parse_pci(dev, &oirq); + if (ret) + return 0; /* Proper return code 0 == NO_IRQ */ + + return irq_create_of_mapping(&oirq); +} +EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci); +#endif /* CONFIG_OF_IRQ */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4a7c6864fdf4..6112dd8d68b6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3066,6 +3066,81 @@ int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size) } /** + * pci_enable_atomic_ops_to_root - enable AtomicOp requests to root port + * @dev: the PCI device + * @cap_mask: mask of desired AtomicOp sizes, including one or more of: + * PCI_EXP_DEVCAP2_ATOMIC_COMP32 + * PCI_EXP_DEVCAP2_ATOMIC_COMP64 + * PCI_EXP_DEVCAP2_ATOMIC_COMP128 + * + * Return 0 if all upstream bridges support AtomicOp routing, egress + * blocking is disabled on all upstream ports, and the root port supports + * the requested completion capabilities (32-bit, 64-bit and/or 128-bit + * AtomicOp completion), or negative otherwise. + */ +int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask) +{ + struct pci_bus *bus = dev->bus; + struct pci_dev *bridge; + u32 cap, ctl2; + + if (!pci_is_pcie(dev)) + return -EINVAL; + + /* + * Per PCIe r4.0, sec 6.15, endpoints and root ports may be + * AtomicOp requesters. For now, we only support endpoints as + * requesters and root ports as completers. No endpoints as + * completers, and no peer-to-peer. + */ + + switch (pci_pcie_type(dev)) { + case PCI_EXP_TYPE_ENDPOINT: + case PCI_EXP_TYPE_LEG_END: + case PCI_EXP_TYPE_RC_END: + break; + default: + return -EINVAL; + } + + while (bus->parent) { + bridge = bus->self; + + pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap); + + switch (pci_pcie_type(bridge)) { + /* Ensure switch ports support AtomicOp routing */ + case PCI_EXP_TYPE_UPSTREAM: + case PCI_EXP_TYPE_DOWNSTREAM: + if (!(cap & PCI_EXP_DEVCAP2_ATOMIC_ROUTE)) + return -EINVAL; + break; + + /* Ensure root port supports all the sizes we care about */ + case PCI_EXP_TYPE_ROOT_PORT: + if ((cap & cap_mask) != cap_mask) + return -EINVAL; + break; + } + + /* Ensure upstream ports don't block AtomicOps on egress */ + if (!bridge->has_secondary_link) { + pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, + &ctl2); + if (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK) + return -EINVAL; + } + + bus = bus->parent; + } + + pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, + PCI_EXP_DEVCTL2_ATOMIC_REQ); + return 0; +} +EXPORT_SYMBOL(pci_enable_atomic_ops_to_root); + +/** * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge * @dev: the PCI device * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index f6b58b32a67c..e90009fff1a9 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -342,6 +342,26 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, void pci_enable_acs(struct pci_dev *dev); +#ifdef CONFIG_PCIEASPM +void pcie_aspm_init_link_state(struct pci_dev *pdev); +void pcie_aspm_exit_link_state(struct pci_dev *pdev); +void pcie_aspm_pm_state_change(struct pci_dev *pdev); +void pcie_aspm_powersave_config_link(struct pci_dev *pdev); +#else +static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) { } +static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) { } +static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) { } +static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) { } +#endif + +#ifdef CONFIG_PCIEASPM_DEBUG +void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev); +void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev); +#else +static inline void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) { } +static inline void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) { } +#endif + #ifdef CONFIG_PCIE_PTM void pci_ptm_init(struct pci_dev *dev); #else diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index ac53edbc9613..d658dfa53b87 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -92,7 +92,7 @@ config PCIE_PME config PCIE_DPC bool "PCIe Downstream Port Containment support" - depends on PCIEPORTBUS + depends on PCIEPORTBUS && PCIEAER default n help This enables PCI Express Downstream Port Containment (DPC) diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 744805232155..92ec13a09a2a 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -633,7 +633,8 @@ static void aer_recover_work_func(struct work_struct *work) continue; } cper_print_aer(pdev, entry.severity, entry.regs); - do_recovery(pdev, entry.severity); + if (entry.severity != AER_CORRECTABLE) + do_recovery(pdev, entry.severity); pci_dev_put(pdev); } } @@ -660,7 +661,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) /* The device might not support AER */ if (!pos) - return 1; + return 0; if (info->severity == AER_CORRECTABLE) { pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 9783e10da3a9..3b9b4d50cd98 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -43,18 +43,6 @@ #define ASPM_STATE_ALL (ASPM_STATE_L0S | ASPM_STATE_L1 | \ ASPM_STATE_L1SS) -/* - * When L1 substates are enabled, the LTR L1.2 threshold is a timing parameter - * that decides whether L1.1 or L1.2 is entered (Refer PCIe spec for details). - * Not sure is there is a way to "calculate" this on the fly, but maybe we - * could turn it into a parameter in future. This value has been taken from - * the following files from Intel's coreboot (which is the only code I found - * to have used this): - * https://www.coreboot.org/pipermail/coreboot-gerrit/2015-March/021134.html - * https://review.coreboot.org/#/c/8832/ - */ -#define LTR_L1_2_THRESHOLD_BITS ((1 << 21) | (1 << 23) | (1 << 30)) - struct aspm_latency { u32 l0s; /* L0s latency (nsec) */ u32 l1; /* L1 latency (nsec) */ @@ -333,6 +321,32 @@ static u32 calc_l1ss_pwron(struct pci_dev *pdev, u32 scale, u32 val) return 0; } +static void encode_l12_threshold(u32 threshold_us, u32 *scale, u32 *value) +{ + u64 threshold_ns = threshold_us * 1000; + + /* See PCIe r3.1, sec 7.33.3 and sec 6.18 */ + if (threshold_ns < 32) { + *scale = 0; + *value = threshold_ns; + } else if (threshold_ns < 1024) { + *scale = 1; + *value = threshold_ns >> 5; + } else if (threshold_ns < 32768) { + *scale = 2; + *value = threshold_ns >> 10; + } else if (threshold_ns < 1048576) { + *scale = 3; + *value = threshold_ns >> 15; + } else if (threshold_ns < 33554432) { + *scale = 4; + *value = threshold_ns >> 20; + } else { + *scale = 5; + *value = threshold_ns >> 25; + } +} + struct aspm_register_info { u32 support:2; u32 enabled:2; @@ -443,6 +457,7 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link, struct aspm_register_info *dwreg) { u32 val1, val2, scale1, scale2; + u32 t_common_mode, t_power_on, l1_2_threshold, scale, value; link->l1ss.up_cap_ptr = upreg->l1ss_cap_ptr; link->l1ss.dw_cap_ptr = dwreg->l1ss_cap_ptr; @@ -454,16 +469,7 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link, /* Choose the greater of the two Port Common_Mode_Restore_Times */ val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; val2 = (dwreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; - if (val1 > val2) - link->l1ss.ctl1 |= val1 << 8; - else - link->l1ss.ctl1 |= val2 << 8; - - /* - * We currently use LTR L1.2 threshold to be fixed constant picked from - * Intel's coreboot. - */ - link->l1ss.ctl1 |= LTR_L1_2_THRESHOLD_BITS; + t_common_mode = max(val1, val2); /* Choose the greater of the two Port T_POWER_ON times */ val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19; @@ -472,10 +478,27 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link, scale2 = (dwreg->l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16; if (calc_l1ss_pwron(link->pdev, scale1, val1) > - calc_l1ss_pwron(link->downstream, scale2, val2)) + calc_l1ss_pwron(link->downstream, scale2, val2)) { link->l1ss.ctl2 |= scale1 | (val1 << 3); - else + t_power_on = calc_l1ss_pwron(link->pdev, scale1, val1); + } else { link->l1ss.ctl2 |= scale2 | (val2 << 3); + t_power_on = calc_l1ss_pwron(link->downstream, scale2, val2); + } + + /* + * Set LTR_L1.2_THRESHOLD to the time required to transition the + * Link from L0 to L1.2 and back to L0 so we enter L1.2 only if + * downstream devices report (via LTR) that they can tolerate at + * least that much latency. + * + * Based on PCIe r3.1, sec 5.5.3.3.1, Figures 5-16 and 5-17, and + * Table 5-11. T(POWER_OFF) is at most 2us and T(L1.2) is at + * least 4us. + */ + l1_2_threshold = 2 + 4 + t_common_mode + t_power_on; + encode_l12_threshold(l1_2_threshold, &scale, &value); + link->l1ss.ctl1 |= t_common_mode << 8 | scale << 29 | value << 16; } static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) diff --git a/drivers/pci/pcie/pcie-dpc.c b/drivers/pci/pcie/pcie-dpc.c index 2d976a623ddc..7eb9bc7d4bfd 100644 --- a/drivers/pci/pcie/pcie-dpc.c +++ b/drivers/pci/pcie/pcie-dpc.c @@ -15,34 +15,15 @@ #include <linux/pci.h> #include <linux/pcieport_if.h> #include "../pci.h" - -struct rp_pio_header_log_regs { - u32 dw0; - u32 dw1; - u32 dw2; - u32 dw3; -}; - -struct dpc_rp_pio_regs { - u32 status; - u32 mask; - u32 severity; - u32 syserror; - u32 exception; - - struct rp_pio_header_log_regs header_log; - u32 impspec_log; - u32 tlp_prefix_log[4]; - u32 log_size; - u16 first_error; -}; +#include "aer/aerdrv.h" struct dpc_dev { struct pcie_device *dev; struct work_struct work; - int cap_pos; - bool rp; + u16 cap_pos; + bool rp_extensions; u32 rp_pio_status; + u8 rp_log_size; }; static const char * const rp_pio_error_string[] = { @@ -72,13 +53,13 @@ static int dpc_wait_rp_inactive(struct dpc_dev *dpc) unsigned long timeout = jiffies + HZ; struct pci_dev *pdev = dpc->dev->port; struct device *dev = &dpc->dev->device; - u16 status; + u16 cap = dpc->cap_pos, status; - pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_STATUS, &status); + pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); while (status & PCI_EXP_DPC_RP_BUSY && !time_after(jiffies, timeout)) { msleep(10); - pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_STATUS, &status); + pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); } if (status & PCI_EXP_DPC_RP_BUSY) { dev_warn(dev, "DPC root port still busy\n"); @@ -104,11 +85,12 @@ static void dpc_wait_link_inactive(struct dpc_dev *dpc) dev_warn(dev, "Link state not disabled for DPC event\n"); } -static void interrupt_event_handler(struct work_struct *work) +static void dpc_work(struct work_struct *work) { struct dpc_dev *dpc = container_of(work, struct dpc_dev, work); struct pci_dev *dev, *temp, *pdev = dpc->dev->port; struct pci_bus *parent = pdev->subordinate; + u16 cap = dpc->cap_pos, ctl; pci_lock_rescan_remove(); list_for_each_entry_safe_reverse(dev, temp, &parent->devices, @@ -124,159 +106,127 @@ static void interrupt_event_handler(struct work_struct *work) pci_unlock_rescan_remove(); dpc_wait_link_inactive(dpc); - if (dpc->rp && dpc_wait_rp_inactive(dpc)) + if (dpc->rp_extensions && dpc_wait_rp_inactive(dpc)) return; - if (dpc->rp && dpc->rp_pio_status) { - pci_write_config_dword(pdev, - dpc->cap_pos + PCI_EXP_DPC_RP_PIO_STATUS, - dpc->rp_pio_status); + if (dpc->rp_extensions && dpc->rp_pio_status) { + pci_write_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, + dpc->rp_pio_status); dpc->rp_pio_status = 0; } - pci_write_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_STATUS, + pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_TRIGGER | PCI_EXP_DPC_STATUS_INTERRUPT); -} -static void dpc_rp_pio_print_tlp_header(struct device *dev, - struct rp_pio_header_log_regs *t) -{ - dev_err(dev, "TLP Header: %#010x %#010x %#010x %#010x\n", - t->dw0, t->dw1, t->dw2, t->dw3); + pci_read_config_word(pdev, cap + PCI_EXP_DPC_CTL, &ctl); + pci_write_config_word(pdev, cap + PCI_EXP_DPC_CTL, + ctl | PCI_EXP_DPC_CTL_INT_EN); } -static void dpc_rp_pio_print_error(struct dpc_dev *dpc, - struct dpc_rp_pio_regs *rp_pio) +static void dpc_process_rp_pio_error(struct dpc_dev *dpc) { struct device *dev = &dpc->dev->device; + struct pci_dev *pdev = dpc->dev->port; + u16 cap = dpc->cap_pos, dpc_status, first_error; + u32 status, mask, sev, syserr, exc, dw0, dw1, dw2, dw3, log, prefix; int i; - u32 status; + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, &status); + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_MASK, &mask); dev_err(dev, "rp_pio_status: %#010x, rp_pio_mask: %#010x\n", - rp_pio->status, rp_pio->mask); + status, mask); + + dpc->rp_pio_status = status; + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_SEVERITY, &sev); + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_SYSERROR, &syserr); + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_EXCEPTION, &exc); dev_err(dev, "RP PIO severity=%#010x, syserror=%#010x, exception=%#010x\n", - rp_pio->severity, rp_pio->syserror, rp_pio->exception); + sev, syserr, exc); - status = (rp_pio->status & ~rp_pio->mask); + /* Get First Error Pointer */ + pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &dpc_status); + first_error = (dpc_status & 0x1f00) >> 8; + status &= ~mask; for (i = 0; i < ARRAY_SIZE(rp_pio_error_string); i++) { - if (!(status & (1 << i))) - continue; - - dev_err(dev, "[%2d] %s%s\n", i, rp_pio_error_string[i], - rp_pio->first_error == i ? " (First)" : ""); + if (status & (1 << i)) + dev_err(dev, "[%2d] %s%s\n", i, rp_pio_error_string[i], + first_error == i ? " (First)" : ""); } - dpc_rp_pio_print_tlp_header(dev, &rp_pio->header_log); - if (rp_pio->log_size == 4) + if (dpc->rp_log_size < 4) return; - dev_err(dev, "RP PIO ImpSpec Log %#010x\n", rp_pio->impspec_log); + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG, + &dw0); + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 4, + &dw1); + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 8, + &dw2); + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 12, + &dw3); + dev_err(dev, "TLP Header: %#010x %#010x %#010x %#010x\n", + dw0, dw1, dw2, dw3); - for (i = 0; i < rp_pio->log_size - 5; i++) - dev_err(dev, "TLP Prefix Header: dw%d, %#010x\n", i, - rp_pio->tlp_prefix_log[i]); + if (dpc->rp_log_size < 5) + return; + pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_IMPSPEC_LOG, &log); + dev_err(dev, "RP PIO ImpSpec Log %#010x\n", log); + + for (i = 0; i < dpc->rp_log_size - 5; i++) { + pci_read_config_dword(pdev, + cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG, &prefix); + dev_err(dev, "TLP Prefix Header: dw%d, %#010x\n", i, prefix); + } } -static void dpc_rp_pio_get_info(struct dpc_dev *dpc, - struct dpc_rp_pio_regs *rp_pio) +static irqreturn_t dpc_irq(int irq, void *context) { + struct dpc_dev *dpc = (struct dpc_dev *)context; struct pci_dev *pdev = dpc->dev->port; struct device *dev = &dpc->dev->device; - int i; - u16 cap; - u16 status; - - pci_read_config_dword(pdev, dpc->cap_pos + PCI_EXP_DPC_RP_PIO_STATUS, - &rp_pio->status); - pci_read_config_dword(pdev, dpc->cap_pos + PCI_EXP_DPC_RP_PIO_MASK, - &rp_pio->mask); - - pci_read_config_dword(pdev, dpc->cap_pos + PCI_EXP_DPC_RP_PIO_SEVERITY, - &rp_pio->severity); - pci_read_config_dword(pdev, dpc->cap_pos + PCI_EXP_DPC_RP_PIO_SYSERROR, - &rp_pio->syserror); - pci_read_config_dword(pdev, dpc->cap_pos + PCI_EXP_DPC_RP_PIO_EXCEPTION, - &rp_pio->exception); + u16 cap = dpc->cap_pos, ctl, status, source, reason, ext_reason; - /* Get First Error Pointer */ - pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_STATUS, &status); - rp_pio->first_error = (status & 0x1f00) >> 8; + pci_read_config_word(pdev, cap + PCI_EXP_DPC_CTL, &ctl); - pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CAP, &cap); - rp_pio->log_size = (cap & PCI_EXP_DPC_RP_PIO_LOG_SIZE) >> 8; - if (rp_pio->log_size < 4 || rp_pio->log_size > 9) { - dev_err(dev, "RP PIO log size %u is invalid\n", - rp_pio->log_size); - return; - } - - pci_read_config_dword(pdev, - dpc->cap_pos + PCI_EXP_DPC_RP_PIO_HEADER_LOG, - &rp_pio->header_log.dw0); - pci_read_config_dword(pdev, - dpc->cap_pos + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 4, - &rp_pio->header_log.dw1); - pci_read_config_dword(pdev, - dpc->cap_pos + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 8, - &rp_pio->header_log.dw2); - pci_read_config_dword(pdev, - dpc->cap_pos + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 12, - &rp_pio->header_log.dw3); - if (rp_pio->log_size == 4) - return; - - pci_read_config_dword(pdev, - dpc->cap_pos + PCI_EXP_DPC_RP_PIO_IMPSPEC_LOG, - &rp_pio->impspec_log); - for (i = 0; i < rp_pio->log_size - 5; i++) - pci_read_config_dword(pdev, - dpc->cap_pos + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG, - &rp_pio->tlp_prefix_log[i]); -} + if (!(ctl & PCI_EXP_DPC_CTL_INT_EN) || ctl == (u16)(~0)) + return IRQ_NONE; -static void dpc_process_rp_pio_error(struct dpc_dev *dpc) -{ - struct dpc_rp_pio_regs rp_pio_regs; + pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); - dpc_rp_pio_get_info(dpc, &rp_pio_regs); - dpc_rp_pio_print_error(dpc, &rp_pio_regs); + if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT)) + return IRQ_NONE; - dpc->rp_pio_status = rp_pio_regs.status; -} + if (!(status & PCI_EXP_DPC_STATUS_TRIGGER)) { + pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, + PCI_EXP_DPC_STATUS_INTERRUPT); + return IRQ_HANDLED; + } -static irqreturn_t dpc_irq(int irq, void *context) -{ - struct dpc_dev *dpc = (struct dpc_dev *)context; - struct pci_dev *pdev = dpc->dev->port; - struct device *dev = &dpc->dev->device; - u16 status, source; + pci_write_config_word(pdev, cap + PCI_EXP_DPC_CTL, + ctl & ~PCI_EXP_DPC_CTL_INT_EN); - pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_STATUS, &status); - pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_SOURCE_ID, + pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID, &source); - if (!status || status == (u16)(~0)) - return IRQ_NONE; dev_info(dev, "DPC containment event, status:%#06x source:%#06x\n", status, source); - if (status & PCI_EXP_DPC_STATUS_TRIGGER) { - u16 reason = (status >> 1) & 0x3; - u16 ext_reason = (status >> 5) & 0x3; - - dev_warn(dev, "DPC %s detected, remove downstream devices\n", - (reason == 0) ? "unmasked uncorrectable error" : - (reason == 1) ? "ERR_NONFATAL" : - (reason == 2) ? "ERR_FATAL" : - (ext_reason == 0) ? "RP PIO error" : - (ext_reason == 1) ? "software trigger" : - "reserved error"); - /* show RP PIO error detail information */ - if (reason == 3 && ext_reason == 0) - dpc_process_rp_pio_error(dpc); - - schedule_work(&dpc->work); - } + reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN) >> 1; + ext_reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT) >> 5; + + dev_warn(dev, "DPC %s detected, remove downstream devices\n", + (reason == 0) ? "unmasked uncorrectable error" : + (reason == 1) ? "ERR_NONFATAL" : + (reason == 2) ? "ERR_FATAL" : + (ext_reason == 0) ? "RP PIO error" : + (ext_reason == 1) ? "software trigger" : + "reserved error"); + /* show RP PIO error detail information */ + if (dpc->rp_extensions && reason == 3 && ext_reason == 0) + dpc_process_rp_pio_error(dpc); + + schedule_work(&dpc->work); + return IRQ_HANDLED; } @@ -289,13 +239,16 @@ static int dpc_probe(struct pcie_device *dev) int status; u16 ctl, cap; + if (pcie_aer_get_firmware_first(pdev)) + return -ENOTSUPP; + dpc = devm_kzalloc(device, sizeof(*dpc), GFP_KERNEL); if (!dpc) return -ENOMEM; dpc->cap_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DPC); dpc->dev = dev; - INIT_WORK(&dpc->work, interrupt_event_handler); + INIT_WORK(&dpc->work, dpc_work); set_service_data(dev, dpc); status = devm_request_irq(device, dev->irq, dpc_irq, IRQF_SHARED, @@ -309,15 +262,23 @@ static int dpc_probe(struct pcie_device *dev) pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CAP, &cap); pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, &ctl); - dpc->rp = (cap & PCI_EXP_DPC_CAP_RP_EXT); + dpc->rp_extensions = (cap & PCI_EXP_DPC_CAP_RP_EXT); + if (dpc->rp_extensions) { + dpc->rp_log_size = (cap & PCI_EXP_DPC_RP_PIO_LOG_SIZE) >> 8; + if (dpc->rp_log_size < 4 || dpc->rp_log_size > 9) { + dev_err(device, "RP PIO log size %u is invalid\n", + dpc->rp_log_size); + dpc->rp_log_size = 0; + } + } ctl = (ctl & 0xfff4) | PCI_EXP_DPC_CTL_EN_NONFATAL | PCI_EXP_DPC_CTL_INT_EN; pci_write_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, ctl); dev_info(device, "DPC error containment capabilities: Int Msg #%d, RPExt%c PoisonedTLP%c SwTrigger%c RP PIO Log %d, DL_ActiveErr%c\n", - cap & 0xf, FLAG(cap, PCI_EXP_DPC_CAP_RP_EXT), + cap & PCI_EXP_DPC_IRQ, FLAG(cap, PCI_EXP_DPC_CAP_RP_EXT), FLAG(cap, PCI_EXP_DPC_CAP_POISONED_TLP), - FLAG(cap, PCI_EXP_DPC_CAP_SW_TRIGGER), (cap >> 8) & 0xf, + FLAG(cap, PCI_EXP_DPC_CAP_SW_TRIGGER), dpc->rp_log_size, FLAG(cap, PCI_EXP_DPC_CAP_DL_ACTIVE)); return status; } diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index a59210350c44..ef3bad4ad010 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -216,9 +216,9 @@ static int get_port_device_capability(struct pci_dev *dev) return 0; cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP - | PCIE_PORT_SERVICE_VC | PCIE_PORT_SERVICE_DPC; + | PCIE_PORT_SERVICE_VC; if (pci_aer_available()) - cap_mask |= PCIE_PORT_SERVICE_AER; + cap_mask |= PCIE_PORT_SERVICE_AER | PCIE_PORT_SERVICE_DPC; if (pcie_ports_auto) pcie_port_platform_notify(dev, &cap_mask); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 14e0ea1ff38b..070476036846 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1875,6 +1875,38 @@ static void pci_configure_relaxed_ordering(struct pci_dev *dev) } } +static void pci_configure_ltr(struct pci_dev *dev) +{ +#ifdef CONFIG_PCIEASPM + u32 cap; + struct pci_dev *bridge; + + if (!pci_is_pcie(dev)) + return; + + pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap); + if (!(cap & PCI_EXP_DEVCAP2_LTR)) + return; + + /* + * Software must not enable LTR in an Endpoint unless the Root + * Complex and all intermediate Switches indicate support for LTR. + * PCIe r3.1, sec 6.18. + */ + if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) + dev->ltr_path = 1; + else { + bridge = pci_upstream_bridge(dev); + if (bridge && bridge->ltr_path) + dev->ltr_path = 1; + } + + if (dev->ltr_path) + pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, + PCI_EXP_DEVCTL2_LTR_EN); +#endif +} + static void pci_configure_device(struct pci_dev *dev) { struct hotplug_params hpp; @@ -1883,6 +1915,7 @@ static void pci_configure_device(struct pci_dev *dev) pci_configure_mps(dev); pci_configure_extended_tags(dev, NULL); pci_configure_relaxed_ordering(dev); + pci_configure_ltr(dev); memset(&hpp, 0, sizeof(hpp)); ret = pci_get_hp_params(dev, &hpp); @@ -2215,22 +2248,27 @@ static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn) static int only_one_child(struct pci_bus *bus) { - struct pci_dev *parent = bus->self; + struct pci_dev *bridge = bus->self; - if (!parent || !pci_is_pcie(parent)) + /* + * Systems with unusual topologies set PCI_SCAN_ALL_PCIE_DEVS so + * we scan for all possible devices, not just Device 0. + */ + if (pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS)) return 0; - if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT) - return 1; /* - * PCIe downstream ports are bridges that normally lead to only a - * device 0, but if PCI_SCAN_ALL_PCIE_DEVS is set, scan all - * possible devices, not just device 0. See PCIe spec r3.0, - * sec 7.3.1. + * A PCIe Downstream Port normally leads to a Link with only Device + * 0 on it (PCIe spec r3.1, sec 7.3.1). As an optimization, scan + * only for Device 0 in that situation. + * + * Checking has_secondary_link is a hack to identify Downstream + * Ports because sometimes Switches are configured such that the + * PCIe Port Type labels are backwards. */ - if (parent->has_secondary_link && - !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS)) + if (bridge && pci_is_pcie(bridge) && bridge->has_secondary_link) return 1; + return 0; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 10684b17d0bd..24e9a148e734 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2699,7 +2699,8 @@ static void __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all) * HT MSI mapping should be disabled on devices that are below * a non-Hypertransport host bridge. Locate the host bridge... */ - host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); + host_bridge = pci_get_domain_bus_and_slot(pci_domain_nr(dev->bus), 0, + PCI_DEVFN(0, 0)); if (host_bridge == NULL) { dev_warn(&dev->dev, "nv_msi_ht_cap_quirk didn't locate host bridge\n"); return; diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c index 83efa001c2e7..e725f99b5479 100644 --- a/drivers/pci/syscall.c +++ b/drivers/pci/syscall.c @@ -28,7 +28,7 @@ SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn, return -EPERM; err = -ENODEV; - dev = pci_get_bus_and_slot(bus, dfn); + dev = pci_get_domain_bus_and_slot(0, bus, dfn); if (!dev) goto error; @@ -96,7 +96,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - dev = pci_get_bus_and_slot(bus, dfn); + dev = pci_get_domain_bus_and_slot(0, bus, dfn); if (!dev) return -ENODEV; diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index 8fc2e9532575..94b25b552254 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -595,6 +595,7 @@ static pci_ers_result_t pcifront_common_process(int cmd, struct pci_driver *pdrv; int bus = pdev->sh_info->aer_op.bus; int devfn = pdev->sh_info->aer_op.devfn; + int domain = pdev->sh_info->aer_op.domain; struct pci_dev *pcidev; int flag = 0; @@ -603,7 +604,7 @@ static pci_ers_result_t pcifront_common_process(int cmd, cmd, bus, devfn); result = PCI_ERS_RESULT_NONE; - pcidev = pci_get_bus_and_slot(bus, devfn); + pcidev = pci_get_domain_bus_and_slot(domain, bus, devfn); if (!pcidev || !pcidev->driver) { dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); pci_dev_put(pcidev); diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 2c2e6a3b4c7e..7b31f19ade83 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -251,8 +251,9 @@ static int oprompci2node(void __user *argp, struct device_node *dp, struct openp struct pci_dev *pdev; struct device_node *dp; - pdev = pci_get_bus_and_slot (((int *) op->oprom_array)[0], - ((int *) op->oprom_array)[1]); + pdev = pci_get_domain_bus_and_slot(0, + ((int *) op->oprom_array)[0], + ((int *) op->oprom_array)[1]); dp = pci_device_to_OF_node(pdev); data->current_node = dp; diff --git a/drivers/video/fbdev/intelfb/intelfbhw.c b/drivers/video/fbdev/intelfb/intelfbhw.c index 83fec573cceb..57aff7450bce 100644 --- a/drivers/video/fbdev/intelfb/intelfbhw.c +++ b/drivers/video/fbdev/intelfb/intelfbhw.c @@ -181,7 +181,9 @@ int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, return 1; /* Find the bridge device. It is always 0:0.0 */ - if (!(bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)))) { + bridge_dev = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), 0, + PCI_DEVFN(0, 0)); + if (!bridge_dev) { ERR_MSG("cannot find bridge device\n"); return 1; } diff --git a/drivers/video/fbdev/nvidia/nv_hw.c b/drivers/video/fbdev/nvidia/nv_hw.c index 81c80ac3c76f..8335da4ca30e 100644 --- a/drivers/video/fbdev/nvidia/nv_hw.c +++ b/drivers/video/fbdev/nvidia/nv_hw.c @@ -683,10 +683,11 @@ static void nForceUpdateArbitrationSettings(unsigned VClk, nv10_sim_state sim_data; unsigned int M, N, P, pll, MClk, NVClk, memctrl; struct pci_dev *dev; + int domain = pci_domain_nr(par->pci_dev->bus); if ((par->Chipset & 0x0FF0) == 0x01A0) { unsigned int uMClkPostDiv; - dev = pci_get_bus_and_slot(0, 3); + dev = pci_get_domain_bus_and_slot(domain, 0, 3); pci_read_config_dword(dev, 0x6C, &uMClkPostDiv); uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf; @@ -694,7 +695,7 @@ static void nForceUpdateArbitrationSettings(unsigned VClk, uMClkPostDiv = 4; MClk = 400000 / uMClkPostDiv; } else { - dev = pci_get_bus_and_slot(0, 5); + dev = pci_get_domain_bus_and_slot(domain, 0, 5); pci_read_config_dword(dev, 0x4c, &MClk); MClk /= 1000; } @@ -707,13 +708,13 @@ static void nForceUpdateArbitrationSettings(unsigned VClk, sim_data.pix_bpp = (char)pixelDepth; sim_data.enable_video = 0; sim_data.enable_mp = 0; - dev = pci_get_bus_and_slot(0, 1); + dev = pci_get_domain_bus_and_slot(domain, 0, 1); pci_read_config_dword(dev, 0x7C, &sim_data.memory_type); pci_dev_put(dev); sim_data.memory_type = (sim_data.memory_type >> 12) & 1; sim_data.memory_width = 64; - dev = pci_get_bus_and_slot(0, 3); + dev = pci_get_domain_bus_and_slot(domain, 0, 3); pci_read_config_dword(dev, 0, &memctrl); pci_dev_put(dev); memctrl >>= 16; @@ -721,7 +722,7 @@ static void nForceUpdateArbitrationSettings(unsigned VClk, if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) { u32 dimm[3]; - dev = pci_get_bus_and_slot(0, 2); + dev = pci_get_domain_bus_and_slot(domain, 0, 2); pci_read_config_dword(dev, 0x40, &dimm[0]); dimm[0] = (dimm[0] >> 8) & 0x4f; pci_read_config_dword(dev, 0x44, &dimm[1]); diff --git a/drivers/video/fbdev/nvidia/nv_setup.c b/drivers/video/fbdev/nvidia/nv_setup.c index 2f2e162134fa..b17acd290360 100644 --- a/drivers/video/fbdev/nvidia/nv_setup.c +++ b/drivers/video/fbdev/nvidia/nv_setup.c @@ -264,7 +264,8 @@ static void nv10GetConfig(struct nvidia_par *par) } #endif - dev = pci_get_bus_and_slot(0, 1); + dev = pci_get_domain_bus_and_slot(pci_domain_nr(par->pci_dev->bus), + 0, 1); if ((par->Chipset & 0xffff) == 0x01a0) { u32 amt; diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c index 1ea78bb911fb..ff8282374f37 100644 --- a/drivers/video/fbdev/riva/fbdev.c +++ b/drivers/video/fbdev/riva/fbdev.c @@ -780,7 +780,7 @@ static int riva_load_video_mode(struct fb_info *info) else newmode.misc_output |= 0x80; - rc = CalcStateExt(&par->riva, &newmode.ext, bpp, width, + rc = CalcStateExt(&par->riva, &newmode.ext, par->pdev, bpp, width, hDisplaySize, height, dotClock); if (rc) goto out; diff --git a/drivers/video/fbdev/riva/nv_driver.c b/drivers/video/fbdev/riva/nv_driver.c index f3694cf17e58..a3d9c66973ad 100644 --- a/drivers/video/fbdev/riva/nv_driver.c +++ b/drivers/video/fbdev/riva/nv_driver.c @@ -159,6 +159,7 @@ unsigned long riva_get_memlen(struct riva_par *par) unsigned int chipset = par->Chipset; struct pci_dev* dev; u32 amt; + int domain = pci_domain_nr(par->pdev->bus); switch (chip->Architecture) { case NV_ARCH_03: @@ -226,12 +227,12 @@ unsigned long riva_get_memlen(struct riva_par *par) case NV_ARCH_30: if(chipset == NV_CHIP_IGEFORCE2) { - dev = pci_get_bus_and_slot(0, 1); + dev = pci_get_domain_bus_and_slot(domain, 0, 1); pci_read_config_dword(dev, 0x7C, &amt); pci_dev_put(dev); memlen = (((amt >> 6) & 31) + 1) * 1024; } else if (chipset == NV_CHIP_0x01F0) { - dev = pci_get_bus_and_slot(0, 1); + dev = pci_get_domain_bus_and_slot(domain, 0, 1); pci_read_config_dword(dev, 0x84, &amt); pci_dev_put(dev); memlen = (((amt >> 4) & 127) + 1) * 1024; @@ -417,6 +418,6 @@ riva_common_setup(struct riva_par *par) } par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE; - RivaGetConfig(&par->riva, par->Chipset); + RivaGetConfig(&par->riva, par->pdev, par->Chipset); } diff --git a/drivers/video/fbdev/riva/riva_hw.c b/drivers/video/fbdev/riva/riva_hw.c index 8bdf37f3013b..0601c13f2105 100644 --- a/drivers/video/fbdev/riva/riva_hw.c +++ b/drivers/video/fbdev/riva/riva_hw.c @@ -1108,7 +1108,8 @@ static void nForceUpdateArbitrationSettings unsigned pixelDepth, unsigned *burst, unsigned *lwm, - RIVA_HW_INST *chip + RIVA_HW_INST *chip, + struct pci_dev *pdev ) { nv10_fifo_info fifo_data; @@ -1116,8 +1117,9 @@ static void nForceUpdateArbitrationSettings unsigned int M, N, P, pll, MClk, NVClk; unsigned int uMClkPostDiv; struct pci_dev *dev; + int domain = pci_domain_nr(pdev->bus); - dev = pci_get_bus_and_slot(0, 3); + dev = pci_get_domain_bus_and_slot(domain, 0, 3); pci_read_config_dword(dev, 0x6C, &uMClkPostDiv); pci_dev_put(dev); uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf; @@ -1132,7 +1134,7 @@ static void nForceUpdateArbitrationSettings sim_data.enable_video = 0; sim_data.enable_mp = 0; - dev = pci_get_bus_and_slot(0, 1); + dev = pci_get_domain_bus_and_slot(domain, 0, 1); pci_read_config_dword(dev, 0x7C, &sim_data.memory_type); pci_dev_put(dev); sim_data.memory_type = (sim_data.memory_type >> 12) & 1; @@ -1234,6 +1236,7 @@ int CalcStateExt ( RIVA_HW_INST *chip, RIVA_HW_STATE *state, + struct pci_dev *pdev, int bpp, int width, int hDisplaySize, @@ -1300,7 +1303,7 @@ int CalcStateExt pixelDepth * 8, &(state->arbitration0), &(state->arbitration1), - chip); + chip, pdev); } else { nv10UpdateArbitrationSettings(VClk, pixelDepth * 8, @@ -2102,10 +2105,12 @@ static void nv4GetConfig static void nv10GetConfig ( RIVA_HW_INST *chip, + struct pci_dev *pdev, unsigned int chipset ) { struct pci_dev* dev; + int domain = pci_domain_nr(pdev->bus); u32 amt; #ifdef __BIG_ENDIAN @@ -2118,12 +2123,12 @@ static void nv10GetConfig * Fill in chip configuration. */ if(chipset == NV_CHIP_IGEFORCE2) { - dev = pci_get_bus_and_slot(0, 1); + dev = pci_get_domain_bus_and_slot(domain, 0, 1); pci_read_config_dword(dev, 0x7C, &amt); pci_dev_put(dev); chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024; } else if(chipset == NV_CHIP_0x01F0) { - dev = pci_get_bus_and_slot(0, 1); + dev = pci_get_domain_bus_and_slot(domain, 0, 1); pci_read_config_dword(dev, 0x84, &amt); pci_dev_put(dev); chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024; @@ -2224,6 +2229,7 @@ static void nv10GetConfig int RivaGetConfig ( RIVA_HW_INST *chip, + struct pci_dev *pdev, unsigned int chipset ) { @@ -2245,7 +2251,7 @@ int RivaGetConfig case NV_ARCH_10: case NV_ARCH_20: case NV_ARCH_30: - nv10GetConfig(chip, chipset); + nv10GetConfig(chip, pdev, chipset); break; default: return (-1); diff --git a/drivers/video/fbdev/riva/riva_hw.h b/drivers/video/fbdev/riva/riva_hw.h index c2769f73e0b2..5e7b35466b00 100644 --- a/drivers/video/fbdev/riva/riva_hw.h +++ b/drivers/video/fbdev/riva/riva_hw.h @@ -536,6 +536,7 @@ extern int CalcStateExt ( RIVA_HW_INST *chip, RIVA_HW_STATE *state, + struct pci_dev *pdev, int bpp, int width, int hDisplaySize, @@ -546,7 +547,7 @@ extern int CalcStateExt /* * External routines. */ -int RivaGetConfig(RIVA_HW_INST *, unsigned int); +int RivaGetConfig(RIVA_HW_INST *chip, struct pci_dev *pdev, unsigned int c); /* * FIFO Free Count. Should attempt to yield processor if RIVA is busy. */ |