source: rtems-libbsd/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c @ f5ed3aa

55-freebsd-126-freebsd-12
Last change on this file since f5ed3aa was f5ed3aa, checked in by Sebastian Huber <sebastian.huber@…>, on 10/27/17 at 09:50:01

sdk_dpaa: Import from QorIQ SDK Linux

http://git.freescale.com/git/cgit.cgi/ppc/sdk/linux.git

Commit 1ae843c08261402b2c35d83422e4fa1e313611f4 (fsl-sdk-v2.0-1703).

Update #3277.

  • Property mode set to 100644
File size: 13.7 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/* Copyright 2008-2013 Freescale Semiconductor Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *     * Redistributions of source code must retain the above copyright
8 *       notice, this list of conditions and the following disclaimer.
9 *     * Redistributions in binary form must reproduce the above copyright
10 *       notice, this list of conditions and the following disclaimer in the
11 *       documentation and/or other materials provided with the distribution.
12 *     * Neither the name of Freescale Semiconductor nor the
13 *       names of its contributors may be used to endorse or promote products
14 *       derived from this software without specific prior written permission.
15 *
16 *
17 * ALTERNATIVELY, this software may be distributed under the terms of the
18 * GNU General Public License ("GPL") as published by the Free Software
19 * Foundation, either version 2 of that License or (at your option) any
20 * later version.
21 *
22 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
23 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
35#define pr_fmt(fmt) \
36        KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
37        KBUILD_BASENAME".c", __LINE__, __func__
38#else
39#define pr_fmt(fmt) \
40        KBUILD_MODNAME ": " fmt
41#endif
42
43#include <linux/init.h>
44#include <linux/module.h>
45#include <linux/of_platform.h>
46#include <linux/of_net.h>
47#include <linux/etherdevice.h>
48#include <linux/kthread.h>
49#include <linux/percpu.h>
50#include <linux/highmem.h>
51#include <linux/fsl_qman.h>
52#include "dpaa_eth.h"
53#include "dpaa_eth_common.h"
54#include "dpaa_eth_base.h"
55#include "lnxwrp_fsl_fman.h" /* fm_get_rx_extra_headroom(), fm_get_max_frm() */
56#include "mac.h"
57
58/* For MAC-based interfaces, we compute the tx needed headroom from the
59 * associated Tx port's buffer layout settings.
60 * For MACless interfaces just use a default value.
61 */
62#define DPA_DEFAULT_TX_HEADROOM 64
63
64#define DPA_DESCRIPTION "FSL DPAA MACless Ethernet driver"
65
66MODULE_LICENSE("Dual BSD/GPL");
67
68MODULE_DESCRIPTION(DPA_DESCRIPTION);
69
70/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */
71static uint16_t macless_tx_timeout = 1000;
72module_param(macless_tx_timeout, ushort, S_IRUGO);
73MODULE_PARM_DESC(macless_tx_timeout, "The MACless Tx timeout in ms");
74
75/* forward declarations */
76static int __cold dpa_macless_start(struct net_device *net_dev);
77static int __cold dpa_macless_stop(struct net_device *net_dev);
78static int __cold dpa_macless_set_address(struct net_device *net_dev,
79                                          void *addr);
80static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev);
81
82static int dpaa_eth_macless_probe(struct platform_device *_of_dev);
83static netdev_features_t
84dpa_macless_fix_features(struct net_device *dev, netdev_features_t features);
85
86static const struct net_device_ops dpa_macless_ops = {
87        .ndo_open = dpa_macless_start,
88        .ndo_start_xmit = dpa_shared_tx,
89        .ndo_stop = dpa_macless_stop,
90        .ndo_tx_timeout = dpa_timeout,
91        .ndo_get_stats64 = dpa_get_stats64,
92        .ndo_set_mac_address = dpa_macless_set_address,
93        .ndo_set_rx_mode = dpa_macless_set_rx_mode,
94        .ndo_validate_addr = eth_validate_addr,
95#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
96        .ndo_select_queue = dpa_select_queue,
97#endif
98        .ndo_change_mtu = dpa_change_mtu,
99        .ndo_init = dpa_ndo_init,
100        .ndo_set_features = dpa_set_features,
101        .ndo_fix_features = dpa_macless_fix_features,
102};
103
104static const struct of_device_id dpa_macless_match[] = {
105        {
106                .compatible     = "fsl,dpa-ethernet-macless"
107        },
108        {}
109};
110MODULE_DEVICE_TABLE(of, dpa_macless_match);
111
112static struct platform_driver dpa_macless_driver = {
113        .driver = {
114                .name           = KBUILD_MODNAME "-macless",
115                .of_match_table = dpa_macless_match,
116                .owner          = THIS_MODULE,
117        },
118        .probe          = dpaa_eth_macless_probe,
119        .remove         = dpa_remove
120};
121
122static const char macless_frame_queues[][25] = {
123        [RX] = "fsl,qman-frame-queues-rx",
124        [TX] = "fsl,qman-frame-queues-tx"
125};
126
127static int __cold dpa_macless_start(struct net_device *net_dev)
128{
129        const struct dpa_priv_s *priv = netdev_priv(net_dev);
130        struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
131
132        netif_tx_start_all_queues(net_dev);
133
134        if (proxy_dev)
135                dpa_proxy_start(net_dev);
136
137
138        return 0;
139}
140
141static int __cold dpa_macless_stop(struct net_device *net_dev)
142{
143        const struct dpa_priv_s *priv = netdev_priv(net_dev);
144        struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
145
146        netif_tx_stop_all_queues(net_dev);
147
148        if (proxy_dev)
149                dpa_proxy_stop(proxy_dev, net_dev);
150
151        return 0;
152}
153
154static int dpa_macless_set_address(struct net_device *net_dev, void *addr)
155{
156        const struct dpa_priv_s *priv = netdev_priv(net_dev);
157        struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
158        int                      _errno;
159
160        _errno = eth_mac_addr(net_dev, addr);
161        if (_errno < 0) {
162                if (netif_msg_drv(priv))
163                        netdev_err(net_dev, "eth_mac_addr() = %d\n", _errno);
164                return _errno;
165        }
166
167        if (proxy_dev) {
168                _errno = dpa_proxy_set_mac_address(proxy_dev, net_dev);
169                if (_errno < 0) {
170                        if (netif_msg_drv(priv))
171                                netdev_err(net_dev, "proxy_set_mac_address() = %d\n",
172                                                _errno);
173                        return _errno;
174                }
175        }
176
177        return 0;
178}
179
180static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev)
181{
182        const struct dpa_priv_s *priv = netdev_priv(net_dev);
183        struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
184
185        if (proxy_dev)
186                dpa_proxy_set_rx_mode(proxy_dev, net_dev);
187}
188
189static netdev_features_t
190dpa_macless_fix_features(struct net_device *dev, netdev_features_t features)
191{
192        netdev_features_t unsupported_features = 0;
193
194        /* In theory we should never be requested to enable features that
195         * we didn't set in netdev->features and netdev->hw_features at probe
196         * time, but double check just to be on the safe side.
197         */
198        unsupported_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
199        /* We don't support enabling Rx csum through ethtool yet */
200        unsupported_features |= NETIF_F_RXCSUM;
201
202        features &= ~unsupported_features;
203
204        return features;
205}
206
207static int dpa_macless_netdev_init(struct device_node *dpa_node,
208                                struct net_device *net_dev)
209{
210        struct dpa_priv_s *priv = netdev_priv(net_dev);
211        struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
212        struct device *dev = net_dev->dev.parent;
213        const uint8_t *mac_addr;
214
215        net_dev->netdev_ops = &dpa_macless_ops;
216
217        if (proxy_dev) {
218                struct mac_device *mac_dev = proxy_dev->mac_dev;
219                net_dev->mem_start = mac_dev->res->start;
220                net_dev->mem_end = mac_dev->res->end;
221
222                return dpa_netdev_init(net_dev, mac_dev->addr,
223                                macless_tx_timeout);
224        } else {
225                /* Get the MAC address from device tree */
226                mac_addr = of_get_mac_address(dpa_node);
227
228                if (mac_addr == NULL) {
229                        if (netif_msg_probe(priv))
230                                dev_err(dev, "No MAC address found!\n");
231                        return -EINVAL;
232                }
233
234                return dpa_netdev_init(net_dev, mac_addr,
235                                macless_tx_timeout);
236        }
237}
238
239/* Probing of FQs for MACless ports */
240static int dpa_fq_probe_macless(struct device *dev, struct list_head *list,
241                                enum port_type ptype)
242{
243        struct device_node *np = dev->of_node;
244        const struct fqid_cell *fqids;
245        int num_ranges;
246        int i, lenp;
247
248        fqids = of_get_property(np, macless_frame_queues[ptype], &lenp);
249        if (fqids == NULL) {
250                dev_err(dev, "Need FQ definition in dts for MACless devices\n");
251                return -EINVAL;
252        }
253
254        num_ranges = lenp / sizeof(*fqids);
255
256        /* All ranges defined in the device tree are used as Rx/Tx queues */
257        for (i = 0; i < num_ranges; i++) {
258                if (!dpa_fq_alloc(dev, be32_to_cpu(fqids[i].start),
259                                  be32_to_cpu(fqids[i].count), list,
260                                  ptype == RX ? FQ_TYPE_RX_PCD : FQ_TYPE_TX)) {
261                        dev_err(dev, "_dpa_fq_alloc() failed\n");
262                        return -ENOMEM;
263                }
264        }
265
266        return 0;
267}
268
269        static struct proxy_device *
270dpa_macless_proxy_probe(struct platform_device *_of_dev)
271{
272        struct device           *dev;
273        const phandle           *proxy_prop;
274        struct proxy_device     *proxy_dev;
275        struct device_node      *proxy_node;
276        struct platform_device  *proxy_pdev;
277        int lenp;
278
279        dev = &_of_dev->dev;
280
281        proxy_prop = of_get_property(dev->of_node, "proxy", &lenp);
282        if (!proxy_prop)
283                return NULL;
284
285        proxy_node = of_find_node_by_phandle(*proxy_prop);
286        if (!proxy_node) {
287                dev_err(dev, "Cannot find proxy node\n");
288                return NULL;
289        }
290
291        proxy_pdev = of_find_device_by_node(proxy_node);
292        if (!proxy_pdev) {
293                of_node_put(proxy_node);
294                dev_err(dev, "Cannot find device represented by proxy node\n");
295                return NULL;
296        }
297
298        proxy_dev = dev_get_drvdata(&proxy_pdev->dev);
299
300        of_node_put(proxy_node);
301
302        return proxy_dev;
303}
304
305static int dpaa_eth_macless_probe(struct platform_device *_of_dev)
306{
307        int err = 0, i, channel;
308        struct device *dev;
309        struct device_node *dpa_node;
310        struct dpa_bp *dpa_bp;
311        size_t count;
312        struct net_device *net_dev = NULL;
313        struct dpa_priv_s *priv = NULL;
314        struct dpa_percpu_priv_s *percpu_priv;
315        static struct proxy_device *proxy_dev;
316        struct task_struct *kth;
317        static u8 macless_idx;
318
319        dev = &_of_dev->dev;
320
321        dpa_node = dev->of_node;
322
323        if (!of_device_is_available(dpa_node))
324                return -ENODEV;
325
326        /* Get the buffer pools assigned to this interface */
327        dpa_bp = dpa_bp_probe(_of_dev, &count);
328        if (IS_ERR(dpa_bp))
329                return PTR_ERR(dpa_bp);
330
331        for (i = 0; i < count; i++)
332                dpa_bp[i].seed_cb = dpa_bp_shared_port_seed;
333
334        proxy_dev = dpa_macless_proxy_probe(_of_dev);
335
336
337        /* Allocate this early, so we can store relevant information in
338         * the private area (needed by 1588 code in dpa_mac_probe)
339         */
340        net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES);
341        if (!net_dev) {
342                dev_err(dev, "alloc_etherdev_mq() failed\n");
343                return -ENOMEM;
344        }
345
346        /* Do this here, so we can be verbose early */
347        SET_NETDEV_DEV(net_dev, dev);
348        dev_set_drvdata(dev, net_dev);
349
350        priv = netdev_priv(net_dev);
351        priv->net_dev = net_dev;
352        sprintf(priv->if_type, "macless%d", macless_idx++);
353
354        priv->msg_enable = netif_msg_init(advanced_debug, -1);
355
356        priv->peer = NULL;
357        priv->mac_dev = NULL;
358        if (proxy_dev) {
359                /* This is a temporary solution for the need of
360                 * having main driver upstreamability: adjust_link
361                 * is a general function that should work for both
362                 * private driver and macless driver with MAC device
363                 * control capabilities even if the last will not be
364                 * upstreamable.
365                 * TODO: find a convenient solution (wrapper over
366                 * main priv structure, etc.)
367                 */
368                priv->mac_dev = proxy_dev->mac_dev;
369
370                /* control over proxy's mac device */
371                priv->peer = (void *)proxy_dev;
372        }
373
374        INIT_LIST_HEAD(&priv->dpa_fq_list);
375
376        err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list, RX);
377        if (!err)
378                err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list,
379                                           TX);
380        if (err < 0)
381                goto fq_probe_failed;
382
383        /* bp init */
384        priv->bp_count = count;
385        err = dpa_bp_create(net_dev, dpa_bp, count);
386        if (err < 0)
387                goto bp_create_failed;
388
389        channel = dpa_get_channel();
390
391        if (channel < 0) {
392                err = channel;
393                goto get_channel_failed;
394        }
395
396        priv->channel = (uint16_t)channel;
397
398        /* Start a thread that will walk the cpus with affine portals
399         * and add this pool channel to each's dequeue mask.
400         */
401        kth = kthread_run(dpaa_eth_add_channel,
402                          (void *)(unsigned long)priv->channel,
403                          "dpaa_%p:%d", net_dev, priv->channel);
404        if (!kth) {
405                err = -ENOMEM;
406                goto add_channel_failed;
407        }
408
409        dpa_fq_setup(priv, &shared_fq_cbs, NULL);
410
411        /* Add the FQs to the interface, and make them active */
412        /* For MAC-less devices we only get here for RX frame queues
413         * initialization, which are the TX queues of the other
414         * partition.
415         * It is safe to rely on one partition to set the FQ taildrop
416         * threshold for the TX queues of the other partition
417         * because the ERN notifications will be received by the
418         * partition doing qman_enqueue.
419         */
420        err = dpa_fqs_init(dev,  &priv->dpa_fq_list, true);
421        if (err < 0)
422                goto fq_alloc_failed;
423
424        priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM;
425
426        priv->percpu_priv = devm_alloc_percpu(dev, *priv->percpu_priv);
427
428        if (priv->percpu_priv == NULL) {
429                dev_err(dev, "devm_alloc_percpu() failed\n");
430                err = -ENOMEM;
431                goto alloc_percpu_failed;
432        }
433        for_each_possible_cpu(i) {
434                percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
435                memset(percpu_priv, 0, sizeof(*percpu_priv));
436        }
437
438        err = dpa_macless_netdev_init(dpa_node, net_dev);
439        if (err < 0)
440                goto netdev_init_failed;
441
442        dpaa_eth_sysfs_init(&net_dev->dev);
443
444        pr_info("fsl_dpa_macless: Probed %s interface as %s\n",
445                        priv->if_type, net_dev->name);
446
447        return 0;
448
449netdev_init_failed:
450alloc_percpu_failed:
451fq_alloc_failed:
452        if (net_dev)
453                dpa_fq_free(dev, &priv->dpa_fq_list);
454add_channel_failed:
455get_channel_failed:
456        if (net_dev)
457                dpa_bp_free(priv);
458bp_create_failed:
459fq_probe_failed:
460        dev_set_drvdata(dev, NULL);
461        if (net_dev)
462                free_netdev(net_dev);
463
464        return err;
465}
466
467static int __init __cold dpa_macless_load(void)
468{
469        int      _errno;
470
471        pr_info(DPA_DESCRIPTION "\n");
472
473        /* Initialize dpaa_eth mirror values */
474        dpa_rx_extra_headroom = fm_get_rx_extra_headroom();
475        dpa_max_frm = fm_get_max_frm();
476
477        _errno = platform_driver_register(&dpa_macless_driver);
478        if (unlikely(_errno < 0)) {
479                pr_err(KBUILD_MODNAME
480                        ": %s:%hu:%s(): platform_driver_register() = %d\n",
481                        KBUILD_BASENAME".c", __LINE__, __func__, _errno);
482        }
483
484        pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
485                KBUILD_BASENAME".c", __func__);
486
487        return _errno;
488}
489module_init(dpa_macless_load);
490
491static void __exit __cold dpa_macless_unload(void)
492{
493        platform_driver_unregister(&dpa_macless_driver);
494
495        pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
496                KBUILD_BASENAME".c", __func__);
497}
498module_exit(dpa_macless_unload);
Note: See TracBrowser for help on using the repository browser.