diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c index 53c60071..87adfd14 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c @@ -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, diff --git a/drivers/net/ethernet/nvidia/nvethernet/ioctl.c b/drivers/net/ethernet/nvidia/nvethernet/ioctl.c index 712533d4..963f528d 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ioctl.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ioctl.c @@ -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); } diff --git a/drivers/net/ethernet/nvidia/nvethernet/ptp.c b/drivers/net/ethernet/nvidia/nvethernet/ptp.c index 4e9f1bab..8a570f99 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ptp.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ptp.c @@ -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,