264 lines
8.5 KiB
Diff
264 lines
8.5 KiB
Diff
From 936ce2452068cb0f6d48ca7d77d6b975802c19ae Mon Sep 17 00:00:00 2001
|
|
From: Ioana Radulescu <ruxandra.radulescu@nxp.com>
|
|
Date: Tue, 3 Sep 2019 14:13:32 +0300
|
|
Subject: [PATCH] dpaa2-eth: Add support for Rx traffic classes
|
|
|
|
The firmware reserves for each DPNI a number of RX frame queues
|
|
equal to the number of configured flows x number of configured
|
|
traffic classes.
|
|
|
|
Current driver configuration directs all incoming traffic to
|
|
FQs corresponding to TC0, leaving all other priority levels unused.
|
|
|
|
Start adding support for multiple ingress traffic classes, by
|
|
configuring the FQs associated with all priority levels, not just
|
|
TC0. All settings that are per-TC, such as those related to
|
|
hashing and flow steering, are also updated.
|
|
|
|
Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
|
|
---
|
|
.../ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c | 7 ++-
|
|
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 70 +++++++++++++++-------
|
|
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 4 +-
|
|
.../net/ethernet/freescale/dpaa2/dpaa2-ethtool.c | 19 ++++--
|
|
4 files changed, 68 insertions(+), 32 deletions(-)
|
|
|
|
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c
|
|
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c
|
|
@@ -81,8 +81,8 @@ static int dpaa2_dbg_fqs_show(struct seq
|
|
int i, err;
|
|
|
|
seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name);
|
|
- seq_printf(file, "%s%16s%16s%16s%16s\n",
|
|
- "VFQID", "CPU", "Type", "Frames", "Pending frames");
|
|
+ seq_printf(file, "%s%16s%16s%16s%16s%16s\n",
|
|
+ "VFQID", "CPU", "TC", "Type", "Frames", "Pending frames");
|
|
|
|
for (i = 0; i < priv->num_fqs; i++) {
|
|
fq = &priv->fq[i];
|
|
@@ -90,9 +90,10 @@ static int dpaa2_dbg_fqs_show(struct seq
|
|
if (err)
|
|
fcnt = 0;
|
|
|
|
- seq_printf(file, "%5d%16d%16s%16llu%16u\n",
|
|
+ seq_printf(file, "%5d%16d%16d%16s%16llu%16u\n",
|
|
fq->fqid,
|
|
fq->target_cpu,
|
|
+ fq->tc,
|
|
fq_type_to_str(fq),
|
|
fq->stats.frames,
|
|
fcnt);
|
|
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
|
|
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
|
|
@@ -1231,6 +1231,7 @@ static void disable_ch_napi(struct dpaa2
|
|
static void dpaa2_eth_set_rx_taildrop(struct dpaa2_eth_priv *priv, bool enable)
|
|
{
|
|
struct dpni_taildrop td = {0};
|
|
+ struct dpaa2_eth_fq *fq;
|
|
int i, err;
|
|
|
|
if (priv->rx_td_enabled == enable)
|
|
@@ -1240,11 +1241,12 @@ static void dpaa2_eth_set_rx_taildrop(st
|
|
td.threshold = DPAA2_ETH_TAILDROP_THRESH;
|
|
|
|
for (i = 0; i < priv->num_fqs; i++) {
|
|
- if (priv->fq[i].type != DPAA2_RX_FQ)
|
|
+ fq = &priv->fq[i];
|
|
+ if (fq->type != DPAA2_RX_FQ)
|
|
continue;
|
|
err = dpni_set_taildrop(priv->mc_io, 0, priv->mc_token,
|
|
- DPNI_CP_QUEUE, DPNI_QUEUE_RX, 0,
|
|
- priv->fq[i].flowid, &td);
|
|
+ DPNI_CP_QUEUE, DPNI_QUEUE_RX,
|
|
+ fq->tc, fq->flowid, &td);
|
|
if (err) {
|
|
netdev_err(priv->net_dev,
|
|
"dpni_set_taildrop() failed\n");
|
|
@@ -2338,7 +2340,7 @@ static void set_fq_affinity(struct dpaa2
|
|
|
|
static void setup_fqs(struct dpaa2_eth_priv *priv)
|
|
{
|
|
- int i;
|
|
+ int i, j;
|
|
|
|
/* We have one TxConf FQ per Tx flow.
|
|
* The number of Tx and Rx queues is the same.
|
|
@@ -2350,10 +2352,13 @@ static void setup_fqs(struct dpaa2_eth_p
|
|
priv->fq[priv->num_fqs++].flowid = (u16)i;
|
|
}
|
|
|
|
- for (i = 0; i < dpaa2_eth_queue_count(priv); i++) {
|
|
- priv->fq[priv->num_fqs].type = DPAA2_RX_FQ;
|
|
- priv->fq[priv->num_fqs].consume = dpaa2_eth_rx;
|
|
- priv->fq[priv->num_fqs++].flowid = (u16)i;
|
|
+ for (j = 0; j < dpaa2_eth_tc_count(priv); j++) {
|
|
+ for (i = 0; i < dpaa2_eth_queue_count(priv); i++) {
|
|
+ priv->fq[priv->num_fqs].type = DPAA2_RX_FQ;
|
|
+ priv->fq[priv->num_fqs].consume = dpaa2_eth_rx;
|
|
+ priv->fq[priv->num_fqs].tc = (u8)j;
|
|
+ priv->fq[priv->num_fqs++].flowid = (u16)i;
|
|
+ }
|
|
}
|
|
|
|
/* For each FQ, decide on which core to process incoming frames */
|
|
@@ -2701,7 +2706,7 @@ static int setup_rx_flow(struct dpaa2_et
|
|
int err;
|
|
|
|
err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
|
|
- DPNI_QUEUE_RX, 0, fq->flowid, &queue, &qid);
|
|
+ DPNI_QUEUE_RX, fq->tc, fq->flowid, &queue, &qid);
|
|
if (err) {
|
|
dev_err(dev, "dpni_get_queue(RX) failed\n");
|
|
return err;
|
|
@@ -2714,7 +2719,7 @@ static int setup_rx_flow(struct dpaa2_et
|
|
queue.destination.priority = 1;
|
|
queue.user_context = (u64)(uintptr_t)fq;
|
|
err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
|
|
- DPNI_QUEUE_RX, 0, fq->flowid,
|
|
+ DPNI_QUEUE_RX, fq->tc, fq->flowid,
|
|
DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST,
|
|
&queue);
|
|
if (err) {
|
|
@@ -2723,6 +2728,10 @@ static int setup_rx_flow(struct dpaa2_et
|
|
}
|
|
|
|
/* xdp_rxq setup */
|
|
+ /* only once for each channel */
|
|
+ if (fq->tc > 0)
|
|
+ return 0;
|
|
+
|
|
err = xdp_rxq_info_reg(&fq->channel->xdp_rxq, priv->net_dev,
|
|
fq->flowid);
|
|
if (err) {
|
|
@@ -2860,7 +2869,7 @@ static int config_legacy_hash_key(struct
|
|
{
|
|
struct device *dev = priv->net_dev->dev.parent;
|
|
struct dpni_rx_tc_dist_cfg dist_cfg;
|
|
- int err;
|
|
+ int i, err = 0;
|
|
|
|
memset(&dist_cfg, 0, sizeof(dist_cfg));
|
|
|
|
@@ -2868,9 +2877,14 @@ static int config_legacy_hash_key(struct
|
|
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");
|
|
+ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
|
|
+ err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token,
|
|
+ i, &dist_cfg);
|
|
+ if (err) {
|
|
+ dev_err(dev, "dpni_set_rx_tc_dist failed\n");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
|
|
return err;
|
|
}
|
|
@@ -2880,7 +2894,7 @@ static int config_hash_key(struct dpaa2_
|
|
{
|
|
struct device *dev = priv->net_dev->dev.parent;
|
|
struct dpni_rx_dist_cfg dist_cfg;
|
|
- int err;
|
|
+ int i, err = 0;
|
|
|
|
memset(&dist_cfg, 0, sizeof(dist_cfg));
|
|
|
|
@@ -2888,9 +2902,15 @@ static int config_hash_key(struct dpaa2_
|
|
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");
|
|
+ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
|
|
+ dist_cfg.tc = i;
|
|
+ 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");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
|
|
return err;
|
|
}
|
|
@@ -2900,7 +2920,7 @@ static int config_cls_key(struct dpaa2_e
|
|
{
|
|
struct device *dev = priv->net_dev->dev.parent;
|
|
struct dpni_rx_dist_cfg dist_cfg;
|
|
- int err;
|
|
+ int i, err = 0;
|
|
|
|
memset(&dist_cfg, 0, sizeof(dist_cfg));
|
|
|
|
@@ -2908,9 +2928,15 @@ static int config_cls_key(struct dpaa2_e
|
|
dist_cfg.dist_size = dpaa2_eth_queue_count(priv);
|
|
dist_cfg.enable = 1;
|
|
|
|
- err = dpni_set_rx_fs_dist(priv->mc_io, 0, priv->mc_token, &dist_cfg);
|
|
- if (err)
|
|
- dev_err(dev, "dpni_set_rx_fs_dist failed\n");
|
|
+ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
|
|
+ dist_cfg.tc = i;
|
|
+ err = dpni_set_rx_fs_dist(priv->mc_io, 0, priv->mc_token,
|
|
+ &dist_cfg);
|
|
+ if (err) {
|
|
+ dev_err(dev, "dpni_set_rx_fs_dist failed\n");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
|
|
return err;
|
|
}
|
|
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
|
|
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
|
|
@@ -291,7 +291,9 @@ struct dpaa2_eth_ch_stats {
|
|
|
|
/* Maximum number of queues associated with a DPNI */
|
|
#define DPAA2_ETH_MAX_TCS 8
|
|
-#define DPAA2_ETH_MAX_RX_QUEUES 16
|
|
+#define DPAA2_ETH_MAX_RX_QUEUES_PER_TC 16
|
|
+#define DPAA2_ETH_MAX_RX_QUEUES \
|
|
+ (DPAA2_ETH_MAX_RX_QUEUES_PER_TC * DPAA2_ETH_MAX_TCS)
|
|
#define DPAA2_ETH_MAX_TX_QUEUES 16
|
|
#define DPAA2_ETH_MAX_QUEUES (DPAA2_ETH_MAX_RX_QUEUES + \
|
|
DPAA2_ETH_MAX_TX_QUEUES)
|
|
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
|
|
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
|
|
@@ -502,7 +502,7 @@ static int do_cls_rule(struct net_device
|
|
dma_addr_t key_iova;
|
|
u64 fields = 0;
|
|
void *key_buf;
|
|
- int err;
|
|
+ int i, err;
|
|
|
|
if (fs->ring_cookie != RX_CLS_FLOW_DISC &&
|
|
fs->ring_cookie >= dpaa2_eth_queue_count(priv))
|
|
@@ -562,11 +562,18 @@ static int do_cls_rule(struct net_device
|
|
fs_act.options |= DPNI_FS_OPT_DISCARD;
|
|
else
|
|
fs_act.flow_id = fs->ring_cookie;
|
|
- err = dpni_add_fs_entry(priv->mc_io, 0, priv->mc_token, 0,
|
|
- fs->location, &rule_cfg, &fs_act);
|
|
- } else {
|
|
- err = dpni_remove_fs_entry(priv->mc_io, 0, priv->mc_token, 0,
|
|
- &rule_cfg);
|
|
+ }
|
|
+ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
|
|
+ if (add)
|
|
+ err = dpni_add_fs_entry(priv->mc_io, 0, priv->mc_token,
|
|
+ i, fs->location, &rule_cfg,
|
|
+ &fs_act);
|
|
+ else
|
|
+ err = dpni_remove_fs_entry(priv->mc_io, 0,
|
|
+ priv->mc_token, i,
|
|
+ &rule_cfg);
|
|
+ if (err)
|
|
+ break;
|
|
}
|
|
|
|
dma_unmap_single(dev, key_iova, rule_cfg.key_size * 2, DMA_TO_DEVICE);
|