nvethernet: Enable slot function support

Issue:
Data packets sent via EQOS hardware are not
following any packet gaping. The AVB use-cases
have different timing requirements for class A
data packets. For example, the time difference
between two class A data packets are supposed
to be 125 microseconds for audio data
of frequency 48 kHz.

Fix:
Enable slot function support to schedule the data
fetching from the system memory by the DMA.
This feature is useful when the source AV data
needs to be transmitted at specific intervals.

Bug 200545374

Change-Id: I549014998380cd6c0d161c778bccdaa5ed017129
Signed-off-by: Mohan Thadikamalla <mohant@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2223850
Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Mohan Thadikamalla
2019-10-23 10:00:03 +05:30
committed by Revanth Kumar Uppala
parent 12328b2c5a
commit ae038d9360
3 changed files with 96 additions and 1 deletions

View File

@@ -3052,7 +3052,7 @@ static int ether_parse_dt(struct ether_priv_data *pdata)
unsigned int tmp_value[OSI_EQOS_MAX_NUM_QUEUES];
struct device_node *np = dev->of_node;
int ret = -EINVAL;
unsigned int i, mtlq;
unsigned int i, mtlq, chan;
/* read ptp clock */
ret = of_property_read_u32(np, "nvidia,ptp_ref_clock_speed",
@@ -3148,6 +3148,41 @@ static int ether_parse_dt(struct ether_priv_data *pdata)
ETHER_QUEUE_PRIO_DEFAULT, ETHER_QUEUE_PRIO_MAX,
osi_core->num_mtl_queues);
/* Read TX slot enable check array DT node */
ret = of_property_read_u32_array(np, "nvidia,slot_num_check",
tmp_value,
osi_dma->num_dma_chans);
if (ret < 0) {
dev_info(dev,
"Failed to read slot_num_check, disabling slot\n");
for (i = 0; i < osi_dma->num_dma_chans; i++)
osi_dma->slot_enabled[i] = OSI_DISABLE;
} else {
/* Set slot enable flags */
for (i = 0; i < osi_dma->num_dma_chans; i++) {
chan = osi_dma->dma_chans[i];
osi_dma->slot_enabled[chan] = tmp_value[i];
}
/* Read TX slot intervals DT node */
ret = of_property_read_u32_array(np, "nvidia,slot_intvl_vals",
tmp_value,
osi_dma->num_dma_chans);
if (ret < 0) {
for (i = 0; i < osi_dma->num_dma_chans; i++) {
chan = osi_dma->dma_chans[i];
osi_dma->slot_interval[chan] =
OSI_SLOT_INTVL_DEFAULT;
}
} else {
/* Copy slot intervals */
for (i = 0; i < osi_dma->num_dma_chans; i++) {
chan = osi_dma->dma_chans[i];
osi_dma->slot_interval[chan] = tmp_value[i];
}
}
}
/* Read Rx Queue - User priority mapping for tagged packets */
ret = of_property_read_u32_array(np, "nvidia,rx-queue-prio",
tmp_value,

View File

@@ -35,6 +35,8 @@ static int ether_set_avb_algo(struct net_device *ndev,
struct ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_core_avb_algorithm l_avb_struct;
struct osi_dma_priv_data *osi_dma = pdata->osi_dma;
struct osi_tx_ring *tx_ring = NULL;
int ret = -1;
if (ifdata->ptr == NULL) {
@@ -51,6 +53,16 @@ static int ether_set_avb_algo(struct net_device *ndev,
return ret;
}
/* Check AVB mode disable on slot function enable */
tx_ring = osi_dma->tx_ring[l_avb_struct.qindex];
if (tx_ring && tx_ring->slot_check == OSI_ENABLE &&
l_avb_struct.oper_mode == OSI_MTL_QUEUE_ENABLE) {
dev_err(pdata->dev,
"Can't disable queue:%d AVB mode when slot is enabled",
l_avb_struct.qindex);
return -EINVAL;
}
return osi_set_avb(osi_core, &l_avb_struct);
}

View File

@@ -241,6 +241,52 @@ void ether_ptp_remove(struct ether_priv_data *pdata)
}
}
/**
* @brief Configure Slot function
*
* Algorithm: This function will set/reset slot funciton
*
* @param[in] pdata: Pointer to private data structure.
* @param[in] set: Flag to set or reset the Slot function.
*
* @note PTP clock driver need to be successfully registered during
* initialization and HW need to support PTP functionality.
*
* @retval none
*/
static void ether_config_slot_function(struct ether_priv_data *pdata, u32 set)
{
struct osi_dma_priv_data *osi_dma = pdata->osi_dma;
struct osi_core_priv_data *osi_core = pdata->osi_core;
unsigned int ret, i, chan, qinx;
struct osi_core_avb_algorithm avb;
/* Configure TXQ AVB mode */
for (i = 0; i < osi_dma->num_dma_chans; i++) {
chan = osi_dma->dma_chans[i];
if (osi_dma->slot_enabled[chan] == OSI_ENABLE) {
/* Set TXQ AVB info */
memset(&avb, 0, sizeof(struct osi_core_avb_algorithm));
qinx = osi_core->mtl_queues[i];
avb.qindex = qinx;
avb.algo = OSI_MTL_TXQ_AVALG_SP;
avb.oper_mode = (set == OSI_ENABLE) ?
OSI_MTL_QUEUE_AVB :
OSI_MTL_QUEUE_ENABLE;
ret = osi_set_avb(osi_core, &avb);
if (ret != 0) {
dev_err(pdata->dev,
"Failed to set TXQ:%d AVB info\n",
qinx);
return;
}
}
}
/* Call OSI slot function to configure */
osi_config_slot_function(osi_dma, set);
}
int ether_handle_hwtstamp_ioctl(struct ether_priv_data *pdata,
struct ifreq *ifr)
{
@@ -380,6 +426,7 @@ int ether_handle_hwtstamp_ioctl(struct ether_priv_data *pdata,
if (!pdata->hwts_tx_en && !hwts_rx_en) {
/* disable the PTP configuration */
osi_ptp_configuration(osi_core, OSI_DISABLE);
ether_config_slot_function(pdata, OSI_DISABLE);
} else {
/* Store SYS CLOCK */
osi_core->ptp_config.ptp_clock = OSI_ETHER_SYSCLOCK;
@@ -396,6 +443,7 @@ int ether_handle_hwtstamp_ioctl(struct ether_priv_data *pdata,
/* Register broadcasting MAC timestamp to clients */
tegra_register_hwtime_source(ether_get_ptptime, pdata);
#endif
ether_config_slot_function(pdata, OSI_ENABLE);
}
return (copy_to_user(ifr->ifr_data, &config,