staging: fsl-dpaa2/eth: Add DPNI version check
authorIoana Radulescu <ruxandra.radulescu@nxp.com>
Fri, 23 Mar 2018 13:44:09 +0000 (08:44 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Mar 2018 15:01:56 +0000 (16:01 +0100)
The DPAA2 Ethernet driver assumes the DPNI objects that it
uses to build network interfaces have a minimum supported
API version, but until now it did nothing to enforce this
requirement.

Add a check at probe time to make sure the DPNI object is
compatible with the set of MC commands we intend to use
on it.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c

index 9fb88f2736d30286cd23df3def2ff943350f9a4d..f58c85a4a62e87b5f977c102405be1f6b286e81f 100644 (file)
@@ -1846,6 +1846,21 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
                return err;
        }
 
+       /* Check if we can work with this DPNI object */
+       err = dpni_get_api_version(priv->mc_io, 0, &priv->dpni_ver_major,
+                                  &priv->dpni_ver_minor);
+       if (err) {
+               dev_err(dev, "dpni_get_api_version() failed\n");
+               goto close;
+       }
+       if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_VER_MAJOR, DPNI_VER_MINOR) < 0) {
+               dev_err(dev, "DPNI version %u.%u not supported, need >= %u.%u\n",
+                       priv->dpni_ver_major, priv->dpni_ver_minor,
+                       DPNI_VER_MAJOR, DPNI_VER_MINOR);
+               err = -ENOTSUPP;
+               goto close;
+       }
+
        ls_dev->mc_io = priv->mc_io;
        ls_dev->mc_handle = priv->mc_token;
 
index c4816e607ec3fc1fc53a2b879ff7fc71f2b5e94d..5ac014f5833ad28084b54d94bffb60636b669dcc 100644 (file)
@@ -311,6 +311,8 @@ struct dpaa2_eth_priv {
        struct dpaa2_eth_channel *channel[DPAA2_ETH_MAX_DPCONS];
 
        struct dpni_attr dpni_attrs;
+       u16 dpni_ver_major;
+       u16 dpni_ver_minor;
        u16 tx_data_offset;
 
        struct fsl_mc_device *dpbp_dev;
@@ -354,6 +356,14 @@ struct dpaa2_eth_priv {
 extern const struct ethtool_ops dpaa2_ethtool_ops;
 extern const char dpaa2_eth_drv_version[];
 
+static inline int dpaa2_eth_cmp_dpni_ver(struct dpaa2_eth_priv *priv,
+                                        u16 ver_major, u16 ver_minor)
+{
+       if (priv->dpni_ver_major == ver_major)
+               return priv->dpni_ver_minor - ver_minor;
+       return priv->dpni_ver_major - ver_major;
+}
+
 /* Hardware only sees DPAA2_ETH_RX_BUF_SIZE, but the skb built around
  * the buffer also needs space for its shared info struct, and we need
  * to allocate enough to accommodate hardware alignment restrictions
index 070a3f2a0523868668f3c6d0e8e24f8158c81a06..dfbfa946aa3f150d25c0d2449d183d6b0ccb678f 100644 (file)
@@ -78,20 +78,13 @@ static void dpaa2_eth_get_drvinfo(struct net_device *net_dev,
                                  struct ethtool_drvinfo *drvinfo)
 {
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-       u16 fw_major, fw_minor;
-       int err;
 
        strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
        strlcpy(drvinfo->version, dpaa2_eth_drv_version,
                sizeof(drvinfo->version));
 
-       err =  dpni_get_api_version(priv->mc_io, 0, &fw_major, &fw_minor);
-       if (!err)
-               snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
-                        "%u.%u", fw_major, fw_minor);
-       else
-               strlcpy(drvinfo->fw_version, "N/A",
-                       sizeof(drvinfo->fw_version));
+       snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+                "%u.%u", priv->dpni_ver_major, priv->dpni_ver_minor);
 
        strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
                sizeof(drvinfo->bus_info));