From dbf00db6bb40fc749af853a79b67f81528a56918 Mon Sep 17 00:00:00 2001 From: Rakesh Goyal Date: Tue, 4 Jan 2022 15:32:08 +0530 Subject: [PATCH] Add support for configure CBS through TC Issue: New feature requirement to have CBS configuration through TC Fix: added support for same. sudo tc qdisc add dev eth4 parent root handle 6666 mqprio \ num_tc 3 \ map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \ queues 1@0 1@1 2@2 \ hw 0 sudo tc qdisc replace dev eth4 parent 6666:3 cbs \ idleslope 2000000 sendslope -8000000 hicredit 3000 locredit -1200 \ offload 1 Bug 200776994 Change-Id: Id83b967bcbbb18201f2757987ab1cefe63b4ad8d Signed-off-by: Rakesh Goyal Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2649428 Reviewed-by: svc_kernel_abi Reviewed-by: Narayan Reddy Reviewed-by: Nagarjuna Kristam Reviewed-by: Sachin Nikam GVS: Gerrit_Virtual_Submit --- .../ethernet/nvidia/nvethernet/ether_linux.c | 2 + .../ethernet/nvidia/nvethernet/ether_linux.h | 27 +++++- .../net/ethernet/nvidia/nvethernet/ether_tc.c | 82 ++++++++++++++++++- 3 files changed, 109 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c index df37a0fe..f5182c0b 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c @@ -4109,6 +4109,8 @@ static int ether_setup_tc(struct net_device *ndev, enum tc_setup_type type, switch (type) { case TC_SETUP_QDISC_TAPRIO: return ether_tc_setup_taprio(pdata, type_data); + case TC_SETUP_QDISC_CBS: + return ether_tc_setup_cbs(pdata, type_data); default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h index f4e61264..e7e20183 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -73,6 +73,13 @@ #include #endif /* ETHER_NVGRO */ +/** + * @brief Constant for CBS value calculate + */ +#define ETH_1K 1000 +#define MULTIPLIER_32 32 +#define MULTIPLIER_8 8 +#define MULTIPLIER_4 4 /** * @brief Max number of Ethernet IRQs supported in HW */ @@ -758,6 +765,24 @@ void ether_set_rx_mode(struct net_device *dev); */ int ether_tc_setup_taprio(struct ether_priv_data *pdata, struct tc_taprio_qopt_offload *qopt); + +/** + * @brief Function to configure credit base shapper + * + * Algorithm: This function is used to handle the hardware CBS + * settings. + * + * @param[in] pdata: Pointer to private data structure. + * @param[in] qopt: Pointer to qdisc taprio offload data. + * + * @note MAC interface should be up. + * + * @retval 0 on success + * @retval "negative value" on Failure + */ +int ether_tc_setup_cbs(struct ether_priv_data *pdata, + struct tc_cbs_qopt_offload *qopt); + #endif #ifdef ETHER_NVGRO void ether_nvgro_purge_timer(struct timer_list *t); diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_tc.c b/drivers/net/ethernet/nvidia/nvethernet/ether_tc.c index 7d2278bd..4478a262 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_tc.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_tc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -170,4 +170,84 @@ disable: done: return ret; } + +int ether_tc_setup_cbs(struct ether_priv_data *pdata, + struct tc_cbs_qopt_offload *qopt) +{ + struct osi_core_priv_data *osi_core = pdata->osi_core; + struct phy_device *phydev = pdata->phydev; + struct osi_ioctl ioctl_data = {}; + int queue = qopt->queue; + unsigned int multiplier, speed_div; + unsigned long value; + int speed; + + /* Queue 0 is not AVB capable */ + if (queue <= 0) { + netdev_err(pdata->ndev, "%s() invalid queue\n", __func__); + return -EINVAL; + } + + if (phydev != NULL) { + speed = phydev->speed; + } else { + speed = pdata->speed; + } + + switch (speed) { + case OSI_SPEED_10000: + multiplier = MULTIPLIER_32; + speed_div = OSI_SPEED_10000 * ETH_1K; + break; + case OSI_SPEED_5000: + multiplier = MULTIPLIER_32; + speed_div = OSI_SPEED_5000 * ETH_1K; + break; + case OSI_SPEED_2500: + multiplier = MULTIPLIER_8; + speed_div = OSI_SPEED_2500 * ETH_1K; + break; + case OSI_SPEED_1000: + multiplier = MULTIPLIER_8; + speed_div = OSI_SPEED_1000 * ETH_1K; + break; + case OSI_SPEED_100: + multiplier = MULTIPLIER_4; + speed_div = OSI_SPEED_100 * ETH_1K; + break; + default: + netdev_err(pdata->ndev, "invalid speed\n"); + return -EINVAL; + } + + ioctl_data.avb.qindex = (unsigned int)queue; + ioctl_data.avb.tcindex = (unsigned int)queue; + + if (qopt->enable) { + ioctl_data.avb.algo = OSI_MTL_TXQ_AVALG_CBS; + ioctl_data.avb.oper_mode = OSI_MTL_QUEUE_AVB; + ioctl_data.avb.credit_control = OSI_ENABLE; + } else { + ioctl_data.avb.algo = OSI_MTL_TXQ_AVALG_SP; + ioctl_data.avb.oper_mode = OSI_MTL_QUEUE_ENABLE; + ioctl_data.avb.credit_control = OSI_DISABLE; + } + + /* Final adjustments for HW */ + value = div_s64(qopt->idleslope * 1024ll * multiplier, speed_div); + ioctl_data.avb.idle_slope = (unsigned long)value; + + value = div_s64(-qopt->sendslope * 1024ll * multiplier, speed_div); + ioctl_data.avb.send_slope = (unsigned long)value; + + value = qopt->hicredit * 1024ll * 8; + ioctl_data.avb.hi_credit = (unsigned long)value; + + value = qopt->locredit * 1024ll * 8; + ioctl_data.avb.low_credit = (unsigned long)value; + + ioctl_data.cmd = OSI_CMD_SET_AVB; + + return osi_handle_ioctl(osi_core, &ioctl_data); +} #endif