diff options
Diffstat (limited to 'drivers/soc/fsl/qbman/bman_portal.c')
| -rw-r--r-- | drivers/soc/fsl/qbman/bman_portal.c | 88 |
1 files changed, 60 insertions, 28 deletions
diff --git a/drivers/soc/fsl/qbman/bman_portal.c b/drivers/soc/fsl/qbman/bman_portal.c index 8354d4dabdad..4d7b9caee1c4 100644 --- a/drivers/soc/fsl/qbman/bman_portal.c +++ b/drivers/soc/fsl/qbman/bman_portal.c @@ -32,6 +32,7 @@ static struct bman_portal *affine_bportals[NR_CPUS]; static struct cpumask portal_cpus; +static int __bman_portals_probed; /* protect bman global registers and global data shared among portals */ static DEFINE_SPINLOCK(bman_lock); @@ -65,7 +66,9 @@ static int bman_offline_cpu(unsigned int cpu) if (!pcfg) return 0; - irq_set_affinity(pcfg->irq, cpumask_of(0)); + /* use any other online CPU */ + cpu = cpumask_any_but(cpu_online_mask, cpu); + irq_set_affinity(pcfg->irq, cpumask_of(cpu)); return 0; } @@ -85,69 +88,79 @@ static int bman_online_cpu(unsigned int cpu) return 0; } +int bman_portals_probed(void) +{ + return __bman_portals_probed; +} +EXPORT_SYMBOL_GPL(bman_portals_probed); + static int bman_portal_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; struct bm_portal_config *pcfg; struct resource *addr_phys[2]; - void __iomem *va; - int irq, cpu; + int irq, cpu, err, i; + + err = bman_is_probed(); + if (!err) + return -EPROBE_DEFER; + if (err < 0) { + dev_err(&pdev->dev, "failing probe due to bman probe error\n"); + return -ENODEV; + } pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL); - if (!pcfg) + if (!pcfg) { + __bman_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; } 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; - spin_lock(&bman_lock); - cpu = cpumask_next_zero(-1, &portal_cpus); + cpu = cpumask_first_zero(&portal_cpus); if (cpu >= nr_cpu_ids) { + __bman_portals_probed = 1; /* unassigned portal, skip init */ spin_unlock(&bman_lock); - return 0; + goto check_cleanup; } cpumask_set_cpu(cpu, &portal_cpus); @@ -163,13 +176,32 @@ static int bman_portal_probe(struct platform_device *pdev) if (!cpu_online(cpu)) bman_offline_cpu(cpu); +check_cleanup: + if (__bman_portals_probed == 1 && bman_requires_cleanup()) { + /* + * BMan wasn't reset prior to boot (Kexec for example) + * Empty all the buffer pools so they are in reset state + */ + for (i = 0; i < BM_POOL_MAX; i++) { + err = bm_shutdown_pool(i); + if (err) { + dev_err(dev, "Failed to shutdown bpool %d\n", + i); + goto err_portal_init; + } + } + bman_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: + __bman_portals_probed = -1; + return -ENXIO; } |
