root/drivers/soc/fsl/qbman/bman_portal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init_pcfg
  2. bman_offline_cpu
  3. bman_online_cpu
  4. bman_portals_probed
  5. bman_portal_probe
  6. bman_portal_driver_register

   1 /* Copyright 2008 - 2016 Freescale Semiconductor, Inc.
   2  *
   3  * Redistribution and use in source and binary forms, with or without
   4  * modification, are permitted provided that the following conditions are met:
   5  *     * Redistributions of source code must retain the above copyright
   6  *       notice, this list of conditions and the following disclaimer.
   7  *     * Redistributions in binary form must reproduce the above copyright
   8  *       notice, this list of conditions and the following disclaimer in the
   9  *       documentation and/or other materials provided with the distribution.
  10  *     * Neither the name of Freescale Semiconductor nor the
  11  *       names of its contributors may be used to endorse or promote products
  12  *       derived from this software without specific prior written permission.
  13  *
  14  * ALTERNATIVELY, this software may be distributed under the terms of the
  15  * GNU General Public License ("GPL") as published by the Free Software
  16  * Foundation, either version 2 of that License or (at your option) any
  17  * later version.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22  * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29  */
  30 
  31 #include "bman_priv.h"
  32 
  33 static struct bman_portal *affine_bportals[NR_CPUS];
  34 static struct cpumask portal_cpus;
  35 static int __bman_portals_probed;
  36 /* protect bman global registers and global data shared among portals */
  37 static DEFINE_SPINLOCK(bman_lock);
  38 
  39 static struct bman_portal *init_pcfg(struct bm_portal_config *pcfg)
  40 {
  41         struct bman_portal *p = bman_create_affine_portal(pcfg);
  42 
  43         if (!p) {
  44                 dev_crit(pcfg->dev, "%s: Portal failure on cpu %d\n",
  45                          __func__, pcfg->cpu);
  46                 return NULL;
  47         }
  48 
  49         bman_p_irqsource_add(p, BM_PIRQ_RCRI);
  50         affine_bportals[pcfg->cpu] = p;
  51 
  52         dev_info(pcfg->dev, "Portal initialised, cpu %d\n", pcfg->cpu);
  53 
  54         return p;
  55 }
  56 
  57 static int bman_offline_cpu(unsigned int cpu)
  58 {
  59         struct bman_portal *p = affine_bportals[cpu];
  60         const struct bm_portal_config *pcfg;
  61 
  62         if (!p)
  63                 return 0;
  64 
  65         pcfg = bman_get_bm_portal_config(p);
  66         if (!pcfg)
  67                 return 0;
  68 
  69         /* use any other online CPU */
  70         cpu = cpumask_any_but(cpu_online_mask, cpu);
  71         irq_set_affinity(pcfg->irq, cpumask_of(cpu));
  72         return 0;
  73 }
  74 
  75 static int bman_online_cpu(unsigned int cpu)
  76 {
  77         struct bman_portal *p = affine_bportals[cpu];
  78         const struct bm_portal_config *pcfg;
  79 
  80         if (!p)
  81                 return 0;
  82 
  83         pcfg = bman_get_bm_portal_config(p);
  84         if (!pcfg)
  85                 return 0;
  86 
  87         irq_set_affinity(pcfg->irq, cpumask_of(cpu));
  88         return 0;
  89 }
  90 
  91 int bman_portals_probed(void)
  92 {
  93         return __bman_portals_probed;
  94 }
  95 EXPORT_SYMBOL_GPL(bman_portals_probed);
  96 
  97 static int bman_portal_probe(struct platform_device *pdev)
  98 {
  99         struct device *dev = &pdev->dev;
 100         struct device_node *node = dev->of_node;
 101         struct bm_portal_config *pcfg;
 102         struct resource *addr_phys[2];
 103         int irq, cpu, err, i;
 104 
 105         err = bman_is_probed();
 106         if (!err)
 107                 return -EPROBE_DEFER;
 108         if (err < 0) {
 109                 dev_err(&pdev->dev, "failing probe due to bman probe error\n");
 110                 return -ENODEV;
 111         }
 112 
 113         pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
 114         if (!pcfg) {
 115                 __bman_portals_probed = -1;
 116                 return -ENOMEM;
 117         }
 118 
 119         pcfg->dev = dev;
 120 
 121         addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
 122                                              DPAA_PORTAL_CE);
 123         if (!addr_phys[0]) {
 124                 dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node);
 125                 goto err_ioremap1;
 126         }
 127 
 128         addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
 129                                              DPAA_PORTAL_CI);
 130         if (!addr_phys[1]) {
 131                 dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node);
 132                 goto err_ioremap1;
 133         }
 134 
 135         pcfg->cpu = -1;
 136 
 137         irq = platform_get_irq(pdev, 0);
 138         if (irq <= 0)
 139                 goto err_ioremap1;
 140         pcfg->irq = irq;
 141 
 142         pcfg->addr_virt_ce = memremap(addr_phys[0]->start,
 143                                         resource_size(addr_phys[0]),
 144                                         QBMAN_MEMREMAP_ATTR);
 145         if (!pcfg->addr_virt_ce) {
 146                 dev_err(dev, "memremap::CE failed\n");
 147                 goto err_ioremap1;
 148         }
 149 
 150         pcfg->addr_virt_ci = ioremap(addr_phys[1]->start,
 151                                         resource_size(addr_phys[1]));
 152         if (!pcfg->addr_virt_ci) {
 153                 dev_err(dev, "ioremap::CI failed\n");
 154                 goto err_ioremap2;
 155         }
 156 
 157         spin_lock(&bman_lock);
 158         cpu = cpumask_next_zero(-1, &portal_cpus);
 159         if (cpu >= nr_cpu_ids) {
 160                 __bman_portals_probed = 1;
 161                 /* unassigned portal, skip init */
 162                 spin_unlock(&bman_lock);
 163                 return 0;
 164         }
 165 
 166         cpumask_set_cpu(cpu, &portal_cpus);
 167         spin_unlock(&bman_lock);
 168         pcfg->cpu = cpu;
 169 
 170         if (!init_pcfg(pcfg)) {
 171                 dev_err(dev, "portal init failed\n");
 172                 goto err_portal_init;
 173         }
 174 
 175         /* clear irq affinity if assigned cpu is offline */
 176         if (!cpu_online(cpu))
 177                 bman_offline_cpu(cpu);
 178 
 179         if (__bman_portals_probed == 1 && bman_requires_cleanup()) {
 180                 /*
 181                  * BMan wasn't reset prior to boot (Kexec for example)
 182                  * Empty all the buffer pools so they are in reset state
 183                  */
 184                 for (i = 0; i < BM_POOL_MAX; i++) {
 185                         err =  bm_shutdown_pool(i);
 186                         if (err) {
 187                                 dev_err(dev, "Failed to shutdown bpool %d\n",
 188                                         i);
 189                                 goto err_portal_init;
 190                         }
 191                 }
 192                 bman_done_cleanup();
 193         }
 194 
 195         return 0;
 196 
 197 err_portal_init:
 198         iounmap(pcfg->addr_virt_ci);
 199 err_ioremap2:
 200         memunmap(pcfg->addr_virt_ce);
 201 err_ioremap1:
 202          __bman_portals_probed = -1;
 203 
 204         return -ENXIO;
 205 }
 206 
 207 static const struct of_device_id bman_portal_ids[] = {
 208         {
 209                 .compatible = "fsl,bman-portal",
 210         },
 211         {}
 212 };
 213 MODULE_DEVICE_TABLE(of, bman_portal_ids);
 214 
 215 static struct platform_driver bman_portal_driver = {
 216         .driver = {
 217                 .name = KBUILD_MODNAME,
 218                 .of_match_table = bman_portal_ids,
 219         },
 220         .probe = bman_portal_probe,
 221 };
 222 
 223 static int __init bman_portal_driver_register(struct platform_driver *drv)
 224 {
 225         int ret;
 226 
 227         ret = platform_driver_register(drv);
 228         if (ret < 0)
 229                 return ret;
 230 
 231         ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
 232                                         "soc/qbman_portal:online",
 233                                         bman_online_cpu, bman_offline_cpu);
 234         if (ret < 0) {
 235                 pr_err("bman: failed to register hotplug callbacks.\n");
 236                 platform_driver_unregister(drv);
 237                 return ret;
 238         }
 239         return 0;
 240 }
 241 
 242 module_driver(bman_portal_driver,
 243               bman_portal_driver_register, platform_driver_unregister);

/* [<][>][^][v][top][bottom][index][help] */