diff options
Diffstat (limited to 'drivers/soc/fsl/qbman/qman_portal.c')
| -rw-r--r-- | drivers/soc/fsl/qbman/qman_portal.c | 154 |
1 files changed, 69 insertions, 85 deletions
diff --git a/drivers/soc/fsl/qbman/qman_portal.c b/drivers/soc/fsl/qbman/qman_portal.c index adbaa30d3c5a..456ef5d5c199 100644 --- a/drivers/soc/fsl/qbman/qman_portal.c +++ b/drivers/soc/fsl/qbman/qman_portal.c @@ -38,6 +38,7 @@ EXPORT_SYMBOL(qman_dma_portal); #define CONFIG_FSL_DPA_PIRQ_FAST 1 static struct cpumask portal_cpus; +static int __qman_portals_probed; /* protect qman global registers and global data shared among portals */ static DEFINE_SPINLOCK(qman_lock); @@ -45,48 +46,17 @@ static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu) { #ifdef CONFIG_FSL_PAMU struct device *dev = pcfg->dev; - int window_count = 1; - struct iommu_domain_geometry geom_attr; - struct pamu_stash_attribute stash_attr; int ret; - pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type); - if (!pcfg->iommu_domain) { + pcfg->iommu_domain = iommu_paging_domain_alloc(dev); + if (IS_ERR(pcfg->iommu_domain)) { dev_err(dev, "%s(): iommu_domain_alloc() failed", __func__); + pcfg->iommu_domain = NULL; goto no_iommu; } - geom_attr.aperture_start = 0; - geom_attr.aperture_end = - ((dma_addr_t)1 << min(8 * sizeof(dma_addr_t), (size_t)36)) - 1; - geom_attr.force_aperture = true; - ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_GEOMETRY, - &geom_attr); + ret = fsl_pamu_configure_l1_stash(pcfg->iommu_domain, cpu); if (ret < 0) { - dev_err(dev, "%s(): iommu_domain_set_attr() = %d", __func__, - ret); - goto out_domain_free; - } - ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_WINDOWS, - &window_count); - if (ret < 0) { - dev_err(dev, "%s(): iommu_domain_set_attr() = %d", __func__, - ret); - goto out_domain_free; - } - stash_attr.cpu = cpu; - stash_attr.cache = PAMU_ATTR_CACHE_L1; - ret = iommu_domain_set_attr(pcfg->iommu_domain, - DOMAIN_ATTR_FSL_PAMU_STASH, - &stash_attr); - if (ret < 0) { - dev_err(dev, "%s(): iommu_domain_set_attr() = %d", - __func__, ret); - goto out_domain_free; - } - ret = iommu_domain_window_enable(pcfg->iommu_domain, 0, 0, 1ULL << 36, - IOMMU_READ | IOMMU_WRITE); - if (ret < 0) { - dev_err(dev, "%s(): iommu_domain_window_enable() = %d", + dev_err(dev, "%s(): fsl_pamu_configure_l1_stash() = %d", __func__, ret); goto out_domain_free; } @@ -96,14 +66,6 @@ static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu) ret); goto out_domain_free; } - ret = iommu_domain_set_attr(pcfg->iommu_domain, - DOMAIN_ATTR_FSL_PAMU_ENABLE, - &window_count); - if (ret < 0) { - dev_err(dev, "%s(): iommu_domain_set_attr() = %d", __func__, - ret); - goto out_detach_device; - } no_iommu: #endif @@ -112,8 +74,6 @@ no_iommu: return; #ifdef CONFIG_FSL_PAMU -out_detach_device: - iommu_detach_device(pcfg->iommu_domain, NULL); out_domain_free: iommu_domain_free(pcfg->iommu_domain); pcfg->iommu_domain = NULL; @@ -168,15 +128,8 @@ static void qman_portal_update_sdest(const struct qm_portal_config *pcfg, unsigned int cpu) { #ifdef CONFIG_FSL_PAMU /* TODO */ - struct pamu_stash_attribute stash_attr; - int ret; - if (pcfg->iommu_domain) { - stash_attr.cpu = cpu; - stash_attr.cache = PAMU_ATTR_CACHE_L1; - ret = iommu_domain_set_attr(pcfg->iommu_domain, - DOMAIN_ATTR_FSL_PAMU_STASH, &stash_attr); - if (ret < 0) { + if (fsl_pamu_configure_l1_stash(pcfg->iommu_domain, cpu) < 0) { dev_err(pcfg->dev, "Failed to update pamu stash setting\n"); return; @@ -195,8 +148,10 @@ static int qman_offline_cpu(unsigned int cpu) if (p) { pcfg = qman_get_qm_portal_config(p); if (pcfg) { - irq_set_affinity(pcfg->irq, cpumask_of(0)); - qman_portal_update_sdest(pcfg, 0); + /* select any other online CPU */ + cpu = cpumask_any_but(cpu_online_mask, cpu); + irq_set_affinity(pcfg->irq, cpumask_of(cpu)); + qman_portal_update_sdest(pcfg, cpu); } } return 0; @@ -218,78 +173,88 @@ static int qman_online_cpu(unsigned int cpu) return 0; } +int qman_portals_probed(void) +{ + return __qman_portals_probed; +} +EXPORT_SYMBOL_GPL(qman_portals_probed); + static int qman_portal_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; struct qm_portal_config *pcfg; struct resource *addr_phys[2]; - void __iomem *va; - int irq, cpu, err; + int irq, cpu, err, i; u32 val; + err = qman_is_probed(); + if (!err) + return -EPROBE_DEFER; + if (err < 0) { + dev_err(&pdev->dev, "failing probe due to qman probe error\n"); + return -ENODEV; + } + pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL); - if (!pcfg) + if (!pcfg) { + __qman_portals_probed = -1; return -ENOMEM; + } pcfg->dev = dev; addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM, DPAA_PORTAL_CE); if (!addr_phys[0]) { - dev_err(dev, "Can't get %s property 'reg::CE'\n", - node->full_name); - return -ENXIO; + dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node); + goto err_ioremap1; } addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM, DPAA_PORTAL_CI); if (!addr_phys[1]) { - dev_err(dev, "Can't get %s property 'reg::CI'\n", - node->full_name); - return -ENXIO; + dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node); + goto err_ioremap1; } err = of_property_read_u32(node, "cell-index", &val); if (err) { - dev_err(dev, "Can't get %s property 'cell-index'\n", - node->full_name); + dev_err(dev, "Can't get %pOF property 'cell-index'\n", node); + __qman_portals_probed = -1; return err; } pcfg->channel = val; pcfg->cpu = -1; irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(dev, "Can't get %s IRQ\n", node->full_name); - return -ENXIO; - } + if (irq <= 0) + goto err_ioremap1; pcfg->irq = irq; - va = ioremap_prot(addr_phys[0]->start, resource_size(addr_phys[0]), 0); - if (!va) { - dev_err(dev, "ioremap::CE failed\n"); + pcfg->addr_virt_ce = memremap(addr_phys[0]->start, + resource_size(addr_phys[0]), + QBMAN_MEMREMAP_ATTR); + if (!pcfg->addr_virt_ce) { + dev_err(dev, "memremap::CE failed\n"); goto err_ioremap1; } - pcfg->addr_virt[DPAA_PORTAL_CE] = va; - - va = ioremap_prot(addr_phys[1]->start, resource_size(addr_phys[1]), - _PAGE_GUARDED | _PAGE_NO_CACHE); - if (!va) { + pcfg->addr_virt_ci = ioremap(addr_phys[1]->start, + resource_size(addr_phys[1])); + if (!pcfg->addr_virt_ci) { dev_err(dev, "ioremap::CI failed\n"); goto err_ioremap2; } - pcfg->addr_virt[DPAA_PORTAL_CI] = va; - pcfg->pools = qm_get_pools_sdqcr(); spin_lock(&qman_lock); - cpu = cpumask_next_zero(-1, &portal_cpus); + cpu = cpumask_first_zero(&portal_cpus); if (cpu >= nr_cpu_ids) { + __qman_portals_probed = 1; /* unassigned portal, skip init */ spin_unlock(&qman_lock); - return 0; + goto check_cleanup; } cpumask_set_cpu(cpu, &portal_cpus); @@ -310,13 +275,32 @@ static int qman_portal_probe(struct platform_device *pdev) if (!cpu_online(cpu)) qman_offline_cpu(cpu); +check_cleanup: + if (__qman_portals_probed == 1 && qman_requires_cleanup()) { + /* + * QMan wasn't reset prior to boot (Kexec for example) + * Empty all the frame queues so they are in reset state + */ + for (i = 0; i < qm_get_fqid_maxcnt(); i++) { + err = qman_shutdown_fq(i); + if (err) { + dev_err(dev, "Failed to shutdown frame queue %d\n", + i); + goto err_portal_init; + } + } + qman_done_cleanup(); + } + return 0; err_portal_init: - iounmap(pcfg->addr_virt[DPAA_PORTAL_CI]); + iounmap(pcfg->addr_virt_ci); err_ioremap2: - iounmap(pcfg->addr_virt[DPAA_PORTAL_CE]); + memunmap(pcfg->addr_virt_ce); err_ioremap1: + __qman_portals_probed = -1; + return -ENXIO; } |
