mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
nvethernet: tctool support for EST and FPE
Add support for ndo_setup_tc in network device operations for kernel 5.10 or above. Bug 200622871 Change-Id: Id5f96001be3b00925d26efaca1b39e26b959e952 Signed-off-by: rakesh goyal <rgoyal@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2550396 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Revanth Kumar Uppala
parent
300cffe2bc
commit
3f0e18c74d
@@ -27,6 +27,7 @@ ccflags-y += -DMACSEC_SUPPORT -DNET30 -DMACSEC_DEBUG -DOSI_DMA_DEBUG
|
||||
nvethernet-objs:= ether_linux.o \
|
||||
osd.o \
|
||||
ethtool.o \
|
||||
ether_tc.o \
|
||||
sysfs.o \
|
||||
ioctl.o \
|
||||
ptp.o \
|
||||
|
||||
@@ -3670,6 +3670,43 @@ static int ether_vlan_rx_kill_vid(struct net_device *ndev, __be16 vlan_proto,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE)
|
||||
/**
|
||||
* @brief ether_setup_tc - TC HW offload support
|
||||
*
|
||||
* Algorithm:
|
||||
* 1) Check the TC setup type
|
||||
* 2) Call appropriate function based on type.
|
||||
*
|
||||
* @param[in] ndev: Network device structure
|
||||
* @param[in] type: qdisc type
|
||||
* @param[in] type_data: void pointer having user passed configuration
|
||||
*
|
||||
* @note Ethernet interface should be up
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval "negative value" on failure.
|
||||
*/
|
||||
static int ether_setup_tc(struct net_device *ndev, enum tc_setup_type type,
|
||||
void *type_data)
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
|
||||
if (!netif_running(ndev)) {
|
||||
dev_err(pdata->dev, "Not Allowed. Ether interface is not up\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case TC_SETUP_QDISC_TAPRIO:
|
||||
return ether_tc_setup_taprio(pdata, type_data);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Ethernet network device operations
|
||||
*/
|
||||
@@ -3685,6 +3722,9 @@ static const struct net_device_ops ether_netdev_ops = {
|
||||
.ndo_set_rx_mode = ether_set_rx_mode,
|
||||
.ndo_vlan_rx_add_vid = ether_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = ether_vlan_rx_kill_vid,
|
||||
#if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE)
|
||||
.ndo_setup_tc = ether_setup_tc,
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/tegra-ivc.h>
|
||||
#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
|
||||
#include <soc/tegra/chip-id.h>
|
||||
@@ -584,8 +585,8 @@ void ether_ptp_remove(struct ether_priv_data *pdata);
|
||||
*
|
||||
* Algorithm: This function is used to handle the hardware PTP settings.
|
||||
*
|
||||
* @param[in] pdata Pointer to private data structure.
|
||||
* @param[in] ifr Interface request structure used for socket ioctl
|
||||
* @param[in] pdata: Pointer to private data structure.
|
||||
* @param[in] ifr: Interface request structure used for socket ioctl
|
||||
*
|
||||
* @note PTP clock driver need to be successfully registered during
|
||||
* initialization and HW need to support PTP functionality.
|
||||
@@ -659,5 +660,25 @@ void ether_assign_osd_ops(struct osi_core_priv_data *osi_core,
|
||||
*/
|
||||
int osd_ivc_send_cmd(void *priv, ivc_msg_common_t *ivc_buf,
|
||||
unsigned int len);
|
||||
|
||||
void ether_set_rx_mode(struct net_device *dev);
|
||||
|
||||
#if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE)
|
||||
/**
|
||||
* @brief Function to configure traffic class
|
||||
*
|
||||
* Algorithm: This function is used to handle the hardware TC
|
||||
* 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_taprio(struct ether_priv_data *pdata,
|
||||
struct tc_taprio_qopt_offload *qopt);
|
||||
#endif
|
||||
#endif /* ETHER_LINUX_H */
|
||||
|
||||
173
drivers/net/ethernet/nvidia/nvethernet/ether_tc.c
Normal file
173
drivers/net/ethernet/nvidia/nvethernet/ether_tc.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ether_linux.h"
|
||||
|
||||
#if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE)
|
||||
int ether_tc_setup_taprio(struct ether_priv_data *pdata,
|
||||
struct tc_taprio_qopt_offload *qopt)
|
||||
{
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
unsigned int fpe_required = OSI_DISABLE;
|
||||
struct osi_ioctl fpe_ioctl_data = {};
|
||||
struct osi_ioctl est_ioctl_data = {};
|
||||
unsigned long cycle_time = 0x0U;
|
||||
/* Hardcode width base on current HW config, input parameter validation
|
||||
* will be done by OSI code any way
|
||||
*/
|
||||
/* total GCL enatry will have 32 valid bits */
|
||||
unsigned int wid_val = OSI_MAX_32BITS;
|
||||
unsigned int gates = 0x0U;
|
||||
/* time is 24 bit long */
|
||||
unsigned int wid = 24U;
|
||||
struct timespec64 time;
|
||||
unsigned long ctr;
|
||||
int i, ret = 0;
|
||||
|
||||
if (qopt == NULL) {
|
||||
netdev_err(pdata->ndev, "invalid input argument\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((osi_core->hw_feature != OSI_NULL) &&
|
||||
(pdata->hw_feat.est_sel == OSI_DISABLE)) {
|
||||
netdev_err(pdata->ndev, "EST not supported in HW\n");
|
||||
ret = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (qopt->num_entries >= OSI_GCL_SIZE_256) {
|
||||
netdev_err(pdata->ndev, "invalid number of GCL entries\n");
|
||||
ret = -ERANGE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!qopt->base_time) {
|
||||
netdev_err(pdata->ndev, "invalid base time\n");
|
||||
ret = -ERANGE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!qopt->cycle_time) {
|
||||
netdev_err(pdata->ndev, "invalid Cycle time\n");
|
||||
ret = -ERANGE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(&est_ioctl_data.est, 0x0, sizeof(struct osi_est_config));
|
||||
memset(&est_ioctl_data.fpe, 0x0, sizeof(struct osi_fpe_config));
|
||||
|
||||
/* This code is to disable TSN, User space is asking to disable
|
||||
*/
|
||||
if (!qopt->enable) {
|
||||
goto disable;
|
||||
}
|
||||
|
||||
est_ioctl_data.est.llr = qopt->num_entries;
|
||||
est_ioctl_data.est.en_dis = qopt->enable;
|
||||
|
||||
for (i = 0U; i < est_ioctl_data.est.llr; i++) {
|
||||
cycle_time = qopt->entries[i].interval;
|
||||
gates = qopt->entries[i].gate_mask;
|
||||
|
||||
switch (qopt->entries[i].command) {
|
||||
case TC_TAPRIO_CMD_SET_GATES:
|
||||
if (fpe_required == OSI_ENABLE) {
|
||||
netdev_err(pdata->ndev,
|
||||
"with set-and-hold/release, only set command is not expected\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case TC_TAPRIO_CMD_SET_AND_HOLD:
|
||||
gates |= OSI_BIT(0);
|
||||
fpe_required = OSI_ENABLE;
|
||||
break;
|
||||
case TC_TAPRIO_CMD_SET_AND_RELEASE:
|
||||
gates &= ~OSI_BIT(0);
|
||||
fpe_required = OSI_ENABLE;
|
||||
break;
|
||||
default:
|
||||
netdev_err(pdata->ndev, "invalid command\n");
|
||||
ret = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
||||
est_ioctl_data.est.gcl[i] = cycle_time | (gates << wid);
|
||||
if (est_ioctl_data.est.gcl[i] > wid_val) {
|
||||
netdev_err(pdata->ndev, "invalid GCL creation\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust for real system time TODO better to have
|
||||
* some offset to avoid BTRE
|
||||
*/
|
||||
time = ktime_to_timespec64(qopt->base_time);
|
||||
est_ioctl_data.est.btr[0] = (unsigned int)time.tv_nsec;
|
||||
est_ioctl_data.est.btr[1] = (unsigned int)time.tv_sec;
|
||||
est_ioctl_data.est.btr_offset[0] = 0;
|
||||
est_ioctl_data.est.btr_offset[1] = 0;
|
||||
|
||||
ctr = qopt->cycle_time;
|
||||
est_ioctl_data.est.ctr[0] = do_div(ctr, NSEC_PER_SEC);
|
||||
est_ioctl_data.est.ctr[1] = (unsigned int)ctr;
|
||||
|
||||
if ((!pdata->hw_feat.fpe_sel) && (fpe_required == OSI_ENABLE)) {
|
||||
netdev_err(pdata->ndev, "FPE not supported in HW\n");
|
||||
ret = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (fpe_required == OSI_ENABLE) {
|
||||
fpe_ioctl_data.fpe.rq = osi_core->residual_queue;
|
||||
fpe_ioctl_data.fpe.tx_queue_preemption_enable = 0x1;
|
||||
fpe_ioctl_data.cmd = OSI_CMD_CONFIG_FPE;
|
||||
ret = osi_handle_ioctl(osi_core, &fpe_ioctl_data);
|
||||
if (ret < 0) {
|
||||
netdev_err(pdata->ndev,
|
||||
"failed to enable Frame Preemption\n");
|
||||
goto done;
|
||||
} else {
|
||||
netdev_info(pdata->ndev, "configured FPE\n");
|
||||
}
|
||||
}
|
||||
|
||||
est_ioctl_data.cmd = OSI_CMD_CONFIG_EST;
|
||||
ret = osi_handle_ioctl(osi_core, &est_ioctl_data);
|
||||
if (ret < 0) {
|
||||
netdev_err(pdata->ndev, "failed to configure EST\n");
|
||||
goto disable;
|
||||
}
|
||||
|
||||
netdev_info(pdata->ndev, "configured EST\n");
|
||||
return 0;
|
||||
|
||||
disable:
|
||||
est_ioctl_data.est.en_dis = false;
|
||||
est_ioctl_data.cmd = OSI_CMD_CONFIG_EST;
|
||||
ret = osi_handle_ioctl(osi_core, &est_ioctl_data);
|
||||
if ((ret >= 0) && (fpe_required == OSI_ENABLE)) {
|
||||
fpe_ioctl_data.fpe.tx_queue_preemption_enable = 0x0;
|
||||
fpe_ioctl_data.cmd = OSI_CMD_CONFIG_FPE;
|
||||
ret = osi_handle_ioctl(osi_core, &fpe_ioctl_data);
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user