summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBogdan Purcareata <bogdan.purcareata@nxp.com>2017-08-08 12:11:25 (GMT)
committerXie Xiaobo <xiaobo.xie@nxp.com>2017-12-12 07:32:41 (GMT)
commit8fa80f047b35fffab695bbdf2fd41c62614deb4d (patch)
tree3b51547b9322e9e1e09e16afd88a84e301b2829a
parent7ab18e0e1c385b50faea0934a8188820c606af04 (diff)
downloadlinux-8fa80f047b35fffab695bbdf2fd41c62614deb4d.tar.xz
staging: fsl-dpaa2/eth: Refactor fq taildrop setup
With the introduction of PFC support, there are multiple ways taildrop is configured, based on the DPNI pause frame configuration: - no pause frames - per-queue taildrop thresholds. - pause frames - no taildrop thresholds (pause frames sent based on buffer depletion). - PFC pause frames - per-group (traffic class) taildrop thresholds for non-PFC enabled priorities (pause frames sent based on Rx congestion notifications). Refactor the fq taildrop setup area. Signed-off-by: Bogdan Purcareata <bogdan.purcareata@nxp.com>
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c109
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h28
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c3
3 files changed, 119 insertions, 21 deletions
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
index e4844ae..5523e58 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
@@ -2116,7 +2116,7 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
/* Enable flow control */
cfg.options = DPNI_LINK_OPT_AUTONEG | DPNI_LINK_OPT_PAUSE;
- priv->tx_pause_frames = 1;
+ priv->tx_pause_frames = true;
err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
if (err) {
@@ -2158,24 +2158,12 @@ static void free_dpni(struct dpaa2_eth_priv *priv)
kfree(priv->cscn_unaligned);
}
-int setup_fqs_taildrop(struct dpaa2_eth_priv *priv,
- bool enable)
+static int set_queue_taildrop(struct dpaa2_eth_priv *priv,
+ struct dpni_taildrop *td)
{
struct device *dev = priv->net_dev->dev.parent;
- struct dpni_taildrop td;
- int err = 0, i;
-
- td.enable = enable;
- td.threshold = DPAA2_ETH_TAILDROP_THRESH;
+ int err, i;
- if (enable) {
- priv->num_bufs = DPAA2_ETH_NUM_BUFS_TD;
- priv->refill_thresh = DPAA2_ETH_REFILL_THRESH_TD;
- } else {
- priv->num_bufs = DPAA2_ETH_NUM_BUFS_FC /
- priv->num_channels;
- priv->refill_thresh = priv->num_bufs - DPAA2_ETH_BUFS_PER_CMD;
- }
for (i = 0; i < priv->num_fqs; i++) {
if (priv->fq[i].type != DPAA2_RX_FQ)
@@ -2184,14 +2172,97 @@ int setup_fqs_taildrop(struct dpaa2_eth_priv *priv,
err = dpni_set_taildrop(priv->mc_io, 0, priv->mc_token,
DPNI_CP_QUEUE, DPNI_QUEUE_RX,
priv->fq[i].tc, priv->fq[i].flowid,
- &td);
+ td);
if (err) {
dev_err(dev, "dpni_set_taildrop() failed (%d)\n", err);
- break;
+ return err;
}
}
- return err;
+ return 0;
+}
+
+static int set_group_taildrop(struct dpaa2_eth_priv *priv,
+ struct dpni_taildrop *td)
+{
+ struct device *dev = priv->net_dev->dev.parent;
+ struct dpni_taildrop disable_td, *tc_td;
+ int i, err;
+
+ memset(&disable_td, 0, sizeof(struct dpni_taildrop));
+ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
+ if (td->enable && dpaa2_eth_is_pfc_enabled(priv, i))
+ /* Do not set taildrop thresholds for PFC-enabled
+ * traffic classes. We will enable congestion
+ * notifications for them.
+ */
+ tc_td = &disable_td;
+ else
+ tc_td = td;
+
+ err = dpni_set_taildrop(priv->mc_io, 0, priv->mc_token,
+ DPNI_CP_GROUP, DPNI_QUEUE_RX,
+ i, 0, tc_td);
+ if (err) {
+ dev_err(dev, "dpni_set_taildrop() failed (%d)\n", err);
+ return err;
+ }
+ }
+ return 0;
+}
+
+/* Enable/disable Rx FQ taildrop
+ *
+ * Rx FQ taildrop is mutually exclusive with flow control and it only gets
+ * disabled when FC is active. Depending on FC status, we need to compute
+ * the maximum number of buffers in the pool differently, so use the
+ * opportunity to update max number of buffers as well.
+ */
+int set_rx_taildrop(struct dpaa2_eth_priv *priv)
+{
+ enum dpaa2_eth_td_cfg cfg = dpaa2_eth_get_td_type(priv);
+ struct dpni_taildrop td_queue, td_group;
+ int err = 0;
+
+ switch (cfg) {
+ case DPAA2_ETH_TD_NONE:
+ memset(&td_queue, 0, sizeof(struct dpni_taildrop));
+ memset(&td_group, 0, sizeof(struct dpni_taildrop));
+ priv->max_bufs_per_ch = DPAA2_ETH_NUM_BUFS_FC /
+ priv->num_channels;
+ break;
+ case DPAA2_ETH_TD_QUEUE:
+ memset(&td_group, 0, sizeof(struct dpni_taildrop));
+ td_queue.enable = 1;
+ td_queue.units = DPNI_CONGESTION_UNIT_BYTES;
+ td_queue.threshold = DPAA2_ETH_TAILDROP_THRESH /
+ dpaa2_eth_tc_count(priv);
+ priv->max_bufs_per_ch = DPAA2_ETH_NUM_BUFS_PER_CH;
+ break;
+ case DPAA2_ETH_TD_GROUP:
+ memset(&td_queue, 0, sizeof(struct dpni_taildrop));
+ td_group.enable = 1;
+ td_group.units = DPNI_CONGESTION_UNIT_FRAMES;
+ td_group.threshold = NAPI_POLL_WEIGHT *
+ dpaa2_eth_queue_count(priv);
+ priv->max_bufs_per_ch = NAPI_POLL_WEIGHT *
+ dpaa2_eth_tc_count(priv);
+ break;
+ default:
+ break;
+ }
+
+ err = set_queue_taildrop(priv, &td_queue);
+ if (err)
+ return err;
+
+ err = set_group_taildrop(priv, &td_group);
+ if (err)
+ return err;
+
+ priv->refill_thresh = DPAA2_ETH_REFILL_THRESH(priv);
+
+ return 0;
}
static int setup_rx_flow(struct dpaa2_eth_priv *priv,
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
index 4d2ac3a..3f5419d 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
@@ -436,6 +436,7 @@ struct dpaa2_eth_priv {
u8 dcbx_mode;
struct ieee_pfc pfc;
bool vlan_clsf_set;
+ bool tx_pause_frames;
};
#define dpaa2_eth_hash_enabled(priv) \
@@ -466,7 +467,32 @@ static inline int dpaa2_eth_tc_count(struct dpaa2_eth_priv *priv)
return priv->dpni_attrs.num_tcs;
}
+static inline bool dpaa2_eth_is_pfc_enabled(struct dpaa2_eth_priv *priv,
+ int traffic_class)
+{
+ return priv->pfc.pfc_en & (1 << traffic_class);
+}
+
+enum dpaa2_eth_td_cfg {
+ DPAA2_ETH_TD_NONE,
+ DPAA2_ETH_TD_QUEUE,
+ DPAA2_ETH_TD_GROUP
+};
+
+static inline enum dpaa2_eth_td_cfg
+dpaa2_eth_get_td_type(struct dpaa2_eth_priv *priv)
+{
+ bool pfc_enabled = !!(priv->pfc.pfc_en);
+
+ if (pfc_enabled)
+ return DPAA2_ETH_TD_GROUP;
+ else if (priv->tx_pause_frames)
+ return DPAA2_ETH_TD_NONE;
+ else
+ return DPAA2_ETH_TD_QUEUE;
+}
+
void check_cls_support(struct dpaa2_eth_priv *priv);
-int setup_fqs_taildrop(struct dpaa2_eth_priv *priv, bool enable);
+int set_rx_taildrop(struct dpaa2_eth_priv *priv);
#endif /* __DPAA2_H */
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
index 4c2c654..304a21c 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
@@ -230,7 +230,8 @@ static int dpaa2_eth_set_pauseparam(struct net_device *net_dev,
if (current_tx_pause == pause->tx_pause)
goto out;
- err = setup_fqs_taildrop(priv, !pause->tx_pause);
+ priv->tx_pause_frames = pause->tx_pause;
+ err = set_rx_taildrop(priv);
if (err)
netdev_dbg(net_dev, "ERROR %d configuring taildrop", err);