diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c index f65c8de9..8b7bf7d5 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c @@ -2396,6 +2396,7 @@ static int ether_prepare_mc_list(struct net_device *dev, filter->dma_chan = 0x0; filter->addr_mask = OSI_AMASK_DISABLE; filter->src_dest = OSI_DA_MATCH; + filter->dma_chansel = osi_core->mc_dmasel; ret = osi_l2_filter(osi_core, filter); if (ret < 0) { dev_err(pdata->dev, "issue in creating mc list\n"); @@ -2513,7 +2514,7 @@ static int ether_prepare_uc_list(struct net_device *dev, * * @note MAC and PHY need to be initialized. */ -static void ether_set_rx_mode(struct net_device *dev) +void ether_set_rx_mode(struct net_device *dev) { struct ether_priv_data *pdata = netdev_priv(dev); struct osi_core_priv_data *osi_core = pdata->osi_core; @@ -2576,6 +2577,7 @@ static void ether_set_rx_mode(struct net_device *dev) filter.dma_chan = OSI_CHAN_ANY; filter.addr_mask = OSI_AMASK_DISABLE; filter.src_dest = OSI_DA_MATCH; + filter.dma_chansel = OSI_DISABLE; ret = osi_l2_filter(osi_core, &filter); if (ret < 0) { dev_err(pdata->dev, "Invalidating expired L2 filter failed\n"); @@ -3898,7 +3900,7 @@ static int ether_parse_dt(struct ether_priv_data *pdata) unsigned int tmp_value[OSI_MGBE_MAX_NUM_QUEUES]; struct device_node *np = dev->of_node; int ret = -EINVAL; - unsigned int i, mtlq, chan; + unsigned int i, mtlq, chan, bitmap; /* read ptp clock */ ret = of_property_read_u32(np, "nvidia,ptp_ref_clock_speed", @@ -4115,6 +4117,33 @@ static int ether_parse_dt(struct ether_priv_data *pdata) osi_core->dcs_en = OSI_DISABLE; } + /* Read XDCS input for DMA channels route */ + ret = of_property_read_u32(np, "nvidia,mc-dmasel", + &osi_core->mc_dmasel); + if (ret < 0) { + /* Disable Multiple DMA selection on DT read failure */ + osi_core->mc_dmasel = osi_dma->dma_chans[0]; + } else { + /* Validate MC DMA channel selection flags */ + bitmap = osi_core->mc_dmasel; + while (bitmap != 0U) { + chan = __builtin_ctz(bitmap); + for (i = 0; i < osi_dma->num_dma_chans; i++) { + if (osi_dma->dma_chans[i] == chan) { + /* channel is enabled */ + break; + } + } + if (i == osi_dma->num_dma_chans) { + /* Invalid MC DMA selection */ + dev_err(dev, "Invalid %d MC DMA selection\n", chan); + osi_core->mc_dmasel = osi_dma->dma_chans[0]; + break; + } + bitmap &= ~OSI_BIT(chan); + } + } + /* Read MAX MTU size supported */ ret = of_property_read_u32(np, "nvidia,max-platform-mtu", &pdata->max_platform_mtu); diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h index 5a536257..630892d3 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h @@ -516,7 +516,7 @@ void ether_assign_osd_ops(struct osi_core_priv_data *osi_core, struct osi_dma_priv_data *osi_dma); /** - * @brief osd_send_cmd - OSD ivc send cmd + * @brief osd_ivc_send_cmd - OSD ivc send cmd * * @param[in] priv: OSD private data * @param[in] func: data @@ -528,4 +528,5 @@ void ether_assign_osd_ops(struct osi_core_priv_data *osi_core, * - De-initialization: Yes */ int osd_ivc_send_cmd(void *priv, void *data, unsigned int len); +void ether_set_rx_mode(struct net_device *dev); #endif /* ETHER_LINUX_H */ diff --git a/drivers/net/ethernet/nvidia/nvethernet/ioctl.c b/drivers/net/ethernet/nvidia/nvethernet/ioctl.c index 3cfbb36c..27aa0ed1 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ioctl.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ioctl.c @@ -553,6 +553,52 @@ static int ether_config_vlan_filter(struct net_device *dev, return ret; } +/** + * @brief This function is invoked by ioctl function when user issues an ioctl + * command to configure multiple DMA routing for MC packets. + * + * @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_mc_dmasel(struct net_device *dev, + unsigned int flags) +{ + struct ether_priv_data *pdata = netdev_priv(dev); + struct osi_core_priv_data *osi_core = pdata->osi_core; + struct osi_dma_priv_data *osi_dma = pdata->osi_dma; + unsigned int bitmap = 0U, i = 0U, chan = 0U; + + /* Validate MC DMA channel selection flags */ + bitmap = flags; + while (bitmap != 0U) { + chan = __builtin_ctz(bitmap); + for (i = 0; i < osi_dma->num_dma_chans; i++) { + if (osi_dma->dma_chans[i] == chan) { + /* channel is enabled */ + break; + } + } + if (i == osi_dma->num_dma_chans) { + /* Invalid MC DMA selection */ + dev_err(pdata->dev, "Invalid %d MC DMA selection\n", chan); + return -EINVAL; + } + bitmap &= ~OSI_BIT(chan); + } + + /* Store flags into OSI core data */ + osi_core->mc_dmasel = flags; + /* Set RX mode with latest flags */ + ether_set_rx_mode(dev); + + return 0; +} + /** * @brief This function is invoked by ioctl function when user issues an ioctl * command to configure L2 destination addressing filtering mode. @@ -975,6 +1021,9 @@ int ether_handle_priv_ioctl(struct net_device *ndev, case EQOS_L2_DA_FILTERING_CMD: ret = ether_config_l2_da_filter(ndev, &ifdata); break; + case ETHER_MC_DMA_ROUTE: + ret = ether_config_mc_dmasel(ndev, ifdata.if_flags); + break; case ETHER_CONFIG_LOOPBACK_MODE: ret = ether_config_loopback_mode(ndev, ifdata.if_flags); break; diff --git a/drivers/net/ethernet/nvidia/nvethernet/ioctl.h b/drivers/net/ethernet/nvidia/nvethernet/ioctl.h index a469ffd9..b9c4d383 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ioctl.h +++ b/drivers/net/ethernet/nvidia/nvethernet/ioctl.h @@ -60,6 +60,7 @@ #define ETHER_CONFIG_FPE 50 /* FRP Command */ #define ETHER_CONFIG_FRP_CMD 51 +#define ETHER_MC_DMA_ROUTE 52 /** @} */ /**