]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
Merge tag 'libnvdimm-for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdim...
[karo-tx-linux.git] / drivers / staging / fsl-dpaa2 / ethernet / dpaa2-eth.c
index a9e245df2488dd0572ac90d2de43d655f35e4785..b9a0a315e6fb31fc0804d146f1c9797220aa7669 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/iommu.h>
 
 #include "../../fsl-mc/include/mc.h"
-#include "../../fsl-mc/include/mc-sys.h"
 #include "dpaa2-eth.h"
 
 /* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files
@@ -227,6 +226,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
        struct dpaa2_eth_drv_stats *percpu_extras;
        struct device *dev = priv->net_dev->dev.parent;
        struct dpaa2_fas *fas;
+       void *buf_data;
        u32 status = 0;
 
        /* Tracing point */
@@ -235,8 +235,10 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
        vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
        dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, DMA_FROM_DEVICE);
 
-       prefetch(vaddr + priv->buf_layout.private_data_size);
-       prefetch(vaddr + dpaa2_fd_get_offset(fd));
+       fas = dpaa2_get_fas(vaddr);
+       prefetch(fas);
+       buf_data = vaddr + dpaa2_fd_get_offset(fd);
+       prefetch(buf_data);
 
        percpu_stats = this_cpu_ptr(priv->percpu_stats);
        percpu_extras = this_cpu_ptr(priv->percpu_extras);
@@ -244,9 +246,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
        if (fd_format == dpaa2_fd_single) {
                skb = build_linear_skb(priv, ch, fd, vaddr);
        } else if (fd_format == dpaa2_fd_sg) {
-               struct dpaa2_sg_entry *sgt =
-                               vaddr + dpaa2_fd_get_offset(fd);
-               skb = build_frag_skb(priv, ch, sgt);
+               skb = build_frag_skb(priv, ch, buf_data);
                skb_free_frag(vaddr);
                percpu_extras->rx_sg_frames++;
                percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd);
@@ -262,8 +262,6 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
 
        /* Check if we need to validate the L4 csum */
        if (likely(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV)) {
-               fas = (struct dpaa2_fas *)
-                               (vaddr + priv->buf_layout.private_data_size);
                status = le32_to_cpu(fas->status);
                validate_rx_csum(priv, status, skb);
        }
@@ -273,10 +271,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
        percpu_stats->rx_packets++;
        percpu_stats->rx_bytes += dpaa2_fd_get_len(fd);
 
-       if (priv->net_dev->features & NETIF_F_GRO)
-               napi_gro_receive(napi, skb);
-       else
-               netif_receive_skb(skb);
+       napi_gro_receive(napi, skb);
 
        return;
 
