mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 10:11:26 +03:00
nvethernet: Extend PTP support
Adding support for one step sync Adding support for user input from sysfs node Bug 200562043 Change-Id: I686f035d54c8fb998db968178aca772258830ec7 Signed-off-by: rakesh goyal <rgoyal@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2314229 Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
This commit is contained in:
committed by
Revanth Kumar Uppala
parent
a6520f2194
commit
59e2c42725
@@ -30,6 +30,7 @@ nvethernet-objs:= ether_linux.o \
|
||||
$(OSI_CORE)/osi_core.o \
|
||||
$(OSI_COMMON)/osi_common.o \
|
||||
$(OSI_COMMON)/eqos_common.o \
|
||||
$(OSI_COMMON)/mgbe_common.o \
|
||||
$(OSI_DMA)/osi_dma.o \
|
||||
$(OSI_DMA)/osi_dma_txrx.o \
|
||||
$(OSI_CORE)/eqos_core.o \
|
||||
|
||||
@@ -1701,6 +1701,8 @@ static int ether_open(struct net_device *dev)
|
||||
* structure variable as well */
|
||||
pdata->vlan_hash_filtering = OSI_PERFECT_FILTER_MODE;
|
||||
pdata->l2_filtering_mode = OSI_PERFECT_FILTER_MODE;
|
||||
/* Set default PTP mode as Two step */
|
||||
pdata->osi_dma->ptp_flag = OSI_PTP_SYNC_TWOSTEP;
|
||||
|
||||
/* Initialize PTP */
|
||||
ret = ether_ptp_init(pdata);
|
||||
@@ -1955,13 +1957,14 @@ static int ether_handle_tso(struct osi_tx_pkt_cx *tx_pkt_cx,
|
||||
* @retval "number of descriptors" on success
|
||||
* @retval "negative value" on failure.
|
||||
*/
|
||||
static int ether_tx_swcx_alloc(struct device *dev,
|
||||
static int ether_tx_swcx_alloc(struct ether_priv_data *pdata,
|
||||
struct osi_tx_ring *tx_ring,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct osi_tx_pkt_cx *tx_pkt_cx = &tx_ring->tx_pkt_cx;
|
||||
unsigned int cur_tx_idx = tx_ring->cur_tx_idx;
|
||||
struct osi_tx_swcx *tx_swcx = NULL;
|
||||
struct device *dev = pdata->dev;
|
||||
unsigned int len = 0, offset = 0, size = 0;
|
||||
int cnt = 0, ret = 0, i, num_frags;
|
||||
#if (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE)
|
||||
@@ -2003,7 +2006,12 @@ static int ether_tx_swcx_alloc(struct device *dev,
|
||||
}
|
||||
|
||||
if (((tx_pkt_cx->flags & OSI_PKT_CX_VLAN) == OSI_PKT_CX_VLAN) ||
|
||||
((tx_pkt_cx->flags & OSI_PKT_CX_TSO) == OSI_PKT_CX_TSO)) {
|
||||
((tx_pkt_cx->flags & OSI_PKT_CX_TSO) == OSI_PKT_CX_TSO) ||
|
||||
(((tx_pkt_cx->flags & OSI_PKT_CX_PTP) == OSI_PKT_CX_PTP) &&
|
||||
/* Check only MGBE as we need ctx fro both sync mode */
|
||||
((pdata->osi_core->mac == OSI_MAC_HW_MGBE) ||
|
||||
((pdata->osi_dma->ptp_flag & OSI_PTP_SYNC_ONESTEP) ==
|
||||
OSI_PTP_SYNC_ONESTEP)))) {
|
||||
tx_swcx = tx_ring->tx_swcx + cur_tx_idx;
|
||||
if (tx_swcx->len) {
|
||||
return 0;
|
||||
@@ -2042,7 +2050,7 @@ static int ether_tx_swcx_alloc(struct device *dev,
|
||||
ret = -ENOMEM;
|
||||
goto dma_map_failed;
|
||||
}
|
||||
tx_swcx->is_paged_buf = 0;
|
||||
tx_swcx->flags &= ~OSI_PKT_CX_PAGED_BUF;
|
||||
|
||||
tx_swcx->len = size;
|
||||
len -= size;
|
||||
@@ -2075,7 +2083,7 @@ static int ether_tx_swcx_alloc(struct device *dev,
|
||||
goto dma_map_failed;
|
||||
}
|
||||
|
||||
tx_swcx->is_paged_buf = 0;
|
||||
tx_swcx->flags &= ~OSI_PKT_CX_PAGED_BUF;
|
||||
tx_swcx->len = size;
|
||||
len -= size;
|
||||
offset += size;
|
||||
@@ -2118,7 +2126,7 @@ static int ether_tx_swcx_alloc(struct device *dev,
|
||||
ret = -ENOMEM;
|
||||
goto dma_map_failed;
|
||||
}
|
||||
tx_swcx->is_paged_buf = 1;
|
||||
tx_swcx->flags |= OSI_PKT_CX_PAGED_BUF;
|
||||
|
||||
tx_swcx->len = size;
|
||||
len -= size;
|
||||
@@ -2142,7 +2150,8 @@ dma_map_failed:
|
||||
DECR_TX_DESC_INDEX(cur_tx_idx, 1U);
|
||||
tx_swcx = tx_ring->tx_swcx + cur_tx_idx;
|
||||
if (tx_swcx->buf_phy_addr) {
|
||||
if (tx_swcx->is_paged_buf) {
|
||||
if ((tx_swcx->flags & OSI_PKT_CX_PAGED_BUF) ==
|
||||
OSI_PKT_CX_PAGED_BUF) {
|
||||
dma_unmap_page(dev, tx_swcx->buf_phy_addr,
|
||||
tx_swcx->len, DMA_TO_DEVICE);
|
||||
} else {
|
||||
@@ -2153,7 +2162,7 @@ dma_map_failed:
|
||||
}
|
||||
tx_swcx->len = 0;
|
||||
|
||||
tx_swcx->is_paged_buf = 0;
|
||||
tx_swcx->flags &= ~OSI_PKT_CX_PAGED_BUF;
|
||||
cnt--;
|
||||
}
|
||||
return ret;
|
||||
@@ -2229,7 +2238,7 @@ static int ether_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
struct osi_tx_ring *tx_ring = osi_dma->tx_ring[chan];
|
||||
int count = 0;
|
||||
|
||||
count = ether_tx_swcx_alloc(pdata->dev, tx_ring, skb);
|
||||
count = ether_tx_swcx_alloc(pdata, tx_ring, skb);
|
||||
if (count <= 0) {
|
||||
if (count == 0) {
|
||||
netif_stop_subqueue(ndev, qinx);
|
||||
|
||||
@@ -686,7 +686,9 @@ static int ether_get_ts_info(struct net_device *ndev,
|
||||
info->phc_index = ptp_clock_index(pdata->ptp_clock);
|
||||
}
|
||||
|
||||
info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
|
||||
info->tx_types = ((1 << HWTSTAMP_TX_OFF) |
|
||||
(1 << HWTSTAMP_TX_ON) |
|
||||
(1 << HWTSTAMP_TX_ONESTEP_SYNC));
|
||||
|
||||
info->rx_filters |= ((1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
|
||||
|
||||
@@ -302,6 +302,7 @@ int ether_handle_hwtstamp_ioctl(struct ether_priv_data *pdata,
|
||||
struct ifreq *ifr)
|
||||
{
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_dma_priv_data *osi_dma = pdata->osi_dma;
|
||||
struct hwtstamp_config config;
|
||||
unsigned int hwts_rx_en = 1;
|
||||
#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE
|
||||
@@ -335,6 +336,7 @@ int ether_handle_hwtstamp_ioctl(struct ether_priv_data *pdata,
|
||||
break;
|
||||
|
||||
case HWTSTAMP_TX_ON:
|
||||
case HWTSTAMP_TX_ONESTEP_SYNC:
|
||||
pdata->hwts_tx_en = OSI_ENABLE;
|
||||
break;
|
||||
|
||||
@@ -400,11 +402,25 @@ int ether_handle_hwtstamp_ioctl(struct ether_priv_data *pdata,
|
||||
|
||||
/* PTP v2/802.AS1, any layer, any kind of event packet */
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
osi_core->ptp_config.ptp_filter = OSI_MAC_TCR_SNAPTYPSEL_1 |
|
||||
OSI_MAC_TCR_TSIPV4ENA |
|
||||
osi_core->ptp_config.ptp_filter = OSI_MAC_TCR_TSIPV4ENA |
|
||||
OSI_MAC_TCR_TSIPV6ENA |
|
||||
OSI_MAC_TCR_TSVER2ENA |
|
||||
OSI_MAC_TCR_TSIPENA;
|
||||
|
||||
if ((osi_dma->ptp_flag & OSI_PTP_SYNC_ONESTEP) ==
|
||||
OSI_PTP_SYNC_ONESTEP) {
|
||||
osi_core->ptp_config.ptp_filter |=
|
||||
(OSI_MAC_TCR_TSEVENTENA |
|
||||
OSI_MAC_TCR_CSC);
|
||||
if ((osi_dma->ptp_flag & OSI_PTP_SYNC_MASTER) ==
|
||||
OSI_PTP_SYNC_MASTER) {
|
||||
osi_core->ptp_config.ptp_filter |=
|
||||
OSI_MAC_TCR_TSMASTERENA;
|
||||
}
|
||||
} else {
|
||||
osi_core->ptp_config.ptp_filter |=
|
||||
OSI_MAC_TCR_SNAPTYPSEL_1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* PTP v2/802.AS1, any layer, Sync packet */
|
||||
|
||||
@@ -37,7 +37,6 @@ static ssize_t ether_mac_loopback_show(struct device *dev,
|
||||
{
|
||||
struct net_device *ndev = (struct net_device *)dev_get_drvdata(dev);
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
(pdata->mac_loopback_mode == 1U) ?
|
||||
"enabled" : "disabled");
|
||||
@@ -122,11 +121,160 @@ static DEVICE_ATTR(mac_loopback, (S_IRUGO | S_IWUSR),
|
||||
ether_mac_loopback_show,
|
||||
ether_mac_loopback_store);
|
||||
|
||||
/**
|
||||
* @brief Shows the current setting of PTP mode
|
||||
*
|
||||
* Algorithm: Display the current PTP mode setting.
|
||||
*
|
||||
* @param[in] dev: Device data.
|
||||
* @param[in] attr: Device attribute
|
||||
* @param[in] buf: Buffer to store the current PTP mode
|
||||
*
|
||||
* @note MAC and PHY need to be initialized.
|
||||
*/
|
||||
static ssize_t ether_ptp_mode_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);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
((pdata->osi_dma->ptp_flag & OSI_PTP_SYNC_MASTER) ==
|
||||
OSI_PTP_SYNC_MASTER) ? "master" :
|
||||
((pdata->osi_dma->ptp_flag & OSI_PTP_SYNC_SLAVE) ==
|
||||
OSI_PTP_SYNC_SLAVE) ? "slave" : " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the user setting of PTP mode
|
||||
*
|
||||
* Algorithm: This is used to set the user mode settings of PTP mode
|
||||
* @param[in] dev: Device data.
|
||||
* @param[in] attr: Device attribute
|
||||
* @param[in] buf: Buffer which contains the user settings of PTP mode
|
||||
* @param[in] size: size of buffer
|
||||
*
|
||||
* @note MAC and PHY need to be initialized.
|
||||
*
|
||||
* @return size of buffer.
|
||||
*/
|
||||
static ssize_t ether_ptp_mode_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct net_device *ndev = (struct net_device *)dev_get_drvdata(dev);
|
||||
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 size;
|
||||
}
|
||||
|
||||
if (strncmp(buf, "master", 6) == 0U) {
|
||||
pdata->osi_dma->ptp_flag &= ~(OSI_PTP_SYNC_MASTER |
|
||||
OSI_PTP_SYNC_SLAVE);
|
||||
pdata->osi_dma->ptp_flag |= OSI_PTP_SYNC_MASTER;
|
||||
} else if (strncmp(buf, "slave", 5) == 0U) {
|
||||
pdata->osi_dma->ptp_flag &= ~(OSI_PTP_SYNC_MASTER |
|
||||
OSI_PTP_SYNC_SLAVE);
|
||||
pdata->osi_dma->ptp_flag |= OSI_PTP_SYNC_SLAVE;
|
||||
} else {
|
||||
dev_err(pdata->dev,
|
||||
"Invalid entry. Valid Entries are master or slave\n");
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sysfs attribute for PTP MODE
|
||||
*
|
||||
*/
|
||||
static DEVICE_ATTR(ptp_mode, (S_IRUGO | S_IWUSR),
|
||||
ether_ptp_mode_show,
|
||||
ether_ptp_mode_store);
|
||||
|
||||
/**
|
||||
* @brief Shows the current setting of PTP sync method
|
||||
*
|
||||
* Algorithm: Display the current PTP sync method.
|
||||
*
|
||||
* @param[in] dev: Device data.
|
||||
* @param[in] attr: Device attribute
|
||||
* @param[in] buf: Buffer to store the current ptp sync method
|
||||
*
|
||||
* @note MAC and PHY need to be initialized.
|
||||
*/
|
||||
static ssize_t ether_ptp_sync_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);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
((pdata->osi_dma->ptp_flag & OSI_PTP_SYNC_TWOSTEP) ==
|
||||
OSI_PTP_SYNC_TWOSTEP) ? "twostep" :
|
||||
((pdata->osi_dma->ptp_flag & OSI_PTP_SYNC_ONESTEP) ==
|
||||
OSI_PTP_SYNC_ONESTEP) ? "onestep" : " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the user setting of PTP sync method
|
||||
*
|
||||
* Algorithm: This is used to set the user mode settings of PTP sync method
|
||||
* @param[in] dev: Device data.
|
||||
* @param[in] attr: Device attribute
|
||||
* @param[in] buf: Buffer which contains the user settings of PTP sync method
|
||||
* @param[in] size: size of buffer
|
||||
*
|
||||
* @note MAC and PHY need to be initialized.
|
||||
*
|
||||
* @return size of buffer.
|
||||
*/
|
||||
static ssize_t ether_ptp_sync_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct net_device *ndev = (struct net_device *)dev_get_drvdata(dev);
|
||||
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 size;
|
||||
}
|
||||
|
||||
if (strncmp(buf, "onestep", 7) == 0U) {
|
||||
pdata->osi_dma->ptp_flag &= ~(OSI_PTP_SYNC_ONESTEP |
|
||||
OSI_PTP_SYNC_TWOSTEP);
|
||||
pdata->osi_dma->ptp_flag |= OSI_PTP_SYNC_ONESTEP;
|
||||
|
||||
} else if (strncmp(buf, "twostep", 7) == 0U) {
|
||||
pdata->osi_dma->ptp_flag &= ~(OSI_PTP_SYNC_ONESTEP |
|
||||
OSI_PTP_SYNC_TWOSTEP);
|
||||
pdata->osi_dma->ptp_flag |= OSI_PTP_SYNC_TWOSTEP;
|
||||
} else {
|
||||
dev_err(pdata->dev,
|
||||
"Invalid entry. Valid Entries are onestep or twostep\n");
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sysfs attribute for PTP sync method
|
||||
*
|
||||
*/
|
||||
static DEVICE_ATTR(ptp_sync, (S_IRUGO | S_IWUSR),
|
||||
ether_ptp_sync_show,
|
||||
ether_ptp_sync_store);
|
||||
|
||||
/**
|
||||
* @brief Attributes for nvethernet sysfs
|
||||
*/
|
||||
static struct attribute *ether_sysfs_attrs[] = {
|
||||
&dev_attr_mac_loopback.attr,
|
||||
&dev_attr_ptp_mode.attr,
|
||||
&dev_attr_ptp_sync.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user