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

Commit 1ae843c08261402b2c35d83422e4fa1e313611f4 (fsl-sdk-v2.0-1703).
---
 .../ethernet/freescale/sdk_dpaa/dpaa_eth_base.c    | 265 +++++++++++
 .../ethernet/freescale/sdk_dpaa/dpaa_eth_base.h    |  50 ++
 .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.h  | 229 ++++++++++
 .../ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c | 502 +++++++++++++++++++++
 4 files changed, 1046 insertions(+)
 create mode 100644 
linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c
 create mode 100644 
linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.h
 create mode 100644 
linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h
 create mode 100644 
linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c

diff --git a/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c 
b/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c
new file mode 100644
index 000000000..2256d4f1e
--- /dev/null
+++ b/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c
@@ -0,0 +1,265 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *      names of its contributors may be used to endorse or promote products
+ *      derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+       KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+       KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+       KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/percpu.h>
+#include <linux/highmem.h>
+#include <linux/sort.h>
+#include <linux/fsl_qman.h>
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#include "dpaa_eth_base.h"
+
+#define DPA_DESCRIPTION "FSL DPAA Advanced drivers:"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+uint8_t advanced_debug = -1;
+module_param(advanced_debug, byte, S_IRUGO);
+MODULE_PARM_DESC(advanced_debug, "Module/Driver verbosity level");
+EXPORT_SYMBOL(advanced_debug);
+
+static int dpa_bp_cmp(const void *dpa_bp0, const void *dpa_bp1)
+{
+       return ((struct dpa_bp *)dpa_bp0)->size -
+                       ((struct dpa_bp *)dpa_bp1)->size;
+}
+
+struct dpa_bp * __cold __must_check /* __attribute__((nonnull)) */
+dpa_bp_probe(struct platform_device *_of_dev, size_t *count)
+{
+       int                      i, lenp, na, ns, err;
+       struct device           *dev;
+       struct device_node      *dev_node;
+       const __be32            *bpool_cfg;
+       struct dpa_bp           *dpa_bp;
+       u32                     bpid;
+
+       dev = &_of_dev->dev;
+
+       *count = of_count_phandle_with_args(dev->of_node,
+                       "fsl,bman-buffer-pools", NULL);
+       if (*count < 1) {
+               dev_err(dev, "missing fsl,bman-buffer-pools device tree 
entry\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       dpa_bp = devm_kzalloc(dev, *count * sizeof(*dpa_bp), GFP_KERNEL);
+       if (dpa_bp == NULL) {
+               dev_err(dev, "devm_kzalloc() failed\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       dev_node = of_find_node_by_path("/");
+       if (unlikely(dev_node == NULL)) {
+               dev_err(dev, "of_find_node_by_path(/) failed\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       na = of_n_addr_cells(dev_node);
+       ns = of_n_size_cells(dev_node);
+
+       for (i = 0; i < *count; i++) {
+               of_node_put(dev_node);
+
+               dev_node = of_parse_phandle(dev->of_node,
+                               "fsl,bman-buffer-pools", i);
+               if (dev_node == NULL) {
+                       dev_err(dev, "of_find_node_by_phandle() failed\n");
+                       return ERR_PTR(-EFAULT);
+               }
+
+               if (unlikely(!of_device_is_compatible(dev_node, "fsl,bpool"))) {
+                       dev_err(dev,
+                               "!of_device_is_compatible(%s, fsl,bpool)\n",
+                               dev_node->full_name);
+                       dpa_bp = ERR_PTR(-EINVAL);
+                       goto _return_of_node_put;
+               }
+
+               err = of_property_read_u32(dev_node, "fsl,bpid", &bpid);
+               if (err) {
+                       dev_err(dev, "Cannot find buffer pool ID in the device 
tree\n");
+                       dpa_bp = ERR_PTR(-EINVAL);
+                       goto _return_of_node_put;
+               }
+               dpa_bp[i].bpid = (uint8_t)bpid;
+
+               bpool_cfg = of_get_property(dev_node, "fsl,bpool-ethernet-cfg",
+                                       &lenp);
+               if (bpool_cfg && (lenp == (2 * ns + na) * sizeof(*bpool_cfg))) {
+                       const uint32_t *seed_pool;
+
+                       dpa_bp[i].config_count =
+                               (int)of_read_number(bpool_cfg, ns);
+                       dpa_bp[i].size  =
+                               (size_t)of_read_number(bpool_cfg + ns, ns);
+                       dpa_bp[i].paddr =
+                               of_read_number(bpool_cfg + 2 * ns, na);
+
+                       seed_pool = of_get_property(dev_node,
+                                       "fsl,bpool-ethernet-seeds", &lenp);
+                       dpa_bp[i].seed_pool = !!seed_pool;
+
+               } else {
+                       dev_err(dev,
+                               "Missing/invalid fsl,bpool-ethernet-cfg device 
tree entry for node %s\n",
+                               dev_node->full_name);
+                       dpa_bp = ERR_PTR(-EINVAL);
+                       goto _return_of_node_put;
+               }
+       }
+
+       sort(dpa_bp, *count, sizeof(*dpa_bp), dpa_bp_cmp, NULL);
+
+       return dpa_bp;
+
+_return_of_node_put:
+       if (dev_node)
+               of_node_put(dev_node);
+
+       return dpa_bp;
+}
+EXPORT_SYMBOL(dpa_bp_probe);
+
+int dpa_bp_shared_port_seed(struct dpa_bp *bp)
+{
+       void __iomem **ptr;
+
+       /* In MAC-less and Shared-MAC scenarios the physical
+        * address of the buffer pool in device tree is set
+        * to 0 to specify that another entity (USDPAA) will
+        * allocate and seed the buffers
+        */
+       if (!bp->paddr)
+               return 0;
+
+       /* allocate memory region for buffers */
+       devm_request_mem_region(bp->dev, bp->paddr,
+                       bp->size * bp->config_count, KBUILD_MODNAME);
+       /* managed ioremap unmapping */
+       ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return -EIO;
+#ifndef CONFIG_PPC
+       bp->vaddr = ioremap_cache_ns(bp->paddr, bp->size * bp->config_count);
+#else
+       bp->vaddr = ioremap_prot(bp->paddr, bp->size * bp->config_count, 0);
+#endif
+       if (bp->vaddr == NULL) {
+               pr_err("Could not map memory for pool %d\n", bp->bpid);
+               devres_free(ptr);
+               return -EIO;
+       }
+       *ptr = bp->vaddr;
+       devres_add(bp->dev, ptr);
+
+       /* seed pool with buffers from that memory region */
+       if (bp->seed_pool) {
+               int count = bp->target_count;
+               dma_addr_t addr = bp->paddr;
+
+               while (count) {
+                       struct bm_buffer bufs[8];
+                       uint8_t num_bufs = 0;
+
+                       do {
+                               BUG_ON(addr > 0xffffffffffffull);
+                               bufs[num_bufs].bpid = bp->bpid;
+                               bm_buffer_set64(&bufs[num_bufs++], addr);
+                               addr += bp->size;
+
+                       } while (--count && (num_bufs < 8));
+
+                       while (bman_release(bp->pool, bufs, num_bufs, 0))
+                               cpu_relax();
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(dpa_bp_shared_port_seed);
+
+int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp,
+               size_t count)
+{
+       struct dpa_priv_s *priv = netdev_priv(net_dev);
+       int i;
+
+       priv->dpa_bp = dpa_bp;
+       priv->bp_count = count;
+
+       for (i = 0; i < count; i++) {
+               int err;
+               err = dpa_bp_alloc(&dpa_bp[i]);
+               if (err < 0) {
+                       dpa_bp_free(priv);
+                       priv->dpa_bp = NULL;
+                       return err;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(dpa_bp_create);
+
+static int __init __cold dpa_advanced_load(void)
+{
+       pr_info(DPA_DESCRIPTION "\n");
+
+       return 0;
+}
+module_init(dpa_advanced_load);
+
+static void __exit __cold dpa_advanced_unload(void)
+{
+       pr_debug(KBUILD_MODNAME ": -> %s:%s()\n",
+                KBUILD_BASENAME".c", __func__);
+
+}
+module_exit(dpa_advanced_unload);
diff --git a/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.h 
b/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.h
new file mode 100644
index 000000000..6f5704132
--- /dev/null
+++ b/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.h
@@ -0,0 +1,50 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *      names of its contributors may be used to endorse or promote products
+ *      derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DPAA_ETH_BASE_H
+#define __DPAA_ETH_BASE_H
+
+#include <linux/etherdevice.h> /* struct net_device */
+#include <linux/fsl_bman.h> /* struct bm_buffer */
+#include <linux/of_platform.h> /* struct platform_device */
+#include <linux/net_tstamp.h>  /* struct hwtstamp_config */
+
+extern uint8_t advanced_debug;
+extern const struct dpa_fq_cbs_t shared_fq_cbs;
+extern int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device 
*net_dev);
+
+struct dpa_bp * __cold __must_check /* __attribute__((nonnull)) */
+dpa_bp_probe(struct platform_device *_of_dev, size_t *count);
+int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp,
+               size_t count);
+int dpa_bp_shared_port_seed(struct dpa_bp *bp);
+
+#endif /* __DPAA_ETH_BASE_H */
diff --git a/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h 
b/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h
new file mode 100644
index 000000000..022b4c2d0
--- /dev/null
+++ b/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h
@@ -0,0 +1,229 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *      names of its contributors may be used to endorse or promote products
+ *      derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DPAA_ETH_COMMON_H
+#define __DPAA_ETH_COMMON_H
+
+#include <linux/etherdevice.h> /* struct net_device */
+#include <linux/fsl_bman.h> /* struct bm_buffer */
+#include <linux/of_platform.h> /* struct platform_device */
+#include <linux/net_tstamp.h>  /* struct hwtstamp_config */
+
+#include "dpaa_eth.h"
+#include "lnxwrp_fsl_fman.h"
+
+#define dpaa_eth_init_port(type, port, param, errq_id, defq_id, buf_layout,\
+                          frag_enabled) \
+{ \
+       param.errq = errq_id; \
+       param.defq = defq_id; \
+       param.priv_data_size = buf_layout->priv_data_size; \
+       param.parse_results = buf_layout->parse_results; \
+       param.hash_results = buf_layout->hash_results; \
+       param.frag_enable = frag_enabled; \
+       param.time_stamp = buf_layout->time_stamp; \
+       param.manip_extra_space = buf_layout->manip_extra_space; \
+       param.data_align = buf_layout->data_align; \
+       fm_set_##type##_port_params(port, &param); \
+}
+
+#define DPA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */
+
+#define DPA_SGT_ENTRIES_THRESHOLD      DPA_SGT_MAX_ENTRIES
+#ifndef CONFIG_PPC
+/* each S/G entry can be divided into two S/G entries during errata W/A */
+#define DPA_SGT_4K_ENTRIES_THRESHOLD   7
+#endif
+
+#define DPA_BUFF_RELEASE_MAX 8 /* maximum number of buffers released at once */
+
+#define DPA_RX_PCD_HI_PRIO_FQ_INIT_FAIL(dpa_fq, _errno) \
+       (((dpa_fq)->fq_type == FQ_TYPE_RX_PCD_HI_PRIO) && \
+         (_errno == -EIO))
+/* return codes for the dpaa-eth hooks */
+enum dpaa_eth_hook_result {
+       /* fd/skb was retained by the hook.
+        *
+        * On the Rx path, this means the Ethernet driver will _not_
+        * deliver the skb to the stack. Instead, the hook implementation
+        * is expected to properly dispose of the skb.
+        *
+        * On the Tx path, the Ethernet driver's dpa_tx() function will
+        * immediately return NETDEV_TX_OK. The hook implementation is expected
+        * to free the skb. *DO*NOT* release it to BMan, or enqueue it to FMan,
+        * unless you know exactly what you're doing!
+        *
+        * On the confirmation/error paths, the Ethernet driver will _not_
+        * perform any fd cleanup, nor update the interface statistics.
+        */
+       DPAA_ETH_STOLEN,
+       /* fd/skb was returned to the Ethernet driver for regular processing.
+        * The hook is not allowed to, for instance, reallocate the skb (as if
+        * by linearizing, copying, cloning or reallocating the headroom).
+        */
+       DPAA_ETH_CONTINUE
+};
+
+typedef enum dpaa_eth_hook_result (*dpaa_eth_ingress_hook_t)(
+               struct sk_buff *skb, struct net_device *net_dev, u32 fqid);
+typedef enum dpaa_eth_hook_result (*dpaa_eth_egress_hook_t)(
+               struct sk_buff *skb, struct net_device *net_dev);
+typedef enum dpaa_eth_hook_result (*dpaa_eth_confirm_hook_t)(
+               struct net_device *net_dev, const struct qm_fd *fd, u32 fqid);
+
+/* used in napi related functions */
+extern u16 qman_portal_max;
+
+/* from dpa_ethtool.c */
+extern const struct ethtool_ops dpa_ethtool_ops;
+
+#ifdef CONFIG_FSL_DPAA_HOOKS
+/* Various hooks used for unit-testing and/or fastpath optimizations.
+ * Currently only one set of such hooks is supported.
+ */
+struct dpaa_eth_hooks_s {
+       /* Invoked on the Tx private path, immediately after receiving the skb
+        * from the stack.
+        */
+       dpaa_eth_egress_hook_t  tx;
+
+       /* Invoked on the Rx private path, right before passing the skb
+        * up the stack. At that point, the packet's protocol id has already
+        * been set. The skb's data pointer is now at the L3 header, and
+        * skb->mac_header points to the L2 header. skb->len has been adjusted
+        * to be the length of L3+payload (i.e., the length of the
+        * original frame minus the L2 header len).
+        * For more details on what the skb looks like, see eth_type_trans().
+        */
+       dpaa_eth_ingress_hook_t rx_default;
+
+       /* Driver hook for the Rx error private path. */
+       dpaa_eth_confirm_hook_t rx_error;
+       /* Driver hook for the Tx confirmation private path. */
+       dpaa_eth_confirm_hook_t tx_confirm;
+       /* Driver hook for the Tx error private path. */
+       dpaa_eth_confirm_hook_t tx_error;
+};
+
+void fsl_dpaa_eth_set_hooks(struct dpaa_eth_hooks_s *hooks);
+
+extern struct dpaa_eth_hooks_s dpaa_eth_hooks;
+#endif
+
+int dpa_netdev_init(struct net_device *net_dev,
+                   const uint8_t *mac_addr,
+                   uint16_t tx_timeout);
+int __cold dpa_start(struct net_device *net_dev);
+int __cold dpa_stop(struct net_device *net_dev);
+void __cold dpa_timeout(struct net_device *net_dev);
+struct rtnl_link_stats64 * __cold
+dpa_get_stats64(struct net_device *net_dev,
+               struct rtnl_link_stats64 *stats);
+int dpa_change_mtu(struct net_device *net_dev, int new_mtu);
+int dpa_ndo_init(struct net_device *net_dev);
+int dpa_set_features(struct net_device *dev, netdev_features_t features);
+netdev_features_t dpa_fix_features(struct net_device *dev,
+               netdev_features_t features);
+#ifdef CONFIG_FSL_DPAA_TS
+u64 dpa_get_timestamp_ns(const struct dpa_priv_s *priv,
+                       enum port_type rx_tx, const void *data);
+/* Updates the skb shared hw timestamp from the hardware timestamp */
+int dpa_get_ts(const struct dpa_priv_s *priv, enum port_type rx_tx,
+       struct skb_shared_hwtstamps *shhwtstamps, const void *data);
+#endif /* CONFIG_FSL_DPAA_TS */
+int dpa_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+int __cold dpa_remove(struct platform_device *of_dev);
+struct mac_device * __cold __must_check
+__attribute__((nonnull)) dpa_mac_probe(struct platform_device *_of_dev);
+int dpa_set_mac_address(struct net_device *net_dev, void *addr);
+void dpa_set_rx_mode(struct net_device *net_dev);
+void dpa_set_buffers_layout(struct mac_device *mac_dev,
+               struct dpa_buffer_layout_s *layout);
+int __attribute__((nonnull))
+dpa_bp_alloc(struct dpa_bp *dpa_bp);
+void __cold __attribute__((nonnull))
+dpa_bp_free(struct dpa_priv_s *priv);
+struct dpa_bp *dpa_bpid2pool(int bpid);
+void dpa_bpid2pool_map(int bpid, struct dpa_bp *dpa_bp);
+bool dpa_bpid2pool_use(int bpid);
+void dpa_bp_drain(struct dpa_bp *bp);
+#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
+u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb,
+                    void *accel_priv, select_queue_fallback_t fallback);
+#endif
+struct dpa_fq *dpa_fq_alloc(struct device *dev,
+                           u32 fq_start,
+                           u32 fq_count,
+                           struct list_head *list,
+                           enum dpa_fq_type fq_type);
+int dpa_fq_probe_mac(struct device *dev, struct list_head *list,
+                    struct fm_port_fqs *port_fqs,
+                    bool tx_conf_fqs_per_core,
+                    enum port_type ptype);
+int dpa_get_channel(void);
+void dpa_release_channel(void);
+int dpaa_eth_add_channel(void *__arg);
+int dpaa_eth_cgr_init(struct dpa_priv_s *priv);
+void dpa_fq_setup(struct dpa_priv_s *priv, const struct dpa_fq_cbs_t *fq_cbs,
+               struct fm_port *tx_port);
+int dpa_fq_init(struct dpa_fq *dpa_fq, bool td_enable);
+int dpa_fqs_init(struct device *dev, struct list_head *list, bool td_enable);
+int __cold __attribute__((nonnull))
+dpa_fq_free(struct device *dev, struct list_head *list);
+void dpaa_eth_init_ports(struct mac_device *mac_dev,
+               struct dpa_bp *bp, size_t count,
+               struct fm_port_fqs *port_fqs,
+               struct dpa_buffer_layout_s *buf_layout,
+               struct device *dev);
+void dpa_release_sgt(struct qm_sg_entry *sgt);
+void __attribute__((nonnull))
+dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd);
+void count_ern(struct dpa_percpu_priv_s *percpu_priv,
+                     const struct qm_mr_entry *msg);
+int dpa_enable_tx_csum(struct dpa_priv_s *priv,
+       struct sk_buff *skb, struct qm_fd *fd, char *parse_results);
+#ifdef CONFIG_FSL_DPAA_CEETM
+void dpa_enable_ceetm(struct net_device *dev);
+void dpa_disable_ceetm(struct net_device *dev);
+#endif
+struct proxy_device {
+               struct mac_device *mac_dev;
+};
+
+/* mac device control functions exposed by proxy interface*/
+int dpa_proxy_start(struct net_device *net_dev);
+int dpa_proxy_stop(struct proxy_device *proxy_dev, struct net_device *net_dev);
+int dpa_proxy_set_mac_address(struct proxy_device *proxy_dev,
+                         struct net_device *net_dev);
+int dpa_proxy_set_rx_mode(struct proxy_device *proxy_dev,
+                     struct net_device *net_dev);
+
+#endif /* __DPAA_ETH_COMMON_H */
diff --git a/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c 
b/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c
new file mode 100644
index 000000000..78abf79f1
--- /dev/null
+++ b/linux/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c
@@ -0,0 +1,502 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/* Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *      names of its contributors may be used to endorse or promote products
+ *      derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+       KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+       KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+       KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/percpu.h>
+#ifndef __rtems__
+#include <linux/highmem.h>
+#include <linux/fsl_qman.h>
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#include "dpaa_eth_base.h"
+#include "lnxwrp_fsl_fman.h" /* fm_get_rx_extra_headroom(), fm_get_max_frm() */
+#include "mac.h"
+#endif /* __rtems__ */
+
+/* For MAC-based interfaces, we compute the tx needed headroom from the
+ * associated Tx port's buffer layout settings.
+ * For MACless interfaces just use a default value.
+ */
+#define DPA_DEFAULT_TX_HEADROOM        64
+
+#define DPA_DESCRIPTION "FSL DPAA MACless Ethernet driver"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+MODULE_DESCRIPTION(DPA_DESCRIPTION);
+
+#ifndef __rtems__
+/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */
+static uint16_t macless_tx_timeout = 1000;
+module_param(macless_tx_timeout, ushort, S_IRUGO);
+MODULE_PARM_DESC(macless_tx_timeout, "The MACless Tx timeout in ms");
+#endif /* __rtems__ */
+
+/* forward declarations */
+static int __cold dpa_macless_start(struct net_device *net_dev);
+static int __cold dpa_macless_stop(struct net_device *net_dev);
+static int __cold dpa_macless_set_address(struct net_device *net_dev,
+                                         void *addr);
+static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev);
+
+static int dpaa_eth_macless_probe(struct platform_device *_of_dev);
+static netdev_features_t
+dpa_macless_fix_features(struct net_device *dev, netdev_features_t features);
+
+static const struct net_device_ops dpa_macless_ops = {
+       .ndo_open = dpa_macless_start,
+       .ndo_start_xmit = dpa_shared_tx,
+       .ndo_stop = dpa_macless_stop,
+       .ndo_tx_timeout = dpa_timeout,
+       .ndo_get_stats64 = dpa_get_stats64,
+       .ndo_set_mac_address = dpa_macless_set_address,
+       .ndo_set_rx_mode = dpa_macless_set_rx_mode,
+       .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
+       .ndo_select_queue = dpa_select_queue,
+#endif
+       .ndo_change_mtu = dpa_change_mtu,
+       .ndo_init = dpa_ndo_init,
+       .ndo_set_features = dpa_set_features,
+       .ndo_fix_features = dpa_macless_fix_features,
+};
+
+static const struct of_device_id dpa_macless_match[] = {
+       {
+               .compatible     = "fsl,dpa-ethernet-macless"
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, dpa_macless_match);
+
+static struct platform_driver dpa_macless_driver = {
+       .driver = {
+               .name           = KBUILD_MODNAME "-macless",
+               .of_match_table = dpa_macless_match,
+               .owner          = THIS_MODULE,
+       },
+       .probe          = dpaa_eth_macless_probe,
+       .remove         = dpa_remove
+};
+
+static const char macless_frame_queues[][25] = {
+       [RX] = "fsl,qman-frame-queues-rx",
+       [TX] = "fsl,qman-frame-queues-tx"
+};
+
+static int __cold dpa_macless_start(struct net_device *net_dev)
+{
+       const struct dpa_priv_s *priv = netdev_priv(net_dev);
+       struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+
+       netif_tx_start_all_queues(net_dev);
+
+       if (proxy_dev)
+               dpa_proxy_start(net_dev);
+
+
+       return 0;
+}
+
+static int __cold dpa_macless_stop(struct net_device *net_dev)
+{
+       const struct dpa_priv_s *priv = netdev_priv(net_dev);
+       struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+
+       netif_tx_stop_all_queues(net_dev);
+
+       if (proxy_dev)
+               dpa_proxy_stop(proxy_dev, net_dev);
+
+       return 0;
+}
+
+static int dpa_macless_set_address(struct net_device *net_dev, void *addr)
+{
+       const struct dpa_priv_s *priv = netdev_priv(net_dev);
+       struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+       int                      _errno;
+
+       _errno = eth_mac_addr(net_dev, addr);
+       if (_errno < 0) {
+               if (netif_msg_drv(priv))
+                       netdev_err(net_dev, "eth_mac_addr() = %d\n", _errno);
+               return _errno;
+       }
+
+       if (proxy_dev) {
+               _errno = dpa_proxy_set_mac_address(proxy_dev, net_dev);
+               if (_errno < 0) {
+                       if (netif_msg_drv(priv))
+                               netdev_err(net_dev, "proxy_set_mac_address() = 
%d\n",
+                                               _errno);
+                       return _errno;
+               }
+       }
+
+       return 0;
+}
+
+static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev)
+{
+       const struct dpa_priv_s *priv = netdev_priv(net_dev);
+       struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+
+       if (proxy_dev)
+               dpa_proxy_set_rx_mode(proxy_dev, net_dev);
+}
+
+static netdev_features_t
+dpa_macless_fix_features(struct net_device *dev, netdev_features_t features)
+{
+       netdev_features_t unsupported_features = 0;
+
+       /* In theory we should never be requested to enable features that
+        * we didn't set in netdev->features and netdev->hw_features at probe
+        * time, but double check just to be on the safe side.
+        */
+       unsupported_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+       /* We don't support enabling Rx csum through ethtool yet */
+       unsupported_features |= NETIF_F_RXCSUM;
+
+       features &= ~unsupported_features;
+
+       return features;
+}
+
+static int dpa_macless_netdev_init(struct device_node *dpa_node,
+                               struct net_device *net_dev)
+{
+       struct dpa_priv_s *priv = netdev_priv(net_dev);
+       struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+       struct device *dev = net_dev->dev.parent;
+       const uint8_t *mac_addr;
+
+       net_dev->netdev_ops = &dpa_macless_ops;
+
+       if (proxy_dev) {
+               struct mac_device *mac_dev = proxy_dev->mac_dev;
+               net_dev->mem_start = mac_dev->res->start;
+               net_dev->mem_end = mac_dev->res->end;
+
+               return dpa_netdev_init(net_dev, mac_dev->addr,
+                               macless_tx_timeout);
+       } else {
+               /* Get the MAC address from device tree */
+               mac_addr = of_get_mac_address(dpa_node);
+
+               if (mac_addr == NULL) {
+                       if (netif_msg_probe(priv))
+                               dev_err(dev, "No MAC address found!\n");
+                       return -EINVAL;
+               }
+
+               return dpa_netdev_init(net_dev, mac_addr,
+                               macless_tx_timeout);
+       }
+}
+
+/* Probing of FQs for MACless ports */
+static int dpa_fq_probe_macless(struct device *dev, struct list_head *list,
+                               enum port_type ptype)
+{
+       struct device_node *np = dev->of_node;
+       const struct fqid_cell *fqids;
+       int num_ranges;
+       int i, lenp;
+
+       fqids = of_get_property(np, macless_frame_queues[ptype], &lenp);
+       if (fqids == NULL) {
+               dev_err(dev, "Need FQ definition in dts for MACless devices\n");
+               return -EINVAL;
+       }
+
+       num_ranges = lenp / sizeof(*fqids);
+
+       /* All ranges defined in the device tree are used as Rx/Tx queues */
+       for (i = 0; i < num_ranges; i++) {
+               if (!dpa_fq_alloc(dev, be32_to_cpu(fqids[i].start),
+                                 be32_to_cpu(fqids[i].count), list,
+                                 ptype == RX ? FQ_TYPE_RX_PCD : FQ_TYPE_TX)) {
+                       dev_err(dev, "_dpa_fq_alloc() failed\n");
+                       return -ENOMEM;
+               }
+       }
+
+       return 0;
+}
+
+       static struct proxy_device *
+dpa_macless_proxy_probe(struct platform_device *_of_dev)
+{
+       struct device           *dev;
+       const phandle           *proxy_prop;
+       struct proxy_device     *proxy_dev;
+       struct device_node      *proxy_node;
+       struct platform_device  *proxy_pdev;
+       int lenp;
+
+       dev = &_of_dev->dev;
+
+       proxy_prop = of_get_property(dev->of_node, "proxy", &lenp);
+       if (!proxy_prop)
+               return NULL;
+
+       proxy_node = of_find_node_by_phandle(*proxy_prop);
+       if (!proxy_node) {
+               dev_err(dev, "Cannot find proxy node\n");
+               return NULL;
+       }
+
+       proxy_pdev = of_find_device_by_node(proxy_node);
+       if (!proxy_pdev) {
+               of_node_put(proxy_node);
+               dev_err(dev, "Cannot find device represented by proxy node\n");
+               return NULL;
+       }
+
+       proxy_dev = dev_get_drvdata(&proxy_pdev->dev);
+
+       of_node_put(proxy_node);
+
+       return proxy_dev;
+}
+
+static int dpaa_eth_macless_probe(struct platform_device *_of_dev)
+{
+       int err = 0, i, channel;
+       struct device *dev;
+       struct device_node *dpa_node;
+       struct dpa_bp *dpa_bp;
+       size_t count;
+       struct net_device *net_dev = NULL;
+       struct dpa_priv_s *priv = NULL;
+       struct dpa_percpu_priv_s *percpu_priv;
+       static struct proxy_device *proxy_dev;
+       struct task_struct *kth;
+       static u8 macless_idx;
+
+       dev = &_of_dev->dev;
+
+       dpa_node = dev->of_node;
+
+       if (!of_device_is_available(dpa_node))
+               return -ENODEV;
+
+       /* Get the buffer pools assigned to this interface */
+       dpa_bp = dpa_bp_probe(_of_dev, &count);
+       if (IS_ERR(dpa_bp))
+               return PTR_ERR(dpa_bp);
+
+       for (i = 0; i < count; i++)
+               dpa_bp[i].seed_cb = dpa_bp_shared_port_seed;
+
+       proxy_dev = dpa_macless_proxy_probe(_of_dev);
+
+
+       /* Allocate this early, so we can store relevant information in
+        * the private area (needed by 1588 code in dpa_mac_probe)
+        */
+       net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES);
+       if (!net_dev) {
+               dev_err(dev, "alloc_etherdev_mq() failed\n");
+               return -ENOMEM;
+       }
+
+       /* Do this here, so we can be verbose early */
+       SET_NETDEV_DEV(net_dev, dev);
+       dev_set_drvdata(dev, net_dev);
+
+       priv = netdev_priv(net_dev);
+       priv->net_dev = net_dev;
+       sprintf(priv->if_type, "macless%d", macless_idx++);
+
+       priv->msg_enable = netif_msg_init(advanced_debug, -1);
+
+       priv->peer = NULL;
+       priv->mac_dev = NULL;
+       if (proxy_dev) {
+               /* This is a temporary solution for the need of
+                * having main driver upstreamability: adjust_link
+                * is a general function that should work for both
+                * private driver and macless driver with MAC device
+                * control capabilities even if the last will not be
+                * upstreamable.
+                * TODO: find a convenient solution (wrapper over
+                * main priv structure, etc.)
+                */
+               priv->mac_dev = proxy_dev->mac_dev;
+
+               /* control over proxy's mac device */
+               priv->peer = (void *)proxy_dev;
+       }
+
+       INIT_LIST_HEAD(&priv->dpa_fq_list);
+
+       err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list, RX);
+       if (!err)
+               err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list,
+                                          TX);
+       if (err < 0)
+               goto fq_probe_failed;
+
+       /* bp init */
+       priv->bp_count = count;
+       err = dpa_bp_create(net_dev, dpa_bp, count);
+       if (err < 0)
+               goto bp_create_failed;
+
+       channel = dpa_get_channel();
+
+       if (channel < 0) {
+               err = channel;
+               goto get_channel_failed;
+       }
+
+       priv->channel = (uint16_t)channel;
+
+       /* Start a thread that will walk the cpus with affine portals
+        * and add this pool channel to each's dequeue mask.
+        */
+       kth = kthread_run(dpaa_eth_add_channel,
+                         (void *)(unsigned long)priv->channel,
+                         "dpaa_%p:%d", net_dev, priv->channel);
+       if (!kth) {
+               err = -ENOMEM;
+               goto add_channel_failed;
+       }
+
+       dpa_fq_setup(priv, &shared_fq_cbs, NULL);
+
+       /* Add the FQs to the interface, and make them active */
+       /* For MAC-less devices we only get here for RX frame queues
+        * initialization, which are the TX queues of the other
+        * partition.
+        * It is safe to rely on one partition to set the FQ taildrop
+        * threshold for the TX queues of the other partition
+        * because the ERN notifications will be received by the
+        * partition doing qman_enqueue.
+        */
+       err = dpa_fqs_init(dev,  &priv->dpa_fq_list, true);
+       if (err < 0)
+               goto fq_alloc_failed;
+
+       priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM;
+
+       priv->percpu_priv = devm_alloc_percpu(dev, *priv->percpu_priv);
+
+       if (priv->percpu_priv == NULL) {
+               dev_err(dev, "devm_alloc_percpu() failed\n");
+               err = -ENOMEM;
+               goto alloc_percpu_failed;
+       }
+       for_each_possible_cpu(i) {
+               percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+               memset(percpu_priv, 0, sizeof(*percpu_priv));
+       }
+
+       err = dpa_macless_netdev_init(dpa_node, net_dev);
+       if (err < 0)
+               goto netdev_init_failed;
+
+       dpaa_eth_sysfs_init(&net_dev->dev);
+
+       pr_info("fsl_dpa_macless: Probed %s interface as %s\n",
+                       priv->if_type, net_dev->name);
+
+       return 0;
+
+netdev_init_failed:
+alloc_percpu_failed:
+fq_alloc_failed:
+       if (net_dev)
+               dpa_fq_free(dev, &priv->dpa_fq_list);
+add_channel_failed:
+get_channel_failed:
+       if (net_dev)
+               dpa_bp_free(priv);
+bp_create_failed:
+fq_probe_failed:
+       dev_set_drvdata(dev, NULL);
+       if (net_dev)
+               free_netdev(net_dev);
+
+       return err;
+}
+
+static int __init __cold dpa_macless_load(void)
+{
+       int      _errno;
+
+       pr_info(DPA_DESCRIPTION "\n");
+
+       /* Initialize dpaa_eth mirror values */
+       dpa_rx_extra_headroom = fm_get_rx_extra_headroom();
+       dpa_max_frm = fm_get_max_frm();
+
+       _errno = platform_driver_register(&dpa_macless_driver);
+       if (unlikely(_errno < 0)) {
+               pr_err(KBUILD_MODNAME
+                       ": %s:%hu:%s(): platform_driver_register() = %d\n",
+                       KBUILD_BASENAME".c", __LINE__, __func__, _errno);
+       }
+
+       pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+               KBUILD_BASENAME".c", __func__);
+
+       return _errno;
+}
+module_init(dpa_macless_load);
+
+static void __exit __cold dpa_macless_unload(void)
+{
+       platform_driver_unregister(&dpa_macless_driver);
+
+       pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+               KBUILD_BASENAME".c", __func__);
+}
+module_exit(dpa_macless_unload);
-- 
2.12.3

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to