@@ -330,7 +325,6 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
 {
        struct device *dev = priv->net_dev->dev.parent;
        void *sgt_buf = NULL;
-       void *hwa;
        dma_addr_t addr;
        int nr_frags = skb_shinfo(skb)->nr_frags;
        struct dpaa2_sg_entry *sgt;
@@ -340,6 +334,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
        int num_sg;
        int num_dma_bufs;
        struct dpaa2_eth_swa *swa;
+       struct dpaa2_fas *fas;
 
        /* Create and map scatterlist.
         * We don't advertise NETIF_F_FRAGLIST, so skb_to_sgvec() will not have
@@ -376,8 +371,8 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
         * on TX confirmation. We are clearing FAS (Frame Annotation Status)
         * field from the hardware annotation area
         */
-       hwa = sgt_buf + priv->buf_layout.private_data_size;
-       memset(hwa + DPAA2_FAS_OFFSET, 0, DPAA2_FAS_SIZE);
+       fas = dpaa2_get_fas(sgt_buf);
+       memset(fas, 0, DPAA2_FAS_SIZE);
 
        sgt = (struct dpaa2_sg_entry *)(sgt_buf + priv->tx_data_offset);
 
@@ -436,7 +431,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
 {
        struct device *dev = priv->net_dev->dev.parent;
        u8 *buffer_start;
-       void *hwa;
+       struct dpaa2_fas *fas;
        struct sk_buff **skbh;
        dma_addr_t addr;
 
@@ -449,8 +444,8 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
         * on TX confirmation. We are clearing FAS (Frame Annotation Status)
         * field from the hardware annotation area
         */
-       hwa = buffer_start + priv->buf_layout.private_data_size;
-       memset(hwa + DPAA2_FAS_OFFSET, 0, DPAA2_FAS_SIZE);
+       fas = dpaa2_get_fas(buffer_start);
+       memset(fas, 0, DPAA2_FAS_SIZE);
 
        /* Store a backpointer to the skb at the beginning of the buffer
         * (in the private data area) such that we can release it
@@ -501,6 +496,7 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
 
        fd_addr = dpaa2_fd_get_addr(fd);
        skbh = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
+       fas = dpaa2_get_fas(skbh);
 
        if (fd_format == dpaa2_fd_single) {
                skb = *skbh;
@@ -537,11 +533,8 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
         * buffer but before we free it. The caller function is responsible
         * for checking the status value.
         */
-       if (status && (dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV)) {
-               fas = (struct dpaa2_fas *)
-                       ((void *)skbh + priv->buf_layout.private_data_size);
+       if (status)
                *status = le32_to_cpu(fas->status);
-       }
 
        /* Free SGT buffer kmalloc'ed on tx */
        if (fd_format != dpaa2_fd_single)
@@ -644,6 +637,8 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
        struct rtnl_link_stats64 *percpu_stats;
        struct dpaa2_eth_drv_stats *percpu_extras;
        u32 status = 0;
+       u32 fd_errors;
+       bool has_fas_errors = false;
 
        /* Tracing point */
        trace_dpaa2_tx_conf_fd(priv->net_dev, fd);
@@ -652,13 +647,31 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
        percpu_extras->tx_conf_frames++;
        percpu_extras->tx_conf_bytes += dpaa2_fd_get_len(fd);
 
-       free_tx_fd(priv, fd, &status);
-
-       if (unlikely(status & DPAA2_ETH_TXCONF_ERR_MASK)) {
-               percpu_stats = this_cpu_ptr(priv->percpu_stats);
-               /* Tx-conf logically pertains to the egress path. */
-               percpu_stats->tx_errors++;
+       /* Check frame errors in the FD field */
+       fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK;
+       if (unlikely(fd_errors)) {
+               /* We only check error bits in the FAS field if corresponding
+                * FAERR bit is set in FD and the FAS field is marked as valid
+                */
+               has_fas_errors = (fd_errors & DPAA2_FD_CTRL_FAERR) &&
+                                !!(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV);
+               if (net_ratelimit())
+                       netdev_dbg(priv->net_dev, "TX frame FD error: %x08\n",
+                                  fd_errors);
        }
+
+       free_tx_fd(priv, fd, has_fas_errors ? &status : NULL);
+
+       if (likely(!fd_errors))
+               return;
+
+       percpu_stats = this_cpu_ptr(priv->percpu_stats);
+       /* Tx-conf logically pertains to the egress path. */
+       percpu_stats->tx_errors++;
+
+       if (has_fas_errors && net_ratelimit())
+               netdev_dbg(priv->net_dev, "TX frame FAS error: %x08\n",
+                          status & DPAA2_FAS_TX_ERR_MASK);
 }
 
 static int set_rx_csum(struct dpaa2_eth_priv *priv, bool enable)
@@ -804,7 +817,7 @@ static void drain_bufs(struct dpaa2_eth_priv *priv, int count)
        int ret, i;
 
        do {
-               ret = dpaa2_io_service_acquire(NULL, priv->dpbp_attrs.bpid,
+               ret = dpaa2_io_service_acquire(NULL, priv->bpid,
                                               buf_array, count);
                if (ret < 0) {
                        netdev_err(priv->net_dev, "dpaa2_io_service_acquire() failed\n");
@@ -901,7 +914,7 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
                        break;
 
                /* Refill pool if appropriate */
-               refill_pool(priv, ch, priv->dpbp_attrs.bpid);
+               refill_pool(priv, ch, priv->bpid);
 
                store_cleaned = consume_frames(ch);
                cleaned += store_cleaned;
@@ -975,7 +988,7 @@ static int link_state_update(struct dpaa2_eth_priv *priv)
                netif_carrier_off(priv->net_dev);
        }
 
-       netdev_info(priv->net_dev, "Link Event: state %s",
+       netdev_info(priv->net_dev, "Link Event: state %s\n",
                    state.up ? "up" : "down");
 
        return 0;
@@ -986,14 +999,14 @@ static int dpaa2_eth_open(struct net_device *net_dev)
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
        int err;
 
-       err = seed_pool(priv, priv->dpbp_attrs.bpid);
+       err = seed_pool(priv, priv->bpid);
        if (err) {
                /* Not much to do; the buffer pool, though not filled up,
                 * may still contain some buffers which would enable us
                 * to limp on.
                 */
                netdev_err(net_dev, "Buffer seeding failed for DPBP %d (bpid=%d)\n",
-                          priv->dpbp_dev->obj_desc.id, priv->dpbp_attrs.bpid);
+                          priv->dpbp_dev->obj_desc.id, priv->bpid);
        }
 
        /* We'll only start the txqs when the link is actually ready; make sure
@@ -1513,6 +1526,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
                if (!channel) {
                        dev_info(dev,
                                 "No affine channel for cpu %d and above\n", i);
+                       err = -ENODEV;
                        goto err_alloc_ch;
                }
 
@@ -1527,10 +1541,13 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
                /* Register the new context */
                err = dpaa2_io_service_register(NULL, nctx);
                if (err) {
-                       dev_info(dev, "No affine DPIO for cpu %d\n", i);
+                       dev_dbg(dev, "No affine DPIO for cpu %d\n", i);
                        /* If no affine DPIO for this core, there's probably
-                        * none available for next cores either.
+                        * none available for next cores either. Signal we want
+                        * to retry later, in case the DPIO devices weren't
+                        * probed yet.
                         */
+                       err = -EPROBE_DEFER;
                        goto err_service_reg;
                }
 
@@ -1568,7 +1585,7 @@ err_service_reg:
 err_alloc_ch:
        if (cpumask_empty(&priv->dpio_cpumask)) {
                dev_err(dev, "No cpu with an affine DPIO/DPCON\n");
-               return -ENODEV;
+               return err;
        }
 
        dev_info(dev, "Cores %*pbl available for processing ingress traffic\n",
@@ -1673,6 +1690,7 @@ static int setup_dpbp(struct dpaa2_eth_priv *priv)
        int err;
        struct fsl_mc_device *dpbp_dev;
        struct device *dev = priv->net_dev->dev.parent;
+       struct dpbp_attr dpbp_attrs;
 
        err = fsl_mc_object_allocate(to_fsl_mc_device(dev), FSL_MC_POOL_DPBP,
                                     &dpbp_dev);
@@ -1690,6 +1708,12 @@ static int setup_dpbp(struct dpaa2_eth_priv *priv)
                goto err_open;
        }
 
+       err = dpbp_reset(priv->mc_io, 0, dpbp_dev->mc_handle);
+       if (err) {
+               dev_err(dev, "dpbp_reset() failed\n");
+               goto err_reset;
+       }
+
        err = dpbp_enable(priv->mc_io, 0, dpbp_dev->mc_handle);
        if (err) {
                dev_err(dev, "dpbp_enable() failed\n");
@@ -1697,17 +1721,19 @@ static int setup_dpbp(struct dpaa2_eth_priv *priv)
        }
 
        err = dpbp_get_attributes(priv->mc_io, 0, dpbp_dev->mc_handle,
-                                 &priv->dpbp_attrs);
+                                 &dpbp_attrs);
        if (err) {
                dev_err(dev, "dpbp_get_attributes() failed\n");
                goto err_get_attr;
        }
+       priv->bpid = dpbp_attrs.bpid;
 
        return 0;
 
 err_get_attr:
        dpbp_disable(priv->mc_io, 0, dpbp_dev->mc_handle);
 err_enable:
+err_reset:
        dpbp_close(priv->mc_io, 0, dpbp_dev->mc_handle);
 err_open:
        fsl_mc_object_free(dpbp_dev);
@@ -1729,15 +1755,14 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
        struct device *dev = &ls_dev->dev;
        struct dpaa2_eth_priv *priv;
        struct net_device *net_dev;
+       struct dpni_buffer_layout buf_layout = {0};
        int err;
 
        net_dev = dev_get_drvdata(dev);
        priv = netdev_priv(net_dev);
 
-       priv->dpni_id = ls_dev->obj_desc.id;
-
        /* get a handle for the DPNI object */
-       err = dpni_open(priv->mc_io, 0, priv->dpni_id, &priv->mc_token);
+       err = dpni_open(priv->mc_io, 0, ls_dev->obj_desc.id, &priv->mc_token);
        if (err) {
                dev_err(dev, "dpni_open() failed\n");
                goto err_open;
@@ -1761,35 +1786,35 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
 
        /* Configure buffer layouts */
        /* rx buffer */
-       priv->buf_layout.pass_parser_result = true;
-       priv->buf_layout.pass_frame_status = true;
-       priv->buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
-       priv->buf_layout.data_align = DPAA2_ETH_RX_BUF_ALIGN;
-       priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
-                                  DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
-                                  DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
-                                  DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
+       buf_layout.pass_parser_result = true;
+       buf_layout.pass_frame_status = true;
+       buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
+       buf_layout.data_align = DPAA2_ETH_RX_BUF_ALIGN;
+       buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
+                            DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
+                            DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
+                            DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
        err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
-                                    DPNI_QUEUE_RX, &priv->buf_layout);
+                                    DPNI_QUEUE_RX, &buf_layout);
        if (err) {
                dev_err(dev, "dpni_set_buffer_layout(RX) failed\n");
                goto err_buf_layout;
        }
 
        /* tx buffer */
-       priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
-                                  DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
+       buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
+                            DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
        err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
-                                    DPNI_QUEUE_TX, &priv->buf_layout);
+                                    DPNI_QUEUE_TX, &buf_layout);
        if (err) {
                dev_err(dev, "dpni_set_buffer_layout(TX) failed\n");
                goto err_buf_layout;
        }
 
        /* tx-confirm buffer */
