From 167b34de1baac527e66eccceb3eddc2776d9a520 Mon Sep 17 00:00:00 2001 From: Madalin Bucur Date: Mon, 17 Jun 2013 15:00:25 +0300 Subject: dpaa_eth: move MACless interface code to a new file Separated the code related to MACless interfaces. Signed-off-by: Madalin Bucur Change-Id: I85ece5c7857c3044fa47592c33dc1e9e532fb33c Reviewed-on: http://git.am.freescale.net:8181/3087 Reviewed-by: Sovaiala Cristian-Constantin-B39531 Reviewed-by: Radulescu Ruxandra Ioana-B05472 Reviewed-by: Fleming Andrew-AFLEMING Tested-by: Fleming Andrew-AFLEMING diff --git a/drivers/net/ethernet/freescale/dpa/Makefile b/drivers/net/ethernet/freescale/dpa/Makefile index 7432374..9e34be9 100644 --- a/drivers/net/ethernet/freescale/dpa/Makefile +++ b/drivers/net/ethernet/freescale/dpa/Makefile @@ -13,13 +13,14 @@ obj-$(CONFIG_FSL_DPAA_ETH_SG_SUPPORT) += fsl-dpa-sg.o # dpaa_debugfs needs to be initialized before dpaa_eth obj-$(CONFIG_FSL_DPAA_ETH_DEBUGFS) += dpaa_debugfs.o obj-$(CONFIG_FSL_DPAA_ETH) += fsl-mac.o fsl-dpa.o fsl-dpa-shared.o \ - fsl-dpa-proxy.o + fsl-dpa-macless.o fsl-dpa-proxy.o obj-$(CONFIG_FSL_DPAA_OFFLINE_PORTS) += fsl-oh.o obj-$(CONFIG_FSL_DPAA_ETH_UNIT_TESTS) += dpaa_eth_unit_test.o fsl-dpa-objs := dpa-ethtool.o dpaa_eth.o dpaa_eth_sysfs.o fsl-dpa-sg-objs := dpaa_eth_sg.o fsl-dpa-shared-objs := dpaa_eth_shared.o +fsl-dpa-macless-objs := dpaa_eth_macless.o fsl-dpa-proxy-objs := dpaa_eth_proxy.o fsl-mac-objs := mac.o mac-api.o fsl-oh-objs := offline_port.o diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c index b8de8b9..173c588 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c @@ -137,12 +137,6 @@ */ #define DPA_RECYCLE_EXTRA_SIZE 1024 -/* 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 Ethernet driver" MODULE_LICENSE("Dual BSD/GPL"); @@ -526,7 +520,7 @@ static struct qman_fq *_dpa_get_tx_conf_queue(const struct dpa_priv_s *priv, return NULL; } -int dpa_fq_init(struct dpa_fq *dpa_fq) +int dpa_fq_init(struct dpa_fq *dpa_fq, bool td_enable) { int _errno; const struct dpa_priv_s *priv; @@ -598,16 +592,7 @@ int dpa_fq_init(struct dpa_fq *dpa_fq) priv->tx_headroom, (size_t)FSL_QMAN_MAX_OAL); } - /* - * 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. - */ - if (!priv->mac_dev) { + if (td_enable) { initfq.we_mask |= QM_INITFQ_WE_TDTHRESH; qm_fqd_taildrop_set(&initfq.fqd.td, DPA_FQ_TD, 1); @@ -964,25 +949,6 @@ int dpa_set_mac_address(struct net_device *net_dev, void *addr) return 0; } -static int dpa_set_macless_address(struct net_device *net_dev, void *addr) -{ - const struct dpa_priv_s *priv; - int _errno; - - priv = netdev_priv(net_dev); - - _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; - } - - return 0; -} - void dpa_set_rx_mode(struct net_device *net_dev) { int _errno; @@ -1006,9 +972,6 @@ void dpa_set_rx_mode(struct net_device *net_dev) netdev_err(net_dev, "mac_dev->set_multi() = %d\n", _errno); } -static void dpa_set_macless_rx_mode(struct net_device *net_dev) -{ -} #if defined(CONFIG_FSL_DPAA_1588) || defined(CONFIG_FSL_DPAA_TS) u64 dpa_get_timestamp_ns(const struct dpa_priv_s *priv, enum port_type rx_tx, const void *data) @@ -1173,10 +1136,6 @@ int dpa_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return ret; } -static int dpa_macless_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - return -EINVAL; -} #ifndef CONFIG_FSL_DPAA_ETH_SG_SUPPORT /* * When we put the buffer into the pool, we purposefully added @@ -2256,13 +2215,6 @@ static int __cold dpa_eth_priv_start(struct net_device *net_dev) return dpa_start(net_dev); } -static int __cold dpa_macless_start(struct net_device *net_dev) -{ - netif_tx_start_all_queues(net_dev); - - return 0; -} - int __cold dpa_stop(struct net_device *net_dev) { int _errno, i; @@ -2303,13 +2255,6 @@ static int __cold dpa_eth_priv_stop(struct net_device *net_dev) return _errno; } -static int __cold dpa_macless_stop(struct net_device *net_dev) -{ - netif_tx_stop_all_queues(net_dev); - - return 0; -} - void __cold dpa_timeout(struct net_device *net_dev) { const struct dpa_priv_s *priv; @@ -2603,24 +2548,6 @@ netdev_features_t dpa_fix_features(struct net_device *dev, return features; } -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; -} - int dpa_set_features(struct net_device *dev, netdev_features_t features) { /* Not much to do here for now */ @@ -2651,27 +2578,6 @@ static const struct net_device_ops dpa_private_ops = { #endif }; -extern int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device *net_dev); - -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_set_macless_address, - .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_set_rx_mode = dpa_set_macless_rx_mode, - .ndo_init = dpa_ndo_init, - .ndo_set_features = dpa_set_features, - .ndo_fix_features = dpa_macless_fix_features, - .ndo_do_ioctl = dpa_macless_ioctl, -}; - static u32 rx_pool_channel; static DEFINE_SPINLOCK(rx_pool_channel_init); @@ -2690,11 +2596,6 @@ int dpa_get_channel(struct device *dev, struct device_node *dpa_node) return rx_pool_channel; } -struct fqid_cell { - uint32_t start; - uint32_t count; -}; - static const struct fqid_cell default_fqids[][3] = { [RX] = { {0, 1}, {0, 1}, {0, DPAA_ETH_RX_QUEUES} }, [TX] = { {0, 1}, {0, 1}, {0, DPAA_ETH_TX_QUEUES} } @@ -2710,7 +2611,7 @@ static const struct fqid_cell tx_recycle_fqids[] = { }; #endif -static struct dpa_fq *dpa_fq_alloc(struct device *dev, +struct dpa_fq *dpa_fq_alloc(struct device *dev, const struct fqid_cell *fqids, struct list_head *list, enum dpa_fq_type fq_type) @@ -2824,35 +2725,6 @@ invalid_error_queue: return -EINVAL; } -/* 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, fsl_qman_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, &fqids[i], list, ptype == RX ? - FQ_TYPE_RX_PCD : FQ_TYPE_TX)) { - dev_err(dev, "_dpa_fq_alloc() failed\n"); - return -ENOMEM; - } - } - - return 0; -} - static inline void dpa_setup_ingress(const struct dpa_priv_s *priv, struct dpa_fq *fq, const struct qman_fq *template) @@ -3090,26 +2962,6 @@ int dpa_netdev_init(struct device_node *dpa_node, return 0; } -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 device *dev = net_dev->dev.parent; - const uint8_t *mac_addr; - - net_dev->netdev_ops = &dpa_macless_ops; - - /* Get the MAC address */ - 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(dpa_node, net_dev, mac_addr); -} - static int dpa_private_netdev_init(struct device_node *dpa_node, struct net_device *net_dev) { @@ -3344,7 +3196,7 @@ dpaa_eth_priv_probe(struct platform_device *_of_dev) /* Add the FQs to the interface, and make them active */ list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) { - err = dpa_fq_init(dpa_fq); + err = dpa_fq_init(dpa_fq, false); if (err < 0) goto fq_alloc_failed; } @@ -3409,149 +3261,6 @@ mac_probe_failed: return err; } -extern const dpa_fq_cbs_t shared_fq_cbs; - -static const struct of_device_id dpa_macless_match[]; -static int -dpaa_eth_macless_probe(struct platform_device *_of_dev) -{ - int err = 0, i; - struct device *dev; - struct device_node *dpa_node; - struct dpa_bp *dpa_bp; - struct dpa_fq *dpa_fq, *tmp; - size_t count; - struct net_device *net_dev = NULL; - struct dpa_priv_s *priv = NULL; - struct dpa_percpu_priv_s *percpu_priv; - struct fm_port_fqs port_fqs; - 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); - - /* 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; - - priv->msg_enable = netif_msg_init(debug, -1); - - INIT_LIST_HEAD(&priv->dpa_fq_list); - - memset(&port_fqs, 0, sizeof(port_fqs)); - - 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 */ - - err = dpa_bp_create(net_dev, dpa_bp, count); - - if (err < 0) - goto bp_create_failed; - - priv->mac_dev = NULL; - - priv->channel = dpa_get_channel(dev, dpa_node); - - if (priv->channel < 0) { - err = priv->channel; - goto get_channel_failed; - } - - /* 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 */ - list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) { - err = dpa_fq_init(dpa_fq); - if (err < 0) - goto fq_alloc_failed; - } - - priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM; - - priv->percpu_priv = alloc_percpu(*priv->percpu_priv); - - if (priv->percpu_priv == NULL) { - dev_err(dev, "alloc_percpu() failed\n"); - err = -ENOMEM; - goto alloc_percpu_failed; - } - for_each_online_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; - - priv->macless_idx = macless_idx++; - - dpaa_eth_sysfs_init(&net_dev->dev); - - return 0; - -netdev_init_failed: - if (net_dev) - free_percpu(priv->percpu_priv); -alloc_percpu_failed: -fq_alloc_failed: - if (net_dev) { - dpa_fq_free(dev, &priv->dpa_fq_list); - qman_release_cgrid(priv->cgr_data.cgr.cgrid); - qman_delete_cgr(&priv->cgr_data.cgr); - } -add_channel_failed: -get_channel_failed: - if (net_dev) - dpa_bp_free(priv, priv->dpa_bp); -bp_create_failed: -fq_probe_failed: - dev_set_drvdata(dev, NULL); - if (net_dev) - free_netdev(net_dev); - - return err; -} - static const struct of_device_id dpa_match[] = { { .compatible = "fsl,dpa-ethernet" @@ -3560,14 +3269,6 @@ static const struct of_device_id dpa_match[] = { }; MODULE_DEVICE_TABLE(of, dpa_match); -static const struct of_device_id dpa_macless_match[] = { - { - .compatible = "fsl,dpa-ethernet-macless" - }, - {} -}; -MODULE_DEVICE_TABLE(of, dpa_macless_match); - int __cold dpa_remove(struct platform_device *of_dev) { int err; @@ -3618,16 +3319,6 @@ static struct platform_driver dpa_driver = { .remove = dpa_remove }; -static struct platform_driver dpa_macless_driver = { - .driver = { - .name = KBUILD_MODNAME, - .of_match_table = dpa_macless_match, - .owner = THIS_MODULE, - }, - .probe = dpaa_eth_macless_probe, - .remove = dpa_remove -}; - static int __init __cold dpa_load(void) { int _errno; @@ -3648,16 +3339,6 @@ static int __init __cold dpa_load(void) pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", KBUILD_BASENAME".c", __func__); - _errno = platform_driver_register(&dpa_macless_driver); - if (unlikely(_errno < 0)) { - pr_err(KBUILD_MODNAME"-macless" - ": %s:%hu:%s(): platform_driver_register() = %d\n", - KBUILD_BASENAME".c", __LINE__, __func__, _errno); - } - - pr_debug(KBUILD_MODNAME"-macless" ": %s:%s() ->\n", - KBUILD_BASENAME".c", __func__); - return _errno; } module_init(dpa_load); @@ -3671,10 +3352,5 @@ static void __exit __cold dpa_unload(void) pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", KBUILD_BASENAME".c", __func__); - - platform_driver_unregister(&dpa_macless_driver); - - pr_debug(KBUILD_MODNAME"-macless" ": %s:%s() ->\n", - KBUILD_BASENAME".c", __func__); } module_exit(dpa_unload); diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h index 953a33e..a5f5a00 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h @@ -252,6 +252,11 @@ typedef struct dpa_fq_cbs_t { struct qman_fq egress_ern; } dpa_fq_cbs_t; +struct fqid_cell { + uint32_t start; + uint32_t count; +}; + struct dpa_bp { struct bman_pool *pool; uint8_t bpid; diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c new file mode 100644 index 0000000..502707c --- /dev/null +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c @@ -0,0 +1,449 @@ +/* + * 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. + */ + +#define pr_fmt(fmt) \ + KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ + KBUILD_BASENAME".c", __LINE__, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dpaa_eth.h" +#include "lnxwrp_fsl_fman.h" /* fm_get_rx_extra_headroom(), fm_get_max_frm() */ + +/* 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" + +static uint8_t debug = -1; +module_param(debug, byte, S_IRUGO); +MODULE_PARM_DESC(debug, "Module/Driver verbosity level"); + +/* candidates for dpa_eth_common.c */ +int dpa_netdev_init(struct device_node *dpa_node, + struct net_device *net_dev, const uint8_t *mac_addr); +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 __cold dpa_remove(struct platform_device *of_dev); +struct dpa_bp * __cold __must_check __attribute__((nonnull)) +dpa_bp_probe(struct platform_device *_of_dev, size_t *count); +struct mac_device * __cold __must_check +__attribute__((nonnull)) dpa_mac_probe(struct platform_device *_of_dev); +void dpa_set_buffers_layout(struct mac_device *mac_dev, + struct dpa_buffer_layout_s *layout); +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); +#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE +u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb); +#endif +int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp, + size_t count); +int dpa_get_channel(struct device *dev, struct device_node *dpa_node); +void dpa_fq_setup(struct dpa_priv_s *priv, const dpa_fq_cbs_t *fq_cbs, + struct fm_port *tx_port); +int dpa_fq_init(struct dpa_fq *dpa_fq, bool td_enable); +void dpaa_eth_sysfs_init(struct device *dev); +int __cold __attribute__((nonnull)) +dpa_fq_free(struct device *dev, struct list_head *list); +void __cold __attribute__((nonnull)) +dpa_bp_free(struct dpa_priv_s *priv, struct dpa_bp *dpa_bp); +int dpaa_eth_add_channel(void *__arg); + +/* reused from the priv driver */ +struct dpa_fq *dpa_fq_alloc(struct device *dev, + const struct fqid_cell *fqids, + struct list_head *list, + enum dpa_fq_type fq_type); + +/* reused from the shared driver */ +extern const dpa_fq_cbs_t shared_fq_cbs; +int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device *net_dev); + +/* 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 dpa_set_macless_address(struct net_device *net_dev, void *addr); +static int dpaa_eth_macless_probe(struct platform_device *_of_dev); +static void dpa_set_macless_rx_mode(struct net_device *net_dev); +static netdev_features_t +dpa_macless_fix_features(struct net_device *dev, netdev_features_t features); +static int dpa_macless_ioctl(struct net_device *dev, + struct ifreq *rq, int cmd); +static int dpa_macless_netdev_init(struct device_node *dpa_node, + struct net_device *net_dev); + +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_set_macless_address, + .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_set_rx_mode = dpa_set_macless_rx_mode, + .ndo_init = dpa_ndo_init, + .ndo_set_features = dpa_set_features, + .ndo_fix_features = dpa_macless_fix_features, + .ndo_do_ioctl = dpa_macless_ioctl, +}; + +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, + .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) +{ + netif_tx_start_all_queues(net_dev); + + return 0; +} + +static int __cold dpa_macless_stop(struct net_device *net_dev) +{ + netif_tx_stop_all_queues(net_dev); + + return 0; +} + +static void dpa_set_macless_rx_mode(struct net_device *net_dev) +{ +} + +static int dpa_set_macless_address(struct net_device *net_dev, void *addr) +{ + const struct dpa_priv_s *priv; + int _errno; + + priv = netdev_priv(net_dev); + + _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; + } + + return 0; +} + +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_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + return -EINVAL; +} + +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 device *dev = net_dev->dev.parent; + const uint8_t *mac_addr; + + net_dev->netdev_ops = &dpa_macless_ops; + + /* Get the MAC address */ + 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(dpa_node, net_dev, mac_addr); +} + +/* 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, &fqids[i], list, ptype == RX ? + FQ_TYPE_RX_PCD : FQ_TYPE_TX)) { + dev_err(dev, "_dpa_fq_alloc() failed\n"); + return -ENOMEM; + } + } + + return 0; +} + +static int dpaa_eth_macless_probe(struct platform_device *_of_dev) +{ + int err = 0, i; + struct device *dev; + struct device_node *dpa_node; + struct dpa_bp *dpa_bp; + struct dpa_fq *dpa_fq, *tmp; + size_t count; + struct net_device *net_dev = NULL; + struct dpa_priv_s *priv = NULL; + struct dpa_percpu_priv_s *percpu_priv; + struct fm_port_fqs port_fqs; + 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); + + /* 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; + + priv->msg_enable = netif_msg_init(debug, -1); + + INIT_LIST_HEAD(&priv->dpa_fq_list); + + memset(&port_fqs, 0, sizeof(port_fqs)); + + 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 */ + + err = dpa_bp_create(net_dev, dpa_bp, count); + + if (err < 0) + goto bp_create_failed; + + priv->mac_dev = NULL; + + priv->channel = dpa_get_channel(dev, dpa_node); + + if (priv->channel < 0) { + err = priv->channel; + goto get_channel_failed; + } + + /* 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 */ + list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) { + /* 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_fq_init(dpa_fq, true); + if (err < 0) + goto fq_alloc_failed; + } + + priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM; + + priv->percpu_priv = alloc_percpu(*priv->percpu_priv); + + if (priv->percpu_priv == NULL) { + dev_err(dev, "alloc_percpu() failed\n"); + err = -ENOMEM; + goto alloc_percpu_failed; + } + for_each_online_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; + + priv->macless_idx = macless_idx++; + + dpaa_eth_sysfs_init(&net_dev->dev); + + return 0; + +netdev_init_failed: + if (net_dev) + free_percpu(priv->percpu_priv); +alloc_percpu_failed: +fq_alloc_failed: + if (net_dev) { + dpa_fq_free(dev, &priv->dpa_fq_list); + qman_release_cgrid(priv->cgr_data.cgr.cgrid); + qman_delete_cgr(&priv->cgr_data.cgr); + } +add_channel_failed: +get_channel_failed: + if (net_dev) + dpa_bp_free(priv, priv->dpa_bp); +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(KBUILD_MODNAME ": " DPA_DESCRIPTION " (" VERSION ")\n"); + +/* Todo: is it safe to remove these? + / * 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); diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_shared.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_shared.c index 8b20595..c05730e 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth_shared.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_shared.c @@ -87,7 +87,7 @@ int dpa_get_channel(struct device *dev, struct device_node *dpa_node); void dpa_fq_setup(struct dpa_priv_s *priv, const dpa_fq_cbs_t *fq_cbs, struct fm_port *tx_port); int dpaa_eth_cgr_init(struct dpa_priv_s *priv); -int dpa_fq_init(struct dpa_fq *dpa_fq); +int dpa_fq_init(struct dpa_fq *dpa_fq, bool td_enable); void dpaa_eth_init_ports(struct mac_device *mac_dev, struct dpa_bp *bp, size_t count, struct fm_port_fqs *port_fqs, @@ -717,7 +717,7 @@ dpaa_eth_shared_probe(struct platform_device *_of_dev) /* Add the FQs to the interface, and make them active */ list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) { - err = dpa_fq_init(dpa_fq); + err = dpa_fq_init(dpa_fq, false); if (err < 0) goto fq_alloc_failed; } -- cgit v0.10.2