nvethernet: Add FRP command IOCTL support

Add new private IOCTL to perform
Flexible Receive Parser table entry
add, delete, and update operations
using OSI API call.

Bug 200565623

Change-Id: I00f2be1aaa6ee737de5154085be0521db0bb9593
Signed-off-by: Mohan Thadikamalla <mohant@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2331371
Reviewed-by: Rakesh Goyal <rgoyal@nvidia.com>
Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
This commit is contained in:
Mohan Thadikamalla
2020-04-20 15:27:33 +05:30
committed by Revanth Kumar Uppala
parent f244049a90
commit c2f3c724bd
5 changed files with 148 additions and 0 deletions

View File

@@ -43,6 +43,7 @@ nvethernet-objs:= ether_linux.o \
$(OSI_DMA)/eqos_desc.o \
$(OSI_DMA)/mgbe_desc.o \
$(OSI_CORE)/mgbe_mmc.o \
$(OSI_CORE)/frp.o \
$(OSI_CORE)/vlan_filter.o
nvethernet-$(CONFIG_NVETHERNET_SELFTESTS) += selftests.o

View File

@@ -39,6 +39,35 @@ struct ether_stats {
size_t stat_offset;
};
/**
* @brief Name of FRP statistics, with length of name not more than
* ETH_GSTRING_LEN
*/
#if KERNEL_VERSION(5, 5, 0) > LINUX_VERSION_CODE
#define ETHER_PKT_FRP_STAT(y) \
{ (#y), FIELD_SIZEOF(struct osi_pkt_err_stats, y), \
offsetof(struct osi_dma_priv_data, pkt_err_stats.y)}
#else
#define ETHER_PKT_FRP_STAT(y) \
{ (#y), sizeof_field(struct osi_pkt_err_stats, y), \
offsetof(struct osi_dma_priv_data, pkt_err_stats.y)}
#endif
/**
* @brief FRP statistics
*/
static const struct ether_stats ether_frpstrings_stats[] = {
ETHER_PKT_FRP_STAT(frp_parsed),
ETHER_PKT_FRP_STAT(frp_dropped),
ETHER_PKT_FRP_STAT(frp_err),
ETHER_PKT_FRP_STAT(frp_incomplete),
};
/**
* @brief Ethernet FRP statistics array length
*/
#define ETHER_FRP_STAT_LEN OSI_ARRAY_SIZE(ether_frpstrings_stats)
/**
* @brief Name of pkt_err statistics, with length of name not more than
* ETH_GSTRING_LEN
@@ -496,6 +525,15 @@ static void ether_get_ethtool_stats(struct net_device *dev,
data[j++] = (ether_tstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
}
for (i = 0; ((i < ETHER_FRP_STAT_LEN) &&
(pdata->hw_feat.frp_sel == OSI_ENABLE)); i++) {
char *p = (char *)osi_core +
ether_frpstrings_stats[i].stat_offset;
data[j++] = (ether_frpstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
}
}
}
@@ -546,6 +584,13 @@ static int ether_get_sset_count(struct net_device *dev, int sset)
len += ETHER_EXTRA_TSN_STAT_LEN;
}
}
if (INT_MAX - ETHER_FRP_STAT_LEN < len) {
/* do nothing */
} else {
if (pdata->hw_feat.frp_sel == OSI_ENABLE) {
len += ETHER_FRP_STAT_LEN;
}
}
} else if (sset == ETH_SS_TEST) {
len = ether_selftest_get_count(pdata);
} else {
@@ -619,6 +664,17 @@ static void ether_get_strings(struct net_device *dev, u32 stringset, u8 *data)
}
p += ETH_GSTRING_LEN;
}
for (i = 0; ((i < ETHER_FRP_STAT_LEN) &&
(pdata->hw_feat.frp_sel == OSI_ENABLE));
i++) {
str = (u8 *)
ether_frpstrings_stats[i].stat_string;
if (memcpy(p, str, ETH_GSTRING_LEN) ==
OSI_NULL) {
return;
}
p += ETH_GSTRING_LEN;
}
}
} else if (stringset == (u32)ETH_SS_TEST) {
ether_selftest_get_strings(pdata, p);

View File

@@ -256,6 +256,48 @@ static int ether_config_arp_offload(struct ether_priv_data *pdata,
return ret;
}
/**
* @brief This function is invoked by ioctl function when user issues an ioctl
* command to configure Flexible Receive Parser table entry add, delete, and
* update commands.
*
* @param[in] dev: Pointer to net device structure.
* @param[in] ifdata: pointer to IOCTL specific structure.
*
* @note MAC and PHY need to be initialized.
*
* @retval 0 on Success
* @retval "negative value" on Failure
*/
static int ether_config_frp_cmd(struct net_device *dev,
struct ether_ifr_data *ifdata)
{
struct ether_priv_data *pdata = netdev_priv(dev);
struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_core_frp_cmd frp_cmd;
int ret = -EINVAL;
if (pdata->hw_feat.frp_sel == OSI_DISABLE) {
dev_err(pdata->dev, "MAC doen't support FRP\n");
return ret;
}
if (!ifdata->ptr) {
dev_err(pdata->dev, "%s: Invalid data for priv ioctl %d\n",
__func__, ifdata->ifcmd);
return ret;
}
if (copy_from_user(&frp_cmd,
(struct osi_core_frp_cmd *)ifdata->ptr,
sizeof(struct osi_core_frp_cmd)) != 0U) {
dev_err(pdata->dev, "%s copy from user failed\n", __func__);
return -EFAULT;
}
return osi_configure_frp(osi_core, &frp_cmd);
}
/**
* @brief This function is invoked by ioctl when user issues an ioctl command
* to enable/disable L3/L4 filtering.
@@ -910,6 +952,9 @@ int ether_handle_priv_ioctl(struct net_device *ndev,
ret = -EOPNOTSUPP;
}
break;
case ETHER_CONFIG_FRP_CMD:
ret = ether_config_frp_cmd(ndev, &ifdata);
break;
case EQOS_IPV4_FILTERING_CMD:
ret = ether_config_ip4_filters(ndev, &ifdata);
break;

View File

@@ -58,6 +58,8 @@
#define ETHER_PTP_RXQUEUE 48
#define ETHER_CONFIG_EST 49
#define ETHER_CONFIG_FPE 50
/* FRP Command */
#define ETHER_CONFIG_FRP_CMD 51
/** @} */
/**

View File

@@ -121,6 +121,49 @@ static DEVICE_ATTR(mac_loopback, (S_IRUGO | S_IWUSR),
ether_mac_loopback_show,
ether_mac_loopback_store);
/**
* @brief Shows the current setting of FRP Table
*
* Algorithm: Display the FRP table
*
* @param[in] dev: Device data.
* @param[in] attr: Device attribute
* @param[in] buf: Buffer to store the current MAC loopback setting
*
* @note MAC and PHY need to be initialized.
*/
static ssize_t ether_mac_frp_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct net_device *ndev = (struct net_device *)dev_get_drvdata(dev);
struct ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_core_frp_entry *entry = NULL;
struct osi_core_frp_data *data = NULL;
int i = 0, j = 0;
/* Write FRP table entries */
for (i = 0, j = 0; ((i < osi_core->frp_cnt) && (j < PAGE_SIZE)); i++) {
entry = &osi_core->frp_table[i];
data = &entry->data;
j += scnprintf((buf + j), (PAGE_SIZE - j),
"[%d] ID:%d MD:0x%x ME:0x%x AF:%d RF:%d IM:%d NIC:%d FO:%d OKI:%d DCH:x%x\n",
i, entry->frp_id, data->match_data,
data->match_en, data->accept_frame,
data->reject_frame, data->inverse_match,
data->next_ins_ctrl, data->frame_offset,
data->ok_index, data->dma_chsel);
}
return j;
}
/**
* @brief Sysfs attribute for FRP table show
*
*/
static DEVICE_ATTR(frp, 0644, ether_mac_frp_show, NULL);
/**
* @brief Shows the current setting of PTP mode
*
@@ -275,6 +318,7 @@ static struct attribute *ether_sysfs_attrs[] = {
&dev_attr_mac_loopback.attr,
&dev_attr_ptp_mode.attr,
&dev_attr_ptp_sync.attr,
&dev_attr_frp.attr,
NULL
};