source: rtems-libbsd/linux/drivers/soc/fsl/qbman/qman_portal.c @ e818128

55-freebsd-126-freebsd-12
Last change on this file since e818128 was e818128, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 23, 2017 at 9:39:26 AM

dpaa: Add "libbsd,dequeue" to QMan portals

The dequeue support for processor affine QMan portals may be explicitly
disabled. The dequeue support is responsible for receiving frames and
completion of frame transmission, e.g. buffer recycling. Without at
least one enabled dequeue support, there will be no networking.

/ {

qman-portals@ff6000000 {

qman-portal@0 {

libbsd,dequeue = "disabled";

};

};

};

  • Property mode set to 100644
File size: 12.6 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3#include <rtems/bsd/local/opt_dpaa.h>
4
5/* Copyright 2008 - 2016 Freescale Semiconductor, Inc.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *     * Redistributions of source code must retain the above copyright
10 *       notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above copyright
12 *       notice, this list of conditions and the following disclaimer in the
13 *       documentation and/or other materials provided with the distribution.
14 *     * Neither the name of Freescale Semiconductor nor the
15 *       names of its contributors may be used to endorse or promote products
16 *       derived from this software without specific prior written permission.
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include "qman_priv.h"
36#ifdef __rtems__
37#include <bsp/qoriq.h>
38#undef dev_crit
39#undef dev_info
40#define dev_crit(dev, fmt, ...) printf(fmt, ##__VA_ARGS__)
41#define dev_info dev_crit
42#endif /* __rtems__ */
43
44#ifndef __rtems__
45struct qman_portal *qman_dma_portal;
46EXPORT_SYMBOL(qman_dma_portal);
47#endif /* __rtems__ */
48
49/* Enable portal interupts (as opposed to polling mode) */
50#define CONFIG_FSL_DPA_PIRQ_SLOW  1
51#define CONFIG_FSL_DPA_PIRQ_FAST  1
52
53#ifndef __rtems__
54static struct cpumask portal_cpus;
55/* protect qman global registers and global data shared among portals */
56static DEFINE_SPINLOCK(qman_lock);
57#endif /* __rtems__ */
58
59static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu)
60{
61#ifdef CONFIG_FSL_PAMU
62        struct device *dev = pcfg->dev;
63        int window_count = 1;
64        struct iommu_domain_geometry geom_attr;
65        struct pamu_stash_attribute stash_attr;
66        int ret;
67
68        pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type);
69        if (!pcfg->iommu_domain) {
70                dev_err(dev, "%s(): iommu_domain_alloc() failed", __func__);
71                goto no_iommu;
72        }
73        geom_attr.aperture_start = 0;
74        geom_attr.aperture_end =
75                ((dma_addr_t)1 << min(8 * sizeof(dma_addr_t), (size_t)36)) - 1;
76        geom_attr.force_aperture = true;
77        ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_GEOMETRY,
78                                    &geom_attr);
79        if (ret < 0) {
80                dev_err(dev, "%s(): iommu_domain_set_attr() = %d", __func__,
81                        ret);
82                goto out_domain_free;
83        }
84        ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_WINDOWS,
85                                    &window_count);
86        if (ret < 0) {
87                dev_err(dev, "%s(): iommu_domain_set_attr() = %d", __func__,
88                        ret);
89                goto out_domain_free;
90        }
91        stash_attr.cpu = cpu;
92        stash_attr.cache = PAMU_ATTR_CACHE_L1;
93        ret = iommu_domain_set_attr(pcfg->iommu_domain,
94                                    DOMAIN_ATTR_FSL_PAMU_STASH,
95                                    &stash_attr);
96        if (ret < 0) {
97                dev_err(dev, "%s(): iommu_domain_set_attr() = %d",
98                        __func__, ret);
99                goto out_domain_free;
100        }
101        ret = iommu_domain_window_enable(pcfg->iommu_domain, 0, 0, 1ULL << 36,
102                                         IOMMU_READ | IOMMU_WRITE);
103        if (ret < 0) {
104                dev_err(dev, "%s(): iommu_domain_window_enable() = %d",
105                        __func__, ret);
106                goto out_domain_free;
107        }
108        ret = iommu_attach_device(pcfg->iommu_domain, dev);
109        if (ret < 0) {
110                dev_err(dev, "%s(): iommu_device_attach() = %d", __func__,
111                        ret);
112                goto out_domain_free;
113        }
114        ret = iommu_domain_set_attr(pcfg->iommu_domain,
115                                    DOMAIN_ATTR_FSL_PAMU_ENABLE,
116                                    &window_count);
117        if (ret < 0) {
118                dev_err(dev, "%s(): iommu_domain_set_attr() = %d", __func__,
119                        ret);
120                goto out_detach_device;
121        }
122
123no_iommu:
124#endif
125        qman_set_sdest(pcfg->channel, cpu);
126
127        return;
128
129#ifdef CONFIG_FSL_PAMU
130out_detach_device:
131        iommu_detach_device(pcfg->iommu_domain, NULL);
132out_domain_free:
133        iommu_domain_free(pcfg->iommu_domain);
134        pcfg->iommu_domain = NULL;
135#endif
136}
137
138static struct qman_portal *init_pcfg(struct qm_portal_config *pcfg)
139{
140        struct qman_portal *p;
141        u32 irq_sources = 0;
142
143        /* We need the same LIODN offset for all portals */
144        qman_liodn_fixup(pcfg->channel);
145
146#ifndef __rtems__
147        pcfg->iommu_domain = NULL;
148#endif /* __rtems__ */
149        portal_set_cpu(pcfg, pcfg->cpu);
150        p = qman_create_affine_portal(pcfg, NULL);
151        if (!p) {
152                dev_crit(pcfg->dev, "%s: Portal failure on cpu %d\n",
153                         __func__, pcfg->cpu);
154                return NULL;
155        }
156
157        /* Determine what should be interrupt-vs-poll driven */
158#ifdef CONFIG_FSL_DPA_PIRQ_SLOW
159        irq_sources |= QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI |
160                       QM_PIRQ_CSCI;
161#endif
162#ifdef CONFIG_FSL_DPA_PIRQ_FAST
163        irq_sources |= QM_PIRQ_DQRI;
164#endif
165        qman_p_irqsource_add(p, irq_sources);
166
167#ifndef __rtems__
168        spin_lock(&qman_lock);
169        if (cpumask_equal(&portal_cpus, cpu_possible_mask)) {
170                /* all assigned portals are initialized now */
171                qman_init_cgr_all();
172        }
173
174        if (!qman_dma_portal)
175                qman_dma_portal = p;
176
177        spin_unlock(&qman_lock);
178#endif /* __rtems__ */
179
180        dev_info(pcfg->dev, "Portal initialised, cpu %d\n", pcfg->cpu);
181
182        return p;
183}
184
185static void qman_portal_update_sdest(const struct qm_portal_config *pcfg,
186                                                        unsigned int cpu)
187{
188#ifdef CONFIG_FSL_PAMU /* TODO */
189        struct pamu_stash_attribute stash_attr;
190        int ret;
191
192        if (pcfg->iommu_domain) {
193                stash_attr.cpu = cpu;
194                stash_attr.cache = PAMU_ATTR_CACHE_L1;
195                ret = iommu_domain_set_attr(pcfg->iommu_domain,
196                                DOMAIN_ATTR_FSL_PAMU_STASH, &stash_attr);
197                if (ret < 0) {
198                        dev_err(pcfg->dev,
199                                "Failed to update pamu stash setting\n");
200                        return;
201                }
202        }
203#endif
204        qman_set_sdest(pcfg->channel, cpu);
205}
206
207#ifndef __rtems__
208static int qman_offline_cpu(unsigned int cpu)
209{
210        struct qman_portal *p;
211        const struct qm_portal_config *pcfg;
212
213        p = affine_portals[cpu];
214        if (p) {
215                pcfg = qman_get_qm_portal_config(p);
216                if (pcfg) {
217                        irq_set_affinity(pcfg->irq, cpumask_of(0));
218                        qman_portal_update_sdest(pcfg, 0);
219                }
220        }
221        return 0;
222}
223
224static int qman_online_cpu(unsigned int cpu)
225{
226        struct qman_portal *p;
227        const struct qm_portal_config *pcfg;
228
229        p = affine_portals[cpu];
230        if (p) {
231                pcfg = qman_get_qm_portal_config(p);
232                if (pcfg) {
233                        irq_set_affinity(pcfg->irq, cpumask_of(cpu));
234                        qman_portal_update_sdest(pcfg, cpu);
235                }
236        }
237        return 0;
238}
239
240static int qman_portal_probe(struct platform_device *pdev)
241{
242        struct device *dev = &pdev->dev;
243        struct device_node *node = dev->of_node;
244        struct qm_portal_config *pcfg;
245        struct resource *addr_phys[2];
246        void __iomem *va;
247        int irq, cpu, err;
248        u32 val;
249
250        pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
251        if (!pcfg)
252                return -ENOMEM;
253
254        pcfg->dev = dev;
255
256        addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
257                                             DPAA_PORTAL_CE);
258        if (!addr_phys[0]) {
259                dev_err(dev, "Can't get %s property 'reg::CE'\n",
260                        node->full_name);
261                return -ENXIO;
262        }
263
264        addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
265                                             DPAA_PORTAL_CI);
266        if (!addr_phys[1]) {
267                dev_err(dev, "Can't get %s property 'reg::CI'\n",
268                        node->full_name);
269                return -ENXIO;
270        }
271
272        err = of_property_read_u32(node, "cell-index", &val);
273        if (err) {
274                dev_err(dev, "Can't get %s property 'cell-index'\n",
275                        node->full_name);
276                return err;
277        }
278        pcfg->channel = val;
279        pcfg->cpu = -1;
280        irq = platform_get_irq(pdev, 0);
281        if (irq < 0) {
282                dev_err(dev, "Can't get %s IRQ\n", node->full_name);
283                return -ENXIO;
284        }
285        pcfg->irq = irq;
286
287        va = ioremap_prot(addr_phys[0]->start, resource_size(addr_phys[0]), 0);
288        if (!va) {
289                dev_err(dev, "ioremap::CE failed\n");
290                goto err_ioremap1;
291        }
292
293        pcfg->addr_virt[DPAA_PORTAL_CE] = va;
294
295        va = ioremap_prot(addr_phys[1]->start, resource_size(addr_phys[1]),
296                          _PAGE_GUARDED | _PAGE_NO_CACHE);
297        if (!va) {
298                dev_err(dev, "ioremap::CI failed\n");
299                goto err_ioremap2;
300        }
301
302        pcfg->addr_virt[DPAA_PORTAL_CI] = va;
303
304        pcfg->pools = qm_get_pools_sdqcr();
305
306        spin_lock(&qman_lock);
307        cpu = cpumask_next_zero(-1, &portal_cpus);
308        if (cpu >= nr_cpu_ids) {
309                /* unassigned portal, skip init */
310                spin_unlock(&qman_lock);
311                return 0;
312        }
313
314        cpumask_set_cpu(cpu, &portal_cpus);
315        spin_unlock(&qman_lock);
316        pcfg->cpu = cpu;
317
318        if (dma_set_mask(dev, DMA_BIT_MASK(40))) {
319                dev_err(dev, "dma_set_mask() failed\n");
320                goto err_portal_init;
321        }
322
323        if (!init_pcfg(pcfg)) {
324                dev_err(dev, "portal init failed\n");
325                goto err_portal_init;
326        }
327
328        /* clear irq affinity if assigned cpu is offline */
329        if (!cpu_online(cpu))
330                qman_offline_cpu(cpu);
331
332        return 0;
333
334err_portal_init:
335        iounmap(pcfg->addr_virt[DPAA_PORTAL_CI]);
336err_ioremap2:
337        iounmap(pcfg->addr_virt[DPAA_PORTAL_CE]);
338err_ioremap1:
339        return -ENXIO;
340}
341
342static const struct of_device_id qman_portal_ids[] = {
343        {
344                .compatible = "fsl,qman-portal",
345        },
346        {}
347};
348MODULE_DEVICE_TABLE(of, qman_portal_ids);
349
350static struct platform_driver qman_portal_driver = {
351        .driver = {
352                .name = KBUILD_MODNAME,
353                .of_match_table = qman_portal_ids,
354        },
355        .probe = qman_portal_probe,
356};
357
358static int __init qman_portal_driver_register(struct platform_driver *drv)
359{
360        int ret;
361
362        ret = platform_driver_register(drv);
363        if (ret < 0)
364                return ret;
365
366        ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
367                                        "soc/qman_portal:online",
368                                        qman_online_cpu, qman_offline_cpu);
369        if (ret < 0) {
370                pr_err("qman: failed to register hotplug callbacks.\n");
371                platform_driver_unregister(drv);
372                return ret;
373        }
374        return 0;
375}
376
377module_driver(qman_portal_driver,
378              qman_portal_driver_register, platform_driver_unregister);
379#else /* __rtems__ */
380#include <bsp/fdt.h>
381#include <linux/of_address.h>
382#include <linux/of_irq.h>
383
384#define MAX_QMAN_PORTALS 50
385
386static struct qm_portal_config qman_configs[MAX_QMAN_PORTALS];
387
388static bool
389is_dequeue_enabled(const struct device_node *dn)
390{
391        const char *dequeue;
392        int len;
393
394        dequeue = of_get_property(dn, "libbsd,dequeue", &len);
395        return (len <= 0 || strcmp(dequeue, "disabled") != 0);
396}
397
398void
399qman_sysinit_portals(void)
400{
401        const char *fdt = bsp_fdt_get();
402        struct device_node dn;
403        const char *name;
404        int cpu_count = (int)rtems_get_processor_count();
405        int i;
406        int ret;
407        int node;
408        int parent;
409
410        memset(&dn, 0, sizeof(dn));
411
412        name = "fsl,qman-portal";
413        node = fdt_node_offset_by_compatible(fdt, 0, name);
414        if (node < 0)
415                panic("qman: no portals in FDT");
416        parent = fdt_parent_offset(fdt, node);
417        if (parent < 0)
418                panic("qman: no parent of portals in FDT");
419        node = fdt_first_subnode(fdt, parent);
420
421        dn.full_name = name;
422        dn.offset = node;
423
424        qoriq_clear_ce_portal(&qoriq_qman_portal[0][0],
425            sizeof(qoriq_qman_portal[0]));
426        qoriq_clear_ci_portal(&qoriq_qman_portal[1][0],
427            sizeof(qoriq_qman_portal[1]));
428
429        for (i = 0; node >= 0 && i < MAX_QMAN_PORTALS; ++i) {
430                struct qm_portal_config *pcfg = &qman_configs[i];
431                struct qman_portal *portal;
432                struct resource res;
433                u32 val;
434
435                ret = of_address_to_resource(&dn, 0, &res);
436                if (ret != 0)
437                        panic("qman: no portal CE address");
438                pcfg->addr_virt[0] = (__iomem void *)
439                    ((uintptr_t)&qoriq_qman_portal[0][0] + (uintptr_t)res.start);
440                BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] >=
441                    (uintptr_t)&qoriq_qman_portal[0][0]);
442                BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] <
443                    (uintptr_t)&qoriq_qman_portal[1][0]);
444
445                ret = of_address_to_resource(&dn, 1, &res);
446                if (ret != 0)
447                        panic("qman: no portal CI address");
448                pcfg->addr_virt[1] = (__iomem void *)
449                    ((uintptr_t)&qoriq_qman_portal[0][0] + (uintptr_t)res.start);
450                BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] >=
451                    (uintptr_t)&qoriq_qman_portal[1][0]);
452                BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] <
453                    (uintptr_t)&qoriq_qman_portal[2][0]);
454
455                ret = of_property_read_u32(&dn, "cell-index", &val);
456                if (ret != 0)
457                        panic("qman: no cell-index");
458                pcfg->channel = val;
459
460                pcfg->irq = of_irq_to_resource(&dn, 0, NULL);
461                if (pcfg->irq == NO_IRQ)
462                        panic("qman: no portal interrupt");
463
464                if (val < cpu_count) {
465                        pcfg->cpu = val;
466
467                        if (is_dequeue_enabled(&dn)) {
468                                pcfg->pools = qm_get_pools_sdqcr();
469                        }
470
471                        portal = init_pcfg(pcfg);
472                        if (portal == NULL)
473                                panic("qman: cannot create portal");
474
475                        qman_portal_update_sdest(pcfg, val);
476                } else {
477                        pcfg->cpu = -1;
478                }
479
480                node = fdt_next_subnode(fdt, node);
481                dn.offset = node;
482        }
483
484        if (i < cpu_count)
485                panic("qman: not enough portals in FDT");
486
487        /* all assigned portals are initialized now */
488        qman_init_cgr_all();
489}
490#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.