-       priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS;
+       buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS;
        err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
-                                    DPNI_QUEUE_TX_CONFIRM, &priv->buf_layout);
+                                    DPNI_QUEUE_TX_CONFIRM, &buf_layout);
        if (err) {
                dev_err(dev, "dpni_set_buffer_layout(TX_CONF) failed\n");
                goto err_buf_layout;
@@ -1806,7 +1831,7 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
        }
 
        if ((priv->tx_data_offset % 64) != 0)
-               dev_warn(dev, "Tx data offset (%d) not a multiple of 64B",
+               dev_warn(dev, "Tx data offset (%d) not a multiple of 64B\n",
                         priv->tx_data_offset);
 
        /* Accommodate software annotation space (SWA) */
@@ -1969,8 +1994,8 @@ static int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
        int err = 0;
 
        if (!dpaa2_eth_hash_enabled(priv)) {
-               dev_err(dev, "Hashing support is not enabled\n");
-               return -EOPNOTSUPP;
+               dev_dbg(dev, "Hashing support is not enabled\n");
+               return 0;
        }
 
        memset(&cls_cfg, 0, sizeof(cls_cfg));
@@ -1996,23 +2021,23 @@ static int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
                priv->rx_hash_fields |= hash_fields[i].rxnfc_field;
        }
 
