]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
dpaa2-eth: Use new API for Rx flow hashing
authorIoana Radulescu <ruxandra.radulescu@nxp.com>
Mon, 1 Oct 2018 10:44:55 +0000 (13:44 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 3 Oct 2018 05:24:08 +0000 (22:24 -0700)
The Management Complex (MC) firmware initially allowed the
configuration of a single key to be used both for Rx flow hashing
and flow classification. This prevented us from supporting
Rx flow classification through ethtool.

Starting with version 10.7.0, the Management Complex(MC) offers
a new set of APIs for separate configuration of Rx hashing and
classification keys.

Update the Rx flow hashing support to use the new API, if available.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
drivers/net/ethernet/freescale/dpaa2/dpni-cmd.h
drivers/net/ethernet/freescale/dpaa2/dpni.c
drivers/net/ethernet/freescale/dpaa2/dpni.h

index c282d5ca06d6bd1ed246dd7a6ec02f5f07a02a96..c72d209c1b5a9cfc184f1bfe39cdd5fb71b1d4f8 100644 (file)
@@ -2049,6 +2049,46 @@ static const struct dpaa2_eth_hash_fields hash_fields[] = {
        },
 };
 
+/* Configure the Rx hash key using the legacy API */
+static int config_legacy_hash_key(struct dpaa2_eth_priv *priv, dma_addr_t key)
+{
+       struct device *dev = priv->net_dev->dev.parent;
+       struct dpni_rx_tc_dist_cfg dist_cfg;
+       int err;
+
+       memset(&dist_cfg, 0, sizeof(dist_cfg));
+
+       dist_cfg.key_cfg_iova = key;
+       dist_cfg.dist_size = dpaa2_eth_queue_count(priv);
+       dist_cfg.dist_mode = DPNI_DIST_MODE_HASH;
+
+       err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, 0, &dist_cfg);
+       if (err)
+               dev_err(dev, "dpni_set_rx_tc_dist failed\n");
+
+       return err;
+}
+
+/* Configure the Rx hash key using the new API */
+static int config_hash_key(struct dpaa2_eth_priv *priv, dma_addr_t key)
+{
+       struct device *dev = priv->net_dev->dev.parent;
+       struct dpni_rx_dist_cfg dist_cfg;
+       int err;
+
+       memset(&dist_cfg, 0, sizeof(dist_cfg));
+
+       dist_cfg.key_cfg_iova = key;
+       dist_cfg.dist_size = dpaa2_eth_queue_count(priv);
+       dist_cfg.enable = 1;
+
+       err = dpni_set_rx_hash_dist(priv->mc_io, 0, priv->mc_token, &dist_cfg);
+       if (err)
+               dev_err(dev, "dpni_set_rx_hash_dist failed\n");
+
+       return err;
+}
+
 /* Set RX hash options
  * flags is a combination of RXH_ bits
  */
@@ -2057,8 +2097,8 @@ int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
        struct device *dev = net_dev->dev.parent;
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
        struct dpkg_profile_cfg cls_cfg;
-       struct dpni_rx_tc_dist_cfg dist_cfg;
        u32 rx_hash_fields = 0;
+       dma_addr_t key_iova;
        u8 *dma_mem;
        int i;
        int err = 0;
@@ -2098,34 +2138,29 @@ int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
        err = dpni_prepare_key_cfg(&cls_cfg, dma_mem);
        if (err) {
                dev_err(dev, "dpni_prepare_key_cfg error %d\n", err);
-               goto err_prep_key;
+               goto free_key;
        }
 
-       memset(&dist_cfg, 0, sizeof(dist_cfg));
-
        /* Prepare for setting the rx dist */
-       dist_cfg.key_cfg_iova = dma_map_single(dev, dma_mem,
-                                              DPAA2_CLASSIFIER_DMA_SIZE,
-                                              DMA_TO_DEVICE);
-       if (dma_mapping_error(dev, dist_cfg.key_cfg_iova)) {
+       key_iova = dma_map_single(dev, dma_mem, DPAA2_CLASSIFIER_DMA_SIZE,
+                                 DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, key_iova)) {
                dev_err(dev, "DMA mapping failed\n");
                err = -ENOMEM;
-               goto err_dma_map;
+               goto free_key;
        }
 
-       dist_cfg.dist_size = dpaa2_eth_queue_count(priv);
-       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(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);
+       if (dpaa2_eth_has_legacy_dist(priv))
+               err = config_legacy_hash_key(priv, key_iova);
        else
+               err = config_hash_key(priv, key_iova);
+
+       dma_unmap_single(dev, key_iova, DPAA2_CLASSIFIER_DMA_SIZE,
+                        DMA_TO_DEVICE);
+       if (!err)
                priv->rx_hash_fields = rx_hash_fields;
 
-err_dma_map:
-err_prep_key:
+free_key:
        kfree(dma_mem);
        return err;
 }
index 93bc41265e5e9af226bc7301cd1893a5340f4804..9c8fec248e64ccebba1af2026e1bcab35d2921da 100644 (file)
@@ -367,6 +367,16 @@ static inline int dpaa2_eth_cmp_dpni_ver(struct dpaa2_eth_priv *priv,
        return priv->dpni_ver_major - ver_major;
 }
 
