|
@@ -289,7 +289,69 @@ static int tc_init(struct stmmac_priv *priv)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int tc_setup_cbs(struct stmmac_priv *priv,
|
|
|
+ struct tc_cbs_qopt_offload *qopt)
|
|
|
+{
|
|
|
+ u32 tx_queues_count = priv->plat->tx_queues_to_use;
|
|
|
+ u32 queue = qopt->queue;
|
|
|
+ u32 ptr, speed_div;
|
|
|
+ u32 mode_to_use;
|
|
|
+ u64 value;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /* Queue 0 is not AVB capable */
|
|
|
+ if (queue <= 0 || queue >= tx_queues_count)
|
|
|
+ return -EINVAL;
|
|
|
+ if (priv->speed != SPEED_100 && priv->speed != SPEED_1000)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use;
|
|
|
+ if (mode_to_use == MTL_QUEUE_DCB && qopt->enable) {
|
|
|
+ ret = stmmac_dma_qmode(priv, priv->ioaddr, queue, MTL_QUEUE_AVB);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB;
|
|
|
+ } else if (!qopt->enable) {
|
|
|
+ return stmmac_dma_qmode(priv, priv->ioaddr, queue, MTL_QUEUE_DCB);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Port Transmit Rate and Speed Divider */
|
|
|
+ ptr = (priv->speed == SPEED_100) ? 4 : 8;
|
|
|
+ speed_div = (priv->speed == SPEED_100) ? 100000 : 1000000;
|
|
|
+
|
|
|
+ /* Final adjustments for HW */
|
|
|
+ value = qopt->idleslope * 1024 * ptr;
|
|
|
+ do_div(value, speed_div);
|
|
|
+ priv->plat->tx_queues_cfg[queue].idle_slope = value & GENMASK(31, 0);
|
|
|
+
|
|
|
+ value = -qopt->sendslope * 1024UL * ptr;
|
|
|
+ do_div(value, speed_div);
|
|
|
+ priv->plat->tx_queues_cfg[queue].send_slope = value & GENMASK(31, 0);
|
|
|
+
|
|
|
+ value = qopt->hicredit * 1024 * 8;
|
|
|
+ priv->plat->tx_queues_cfg[queue].high_credit = value & GENMASK(31, 0);
|
|
|
+
|
|
|
+ value = qopt->locredit * 1024 * 8;
|
|
|
+ priv->plat->tx_queues_cfg[queue].low_credit = value & GENMASK(31, 0);
|
|
|
+
|
|
|
+ ret = stmmac_config_cbs(priv, priv->hw,
|
|
|
+ priv->plat->tx_queues_cfg[queue].send_slope,
|
|
|
+ priv->plat->tx_queues_cfg[queue].idle_slope,
|
|
|
+ priv->plat->tx_queues_cfg[queue].high_credit,
|
|
|
+ priv->plat->tx_queues_cfg[queue].low_credit,
|
|
|
+ queue);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ dev_info(priv->device, "CBS queue %d: send %d, idle %d, hi %d, lo %d\n",
|
|
|
+ queue, qopt->sendslope, qopt->idleslope,
|
|
|
+ qopt->hicredit, qopt->locredit);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
const struct stmmac_tc_ops dwmac510_tc_ops = {
|
|
|
.init = tc_init,
|
|
|
.setup_cls_u32 = tc_setup_cls_u32,
|
|
|
+ .setup_cbs = tc_setup_cbs,
|
|
|
};
|