-       dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_DMA | GFP_KERNEL);
+       dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_KERNEL);
        if (!dma_mem)
                return -ENOMEM;
 
        err = dpni_prepare_key_cfg(&cls_cfg, dma_mem);
        if (err) {
-               dev_err(dev, "dpni_prepare_key_cfg error %d", err);
+               dev_err(dev, "dpni_prepare_key_cfg error %d\n", err);
                goto err_prep_key;
        }
 
        memset(&dist_cfg, 0, sizeof(dist_cfg));
 
        /* Prepare for setting the rx dist */
-       dist_cfg.key_cfg_iova = dma_map_single(net_dev->dev.parent, dma_mem,
+       dist_cfg.key_cfg_iova = dma_map_single(dev, dma_mem,
                                               DPAA2_CLASSIFIER_DMA_SIZE,
                                               DMA_TO_DEVICE);
-       if (dma_mapping_error(net_dev->dev.parent, dist_cfg.key_cfg_iova)) {
+       if (dma_mapping_error(dev, dist_cfg.key_cfg_iova)) {
                dev_err(dev, "DMA mapping failed\n");
                err = -ENOMEM;
                goto err_dma_map;
@@ -2022,7 +2047,7 @@ static int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
        dist_cfg.dist_mode = DPNI_DIST_MODE_HASH;
 
        err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, 0, &dist_cfg);
-       dma_unmap_single(net_dev->dev.parent, dist_cfg.key_cfg_iova,
+       dma_unmap_single(dev, dist_cfg.key_cfg_iova,
                         DPAA2_CLASSIFIER_DMA_SIZE, DMA_TO_DEVICE);
        if (err)
                dev_err(dev, "dpni_set_rx_tc_dist() error %d\n", err);
@@ -2063,7 +2088,7 @@ static int bind_dpni(struct dpaa2_eth_priv *priv)
                netdev_err(net_dev, "Failed to configure hashing\n");
 
        /* Configure handling of error frames */
-       err_cfg.errors = DPAA2_ETH_RX_ERR_MASK;
+       err_cfg.errors = DPAA2_FAS_RX_ERR_MASK;
        err_cfg.set_frame_annotation = 1;
        err_cfg.error_action = DPNI_ERROR_ACTION_DISCARD;
        err = dpni_set_errors_behavior(priv->mc_io, 0, priv->mc_token,
@@ -2136,15 +2161,12 @@ static void free_rings(struct dpaa2_eth_priv *priv)
                dpaa2_io_store_destroy(priv->channel[i]->store);
 }
 
-static int netdev_init(struct net_device *net_dev)
+static int set_mac_addr(struct dpaa2_eth_priv *priv)
 {
-       int err;
+       struct net_device *net_dev = priv->net_dev;
        struct device *dev = net_dev->dev.parent;
-       struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
        u8 mac_addr[ETH_ALEN], dpni_mac_addr[ETH_ALEN];
-       u8 bcast_addr[ETH_ALEN];
-
-       net_dev->netdev_ops = &dpaa2_eth_ops;
+       int err;
 
        /* Get firmware address, if any */
        err = dpni_get_port_mac_addr(priv->mc_io, 0, priv->mc_token, mac_addr);
@@ -2157,7 +2179,7 @@ static int netdev_init(struct net_device *net_dev)
        err = dpni_get_primary_mac_addr(priv->mc_io, 0, priv->mc_token,
                                        dpni_mac_addr);
        if (err) {
-               dev_err(dev, "dpni_get_primary_mac_addr() failed (%d)\n", err);
+               dev_err(dev, "dpni_get_primary_mac_addr() failed\n");
                return err;
        }
 
@@ -2175,18 +2197,19 @@ static int netdev_init(struct net_device *net_dev)
                }
                memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len);
        } else if (is_zero_ether_addr(dpni_mac_addr)) {
-               /* Fills in net_dev->dev_addr, as required by
-                * register_netdevice()
+               /* No MAC address configured, fill in net_dev->dev_addr
+                * with a random one
                 */
                eth_hw_addr_random(net_dev);
-               /* Make the user aware, without cluttering the boot log */
-               dev_dbg_once(dev, " device(s) have all-zero hwaddr, replaced with random\n");
+               dev_dbg_once(dev, "device(s) have all-zero hwaddr, replaced with random\n");
+
                err = dpni_set_primary_mac_addr(priv->mc_io, 0, priv->mc_token,
                                                net_dev->dev_addr);
                if (err) {
-                       dev_err(dev, "dpni_set_primary_mac_addr(): %d\n", err);
+                       dev_err(dev, "dpni_set_primary_mac_addr() failed\n");
                        return err;
                }
+
                /* Override NET_ADDR_RANDOM set by eth_hw_addr_random(); for all
                 * practical purposes, this will be our "permanent" mac address,
                 * at least until the next reboot. This move will also permit
@@ -2200,14 +2223,29 @@ static int netdev_init(struct net_device *net_dev)
                memcpy(net_dev->dev_addr, dpni_mac_addr, net_dev->addr_len);
        }
 
-       /* Explicitly add the broadcast address to the MAC filtering table;
-        * the MC won't do that for us.
-        */
+       return 0;
+}
+
+static int netdev_init(struct net_device *net_dev)
+{
+       struct device *dev = net_dev->dev.parent;
+       struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+       u8 bcast_addr[ETH_ALEN];
+       u8 num_queues;
+       int err;
+
+       net_dev->netdev_ops = &dpaa2_eth_ops;
+
+       err = set_mac_addr(priv);
+       if (err)
+               return err;
+
+       /* Explicitly add the broadcast address to the MAC filtering table */
        eth_broadcast_addr(bcast_addr);
        err = dpni_add_mac_addr(priv->mc_io, 0, priv->mc_token, bcast_addr);
        if (err) {
-               dev_warn(dev, "dpni_add_mac_addr() failed (%d)\n", err);
-               /* Won't return an error; at least, we'd have egress traffic */
+               dev_err(dev, "dpni_add_mac_addr() failed\n");
+               return err;
        }
 
        /* Reserve enough space to align buffer as per hardware requirement;
@@ -2219,6 +2257,19 @@ static int netdev_init(struct net_device *net_dev)
        net_dev->min_mtu = 68;
        net_dev->max_mtu = DPAA2_ETH_MAX_MTU;
 
+       /* Set actual number of queues in the net device */
+       num_queues = dpaa2_eth_queue_count(priv);
+       err = netif_set_real_num_tx_queues(net_dev, num_queues);
+       if (err) {
+               dev_err(dev, "netif_set_real_num_tx_queues() failed\n");
+               return err;
+       }
+       err = netif_set_real_num_rx_queues(net_dev, num_queues);
+       if (err) {
+               dev_err(dev, "netif_set_real_num_rx_queues() failed\n");
+               return err;
+       }
+
        /* Our .ndo_init will be called herein */
        err = register_netdev(net_dev);
        if (err < 0) {
@@ -2261,7 +2312,7 @@ static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg)
        err = dpni_get_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle,
                                  DPNI_IRQ_INDEX, &status);
        if (unlikely(err)) {
-               netdev_err(net_dev, "Can't get irq status (err %d)", err);
+               netdev_err(net_dev, "Can't get irq status (err %d)\n", err);
                clear = 0xffffffff;
                goto out;
        }
@@ -2295,21 +2346,21 @@ static int setup_irqs(struct fsl_mc_device *ls_dev)
                                        IRQF_NO_SUSPEND | IRQF_ONESHOT,
                                        dev_name(&ls_dev->dev), &ls_dev->dev);
        if (err < 0) {
-               dev_err(&ls_dev->dev, "devm_request_threaded_irq(): %d", err);
+               dev_err(&ls_dev->dev, "devm_request_threaded_irq(): %d\n", err);
                goto free_mc_irq;
        }
 
        err = dpni_set_irq_mask(ls_dev->mc_io, 0, ls_dev->mc_handle,
                                DPNI_IRQ_INDEX, DPNI_IRQ_EVENT_LINK_CHANGED);
        if (err < 0) {
-               dev_err(&ls_dev->dev, "dpni_set_irq_mask(): %d", err);
+               dev_err(&ls_dev->dev, "dpni_set_irq_mask(): %d\n", err);
                goto free_irq;
        }
 
        err = dpni_set_irq_enable(ls_dev->mc_io, 0, ls_dev->mc_handle,
                                  DPNI_IRQ_INDEX, 1);
        if (err < 0) {
-               dev_err(&ls_dev->dev, "dpni_set_irq_enable(): %d", err);
+               dev_err(&ls_dev->dev, "dpni_set_irq_enable(): %d\n", err);
                goto free_irq;
        }