+/* Minimum firmware version that supports a more flexible API
+ * for configuring the Rx flow hash key
+ */
+#define DPNI_RX_DIST_KEY_VER_MAJOR     7
+#define DPNI_RX_DIST_KEY_VER_MINOR     5
+
+#define dpaa2_eth_has_legacy_dist(priv)                                        \
+       (dpaa2_eth_cmp_dpni_ver((priv), DPNI_RX_DIST_KEY_VER_MAJOR,     \
+                               DPNI_RX_DIST_KEY_VER_MINOR) < 0)
+
 /* 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 83698abce8b443f185bb78ad2e76d371354c7b76..a5285c72d2beca3fa2d54f646659e6f372095b57 100644 (file)
@@ -82,6 +82,8 @@
 #define DPNI_CMDID_GET_OFFLOAD                         DPNI_CMD(0x26B)
 #define DPNI_CMDID_SET_OFFLOAD                         DPNI_CMD(0x26C)
 
+#define DPNI_CMDID_SET_RX_HASH_DIST                    DPNI_CMD(0x274)
+
 /* Macros for accessing command fields smaller than 1byte */
 #define DPNI_MASK(field)       \
        GENMASK(DPNI_##field##_SHIFT + DPNI_##field##_SIZE - 1, \
@@ -515,4 +517,14 @@ struct dpni_rsp_get_api_version {
        __le16 minor;
 };
 
+#define DPNI_RX_HASH_DIST_ENABLE_SHIFT 0
+#define DPNI_RX_HASH_DIST_ENABLE_SIZE  1
+struct dpni_cmd_set_rx_hash_dist {
+       __le16 dist_size;
+       u8 enable;
+       u8 tc;
+       __le32 pad;
+       __le64 key_cfg_iova;
+};
+
 #endif /* _FSL_DPNI_CMD_H */
index d6ac26797ceca2bfb86c6f41353c2c99e1d132fc..a5c71fade554cb252711a28c7a138b73b35714cb 100644 (file)
@@ -1598,3 +1598,35 @@ int dpni_get_api_version(struct fsl_mc_io *mc_io,
 
        return 0;
 }
+
+/**
+ * dpni_set_rx_hash_dist() - Set Rx hash distribution
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:     Token of DPNI object
+ * @cfg: Distribution configuration
+ * If cfg.enable is set to 1 the packets will be classified using a hash
+ * function based on the key received in cfg.key_cfg_iova parameter.
+ * If cfg.enable is set to 0 the packets will be sent to the default queue
+ */
+int dpni_set_rx_hash_dist(struct fsl_mc_io *mc_io,
+                         u32 cmd_flags,
+                         u16 token,
+                         const struct dpni_rx_dist_cfg *cfg)
+{
+       struct dpni_cmd_set_rx_hash_dist *cmd_params;
+       struct fsl_mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_HASH_DIST,
+                                         cmd_flags,
+                                         token);
+       cmd_params = (struct dpni_cmd_set_rx_hash_dist *)cmd.params;
+       cmd_params->dist_size = cpu_to_le16(cfg->dist_size);
+       dpni_set_field(cmd_params->enable, RX_HASH_DIST_ENABLE, cfg->enable);
+       cmd_params->tc = cfg->tc;
+       cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
index b378a00c7c5342349b165365c4f3d96bf879fea7..1664b77b28b11f54044be3bdd7c6c8e4f6628187 100644 (file)
@@ -628,6 +628,40 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io                   *mc_io,
                        u8                                      tc_id,
                        const struct dpni_rx_tc_dist_cfg        *cfg);
 
+/**
+ * When used for fs_miss_flow_id in function dpni_set_rx_dist,
+ * will signal to dpni to drop all unclassified frames
+ */
+#define DPNI_FS_MISS_DROP              ((uint16_t)-1)
+
+/**
+ * struct dpni_rx_dist_cfg - Rx distribution configuration
+ * @dist_size: distribution size
+ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with
+ *             the extractions to be used for the distribution key by calling
+ *             dpni_prepare_key_cfg(); relevant only when enable!=0 otherwise
+ *             it can be '0'
+ * @enable: enable/disable the distribution.
+ * @tc: TC id for which distribution is set
+ * @fs_miss_flow_id: when packet misses all rules from flow steering table and
+ *             hash is disabled it will be put into this queue id; use
+ *             DPNI_FS_MISS_DROP to drop frames. The value of this field is
+ *             used only when flow steering distribution is enabled and hash
+ *             distribution is disabled
+ */
+struct dpni_rx_dist_cfg {
+       u16 dist_size;
+       u64 key_cfg_iova;
+       u8 enable;
+       u8 tc;
+       u16 fs_miss_flow_id;
+};
+
+int dpni_set_rx_hash_dist(struct fsl_mc_io *mc_io,
+                         u32 cmd_flags,
+                         u16 token,
+                         const struct dpni_rx_dist_cfg *cfg);
+
 /**
  * enum dpni_dest - DPNI destination types
  * @DPNI_DEST_NONE: Unassigned destination; The queue is set in parked mode and