]> 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 ee71e158b0a9347d888d8f323f13d284863cd879..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
@@ -534,7 +533,7 @@ 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))
+       if (status)
                *status = le32_to_cpu(fas->status);
 
        /* Free SGT buffer kmalloc'ed on tx */
@@ -638,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);
@@ -646,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)
@@ -798,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");
@@ -895,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;
@@ -980,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
@@ -1671,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);
@@ -1701,11 +1721,12 @@ 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;
 
@@ -2067,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,
@@ -2140,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);
@@ -2161,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;
        }
 
@@ -2179,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
@@ -2204,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;
@@ -2223,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) {