diff options
| author | Dave Airlie <airlied@redhat.com> | 2015-04-20 11:32:26 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2015-04-20 13:05:20 +1000 |
| commit | 2c33ce009ca2389dbf0535d0672214d09738e35e (patch) | |
| tree | 6186a6458c3c160385d794a23eaf07c786a9e61b /arch/powerpc/platforms/powernv/pci.c | |
| parent | cec32a47010647e8b0603726ebb75b990a4057a4 (diff) | |
| parent | 09d51602cf84a1264946711dd4ea0dddbac599a1 (diff) | |
Merge Linus master into drm-next
The merge is clean, but the arm build fails afterwards,
due to API changes in the regulator tree.
I've included the patch into the merge to fix the build.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'arch/powerpc/platforms/powernv/pci.c')
| -rw-r--r-- | arch/powerpc/platforms/powernv/pci.c | 190 |
1 files changed, 67 insertions, 123 deletions
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 54323d6b5166..bca2aeb6e4b6 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -366,9 +366,9 @@ static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no) spin_unlock_irqrestore(&phb->lock, flags); } -static void pnv_pci_config_check_eeh(struct pnv_phb *phb, - struct device_node *dn) +static void pnv_pci_config_check_eeh(struct pci_dn *pdn) { + struct pnv_phb *phb = pdn->phb->private_data; u8 fstate; __be16 pcierr; int pe_no; @@ -379,7 +379,7 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, * setup that yet. So all ER errors should be mapped to * reserved PE. */ - pe_no = PCI_DN(dn)->pe_number; + pe_no = pdn->pe_number; if (pe_no == IODA_INVALID_PE) { if (phb->type == PNV_PHB_P5IOC2) pe_no = 0; @@ -407,8 +407,7 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, } cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n", - (PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn), - pe_no, fstate); + (pdn->busno << 8) | (pdn->devfn), pe_no, fstate); /* Clear the frozen state if applicable */ if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE || @@ -425,10 +424,9 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, } } -int pnv_pci_cfg_read(struct device_node *dn, +int pnv_pci_cfg_read(struct pci_dn *pdn, int where, int size, u32 *val) { - struct pci_dn *pdn = PCI_DN(dn); struct pnv_phb *phb = pdn->phb->private_data; u32 bdfn = (pdn->busno << 8) | pdn->devfn; s64 rc; @@ -462,10 +460,9 @@ int pnv_pci_cfg_read(struct device_node *dn, return PCIBIOS_SUCCESSFUL; } -int pnv_pci_cfg_write(struct device_node *dn, +int pnv_pci_cfg_write(struct pci_dn *pdn, int where, int size, u32 val) { - struct pci_dn *pdn = PCI_DN(dn); struct pnv_phb *phb = pdn->phb->private_data; u32 bdfn = (pdn->busno << 8) | pdn->devfn; @@ -489,18 +486,17 @@ int pnv_pci_cfg_write(struct device_node *dn, } #if CONFIG_EEH -static bool pnv_pci_cfg_check(struct pci_controller *hose, - struct device_node *dn) +static bool pnv_pci_cfg_check(struct pci_dn *pdn) { struct eeh_dev *edev = NULL; - struct pnv_phb *phb = hose->private_data; + struct pnv_phb *phb = pdn->phb->private_data; /* EEH not enabled ? */ if (!(phb->flags & PNV_PHB_FLAG_EEH)) return true; /* PE reset or device removed ? */ - edev = of_node_to_eeh_dev(dn); + edev = pdn->edev; if (edev) { if (edev->pe && (edev->pe->state & EEH_PE_CFG_BLOCKED)) @@ -513,8 +509,7 @@ static bool pnv_pci_cfg_check(struct pci_controller *hose, return true; } #else -static inline pnv_pci_cfg_check(struct pci_controller *hose, - struct device_node *dn) +static inline pnv_pci_cfg_check(struct pci_dn *pdn) { return true; } @@ -524,32 +519,26 @@ static int pnv_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { - struct device_node *dn, *busdn = pci_bus_to_OF_node(bus); struct pci_dn *pdn; struct pnv_phb *phb; - bool found = false; int ret; *val = 0xFFFFFFFF; - for (dn = busdn->child; dn; dn = dn->sibling) { - pdn = PCI_DN(dn); - if (pdn && pdn->devfn == devfn) { - phb = pdn->phb->private_data; - found = true; - break; - } - } + pdn = pci_get_pdn_by_devfn(bus, devfn); + if (!pdn) + return PCIBIOS_DEVICE_NOT_FOUND; - if (!found || !pnv_pci_cfg_check(pdn->phb, dn)) + if (!pnv_pci_cfg_check(pdn)) return PCIBIOS_DEVICE_NOT_FOUND; - ret = pnv_pci_cfg_read(dn, where, size, val); - if (phb->flags & PNV_PHB_FLAG_EEH) { + ret = pnv_pci_cfg_read(pdn, where, size, val); + phb = pdn->phb->private_data; + if (phb->flags & PNV_PHB_FLAG_EEH && pdn->edev) { if (*val == EEH_IO_ERROR_VALUE(size) && - eeh_dev_check_failure(of_node_to_eeh_dev(dn))) + eeh_dev_check_failure(pdn->edev)) return PCIBIOS_DEVICE_NOT_FOUND; } else { - pnv_pci_config_check_eeh(phb, dn); + pnv_pci_config_check_eeh(pdn); } return ret; @@ -559,27 +548,21 @@ static int pnv_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { - struct device_node *dn, *busdn = pci_bus_to_OF_node(bus); struct pci_dn *pdn; struct pnv_phb *phb; - bool found = false; int ret; - for (dn = busdn->child; dn; dn = dn->sibling) { - pdn = PCI_DN(dn); - if (pdn && pdn->devfn == devfn) { - phb = pdn->phb->private_data; - found = true; - break; - } - } + pdn = pci_get_pdn_by_devfn(bus, devfn); + if (!pdn) + return PCIBIOS_DEVICE_NOT_FOUND; - if (!found || !pnv_pci_cfg_check(pdn->phb, dn)) + if (!pnv_pci_cfg_check(pdn)) return PCIBIOS_DEVICE_NOT_FOUND; - ret = pnv_pci_cfg_write(dn, where, size, val); + ret = pnv_pci_cfg_write(pdn, where, size, val); + phb = pdn->phb->private_data; if (!(phb->flags & PNV_PHB_FLAG_EEH)) - pnv_pci_config_check_eeh(phb, dn); + pnv_pci_config_check_eeh(pdn); return ret; } @@ -679,66 +662,31 @@ void pnv_pci_setup_iommu_table(struct iommu_table *tbl, tbl->it_type = TCE_PCI; } -static struct iommu_table *pnv_pci_setup_bml_iommu(struct pci_controller *hose) -{ - struct iommu_table *tbl; - const __be64 *basep, *swinvp; - const __be32 *sizep; - - basep = of_get_property(hose->dn, "linux,tce-base", NULL); - sizep = of_get_property(hose->dn, "linux,tce-size", NULL); - if (basep == NULL || sizep == NULL) { - pr_err("PCI: %s has missing tce entries !\n", - hose->dn->full_name); - return NULL; - } - tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, hose->node); - if (WARN_ON(!tbl)) - return NULL; - pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)), - be32_to_cpup(sizep), 0, IOMMU_PAGE_SHIFT_4K); - iommu_init_table(tbl, hose->node); - iommu_register_group(tbl, pci_domain_nr(hose->bus), 0); - - /* Deal with SW invalidated TCEs when needed (BML way) */ - swinvp = of_get_property(hose->dn, "linux,tce-sw-invalidate-info", - NULL); - if (swinvp) { - tbl->it_busno = be64_to_cpu(swinvp[1]); - tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8); - tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE; - } - return tbl; -} - -static void pnv_pci_dma_fallback_setup(struct pci_controller *hose, - struct pci_dev *pdev) -{ - struct device_node *np = pci_bus_to_OF_node(hose->bus); - struct pci_dn *pdn; - - if (np == NULL) - return; - pdn = PCI_DN(np); - if (!pdn->iommu_table) - pdn->iommu_table = pnv_pci_setup_bml_iommu(hose); - if (!pdn->iommu_table) - return; - set_iommu_table_base_and_group(&pdev->dev, pdn->iommu_table); -} - static void pnv_pci_dma_dev_setup(struct pci_dev *pdev) { struct pci_controller *hose = pci_bus_to_host(pdev->bus); struct pnv_phb *phb = hose->private_data; +#ifdef CONFIG_PCI_IOV + struct pnv_ioda_pe *pe; + struct pci_dn *pdn; + + /* Fix the VF pdn PE number */ + if (pdev->is_virtfn) { + pdn = pci_get_pdn(pdev); + WARN_ON(pdn->pe_number != IODA_INVALID_PE); + list_for_each_entry(pe, &phb->ioda.pe_list, list) { + if (pe->rid == ((pdev->bus->number << 8) | + (pdev->devfn & 0xff))) { + pdn->pe_number = pe->pe_number; + pe->pdev = pdev; + break; + } + } + } +#endif /* CONFIG_PCI_IOV */ - /* If we have no phb structure, try to setup a fallback based on - * the device-tree (RTAS PCI for example) - */ if (phb && phb->dma_dev_setup) phb->dma_dev_setup(phb, pdev); - else - pnv_pci_dma_fallback_setup(hose, pdev); } int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask) @@ -784,44 +732,36 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM, 0x3b9, pnv_p7ioc_rc_quirk); void __init pnv_pci_init(void) { struct device_node *np; + bool found_ioda = false; pci_add_flags(PCI_CAN_SKIP_ISA_ALIGN); - /* OPAL absent, try POPAL first then RTAS detection of PHBs */ - if (!firmware_has_feature(FW_FEATURE_OPAL)) { -#ifdef CONFIG_PPC_POWERNV_RTAS - init_pci_config_tokens(); - find_and_init_phbs(); -#endif /* CONFIG_PPC_POWERNV_RTAS */ - } - /* OPAL is here, do our normal stuff */ - else { - int found_ioda = 0; + /* If we don't have OPAL, eg. in sim, just skip PCI probe */ + if (!firmware_has_feature(FW_FEATURE_OPAL)) + return; - /* Look for IODA IO-Hubs. We don't support mixing IODA - * and p5ioc2 due to the need to change some global - * probing flags - */ - for_each_compatible_node(np, NULL, "ibm,ioda-hub") { - pnv_pci_init_ioda_hub(np); - found_ioda = 1; - } + /* Look for IODA IO-Hubs. We don't support mixing IODA + * and p5ioc2 due to the need to change some global + * probing flags + */ + for_each_compatible_node(np, NULL, "ibm,ioda-hub") { + pnv_pci_init_ioda_hub(np); + found_ioda = true; + } - /* Look for p5ioc2 IO-Hubs */ - if (!found_ioda) - for_each_compatible_node(np, NULL, "ibm,p5ioc2") - pnv_pci_init_p5ioc2_hub(np); + /* Look for p5ioc2 IO-Hubs */ + if (!found_ioda) + for_each_compatible_node(np, NULL, "ibm,p5ioc2") + pnv_pci_init_p5ioc2_hub(np); - /* Look for ioda2 built-in PHB3's */ - for_each_compatible_node(np, NULL, "ibm,ioda2-phb") - pnv_pci_init_ioda2_phb(np); - } + /* Look for ioda2 built-in PHB3's */ + for_each_compatible_node(np, NULL, "ibm,ioda2-phb") + pnv_pci_init_ioda2_phb(np); /* Setup the linkage between OF nodes and PHBs */ pci_devs_phb_init(); /* Configure IOMMU DMA hooks */ - ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup; ppc_md.tce_build = pnv_tce_build_vm; ppc_md.tce_free = pnv_tce_free_vm; ppc_md.tce_build_rm = pnv_tce_build_rm; @@ -837,3 +777,7 @@ void __init pnv_pci_init(void) } machine_subsys_initcall_sync(powernv, tce_iommu_bus_notifier_init); + +struct pci_controller_ops pnv_pci_controller_ops = { + .dma_dev_setup = pnv_pci_dma_dev_setup, +}; |
