mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 02:01:36 +03:00
nvethernet: use single API for ioctl
To reduce number of external OSI interface APIs, consolidated all IOCTL API to one interface API. OSD should use same for all interaction to OSI. Bug 200671160 Change-Id: I05324777c9bd7ed3c167e4f8a629af2e695389d2 Signed-off-by: rakesh goyal <rgoyal@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2493248 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Revanth Kumar Uppala
parent
71fa042ce4
commit
f4d30eb89b
@@ -34,9 +34,11 @@ static inline void ether_stats_work_func(struct work_struct *work)
|
||||
struct ether_priv_data *pdata = container_of(dwork,
|
||||
struct ether_priv_data, ether_stats_work);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret;
|
||||
|
||||
ret = osi_read_mmc(osi_core);
|
||||
ioctl_data.cmd = OSI_CMD_READ_MMC;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "failed to read MMC counters %s\n",
|
||||
__func__);
|
||||
@@ -240,6 +242,7 @@ int ether_conf_eee(struct ether_priv_data *pdata, unsigned int tx_lpi_enable)
|
||||
int ret = 0;
|
||||
struct phy_device *phydev = pdata->phydev;
|
||||
unsigned int enable = tx_lpi_enable;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
|
||||
if (tx_lpi_enable) {
|
||||
/* phy_init_eee() returns 0 if EEE is supported by the PHY */
|
||||
@@ -253,9 +256,11 @@ int ether_conf_eee(struct ether_priv_data *pdata, unsigned int tx_lpi_enable)
|
||||
}
|
||||
|
||||
/* Enable EEE */
|
||||
ret = osi_configure_eee(pdata->osi_core,
|
||||
enable,
|
||||
pdata->tx_lpi_timer);
|
||||
ioctl_data.cmd = OSI_CMD_CONFIG_EEE;
|
||||
ioctl_data.arg1_u32 = enable;
|
||||
ioctl_data.arg2_u32 = pdata->tx_lpi_timer;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
|
||||
/* Return current status of EEE based on OSI API success/failure */
|
||||
if (ret != 0) {
|
||||
if (enable) {
|
||||
@@ -291,6 +296,7 @@ static void ether_adjust_link(struct net_device *dev)
|
||||
int new_state = 0, speed_changed = 0;
|
||||
unsigned long val;
|
||||
unsigned int eee_enable = OSI_DISABLE;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = 0;
|
||||
|
||||
if (phydev == NULL) {
|
||||
@@ -300,20 +306,33 @@ static void ether_adjust_link(struct net_device *dev)
|
||||
if (phydev->link) {
|
||||
if ((pdata->osi_core->pause_frames == OSI_PAUSE_FRAMES_ENABLE)
|
||||
&& (phydev->pause || phydev->asym_pause)) {
|
||||
osi_configure_flow_control(pdata->osi_core,
|
||||
pdata->osi_core->flow_ctrl);
|
||||
ioctl_data.cmd = OSI_CMD_FLOW_CTRL;
|
||||
ioctl_data.arg1_u32 = pdata->osi_core->flow_ctrl;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev, "Failed to set pause frame\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (phydev->duplex != pdata->oldduplex) {
|
||||
new_state = 1;
|
||||
osi_set_mode(pdata->osi_core, phydev->duplex);
|
||||
ioctl_data.cmd = OSI_CMD_SET_MODE;
|
||||
ioctl_data.arg6_32 = phydev->duplex;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev, "Failed to set mode\n");
|
||||
return;
|
||||
}
|
||||
pdata->oldduplex = phydev->duplex;
|
||||
}
|
||||
|
||||
if (phydev->speed != pdata->speed) {
|
||||
new_state = 1;
|
||||
speed_changed = 1;
|
||||
ret = osi_set_speed(pdata->osi_core, phydev->speed);
|
||||
ioctl_data.cmd = OSI_CMD_SET_SPEED;
|
||||
ioctl_data.arg6_32 = phydev->speed;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
netdev_err(dev, "Failed to set speed\n");
|
||||
return;
|
||||
@@ -351,11 +370,14 @@ static void ether_adjust_link(struct net_device *dev)
|
||||
(phydev->speed ==
|
||||
SPEED_100) ? 25000 * 1000 : 125000 * 1000);
|
||||
if (phydev->speed != SPEED_10) {
|
||||
if (osi_pad_calibrate(pdata->osi_core) < 0)
|
||||
ioctl_data.cmd = OSI_CMD_PAD_CALIBRATION;
|
||||
if (osi_handle_ioctl(pdata->osi_core, &ioctl_data) <
|
||||
0) {
|
||||
dev_err(pdata->dev,
|
||||
"failed to do pad caliberation\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure EEE if it is enabled */
|
||||
if (pdata->eee_enabled && pdata->tx_lpi_enabled) {
|
||||
@@ -625,8 +647,15 @@ static irqreturn_t ether_rx_chan_isr(int irq, void *data)
|
||||
static irqreturn_t ether_common_isr(int irq, void *data)
|
||||
{
|
||||
struct ether_priv_data *pdata = (struct ether_priv_data *)data;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret;
|
||||
|
||||
osi_common_isr(pdata->osi_core);
|
||||
ioctl_data.cmd = OSI_CMD_COMMON_ISR;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev,
|
||||
"%s() failure in handling ISR\n", __func__);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1507,6 +1536,8 @@ static int ether_set_cur_therm_state(struct thermal_cooling_device *tcd,
|
||||
{
|
||||
struct ether_priv_data *pdata = tcd->devdata;
|
||||
struct device *dev = pdata->dev;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
|
||||
|
||||
/* Thermal framework will take care of making sure state is within
|
||||
* valid bounds, based on the get_max_state callback. So no need
|
||||
@@ -1517,7 +1548,8 @@ static int ether_set_cur_therm_state(struct thermal_cooling_device *tcd,
|
||||
|
||||
atomic_set(&pdata->therm_state, state);
|
||||
|
||||
if (osi_pad_calibrate(pdata->osi_core) < 0) {
|
||||
ioctl_data.cmd = OSI_CMD_PAD_CALIBRATION;
|
||||
if (osi_handle_ioctl(pdata->osi_core, &ioctl_data) < 0) {
|
||||
dev_err(dev, "Therm state changed, failed pad calibration\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1616,6 +1648,7 @@ static int ether_open(struct net_device *dev)
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(dev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = 0;
|
||||
|
||||
/* Reset the PHY */
|
||||
@@ -1641,7 +1674,8 @@ static int ether_open(struct net_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
ret = osi_poll_for_mac_reset_complete(osi_core);
|
||||
ioctl_data.cmd = OSI_CMD_POLL_FOR_MAC_RST;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->dev, "failed to poll MAC Software reset\n");
|
||||
goto err_poll_swr;
|
||||
@@ -1723,8 +1757,14 @@ static int ether_open(struct net_device *dev)
|
||||
ether_init_eee_params(pdata);
|
||||
|
||||
/* Start the MAC */
|
||||
osi_start_mac(pdata->osi_core);
|
||||
|
||||
ioctl_data.cmd = OSI_CMD_START_MAC;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->dev,
|
||||
"%s: failed to start MAC %d\n",
|
||||
__func__, ret);
|
||||
goto err_r_irq;
|
||||
}
|
||||
/* start PHY */
|
||||
phy_start(pdata->phydev);
|
||||
|
||||
@@ -2269,7 +2309,7 @@ static int ether_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
* @retval "negative value" on failure.
|
||||
*/
|
||||
static int ether_prepare_mc_list(struct net_device *dev,
|
||||
struct osi_filter *filter)
|
||||
struct osi_ioctl *ioctl_data)
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(dev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
@@ -2277,38 +2317,39 @@ static int ether_prepare_mc_list(struct net_device *dev,
|
||||
unsigned int i = 1;
|
||||
int ret = -1;
|
||||
|
||||
if (filter == NULL) {
|
||||
dev_err(pdata->dev, "filter is NULL\n");
|
||||
if (ioctl_data == NULL) {
|
||||
dev_err(pdata->dev, "ioctl_data is NULL\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(filter, 0x0, sizeof(struct osi_filter));
|
||||
memset(&ioctl_data->l2_filter, 0x0, sizeof(struct osi_filter));
|
||||
|
||||
if (pdata->l2_filtering_mode == OSI_HASH_FILTER_MODE) {
|
||||
dev_err(pdata->dev,
|
||||
"HASH FILTERING for mc addresses not Supported in SW\n");
|
||||
filter->oper_mode = (OSI_OPER_EN_PERFECT |
|
||||
ioctl_data->l2_filter.oper_mode = (OSI_OPER_EN_PERFECT |
|
||||
OSI_OPER_DIS_PROMISC |
|
||||
OSI_OPER_DIS_ALLMULTI);
|
||||
|
||||
return osi_l2_filter(osi_core, filter);
|
||||
ioctl_data->cmd = OSI_CMD_L2_FILTER;
|
||||
return osi_handle_ioctl(osi_core, ioctl_data);
|
||||
/* address 0 is used for DUT DA so compare with
|
||||
* pdata->num_mac_addr_regs - 1
|
||||
*/
|
||||
} else if (netdev_mc_count(dev) > (pdata->num_mac_addr_regs - 1)) {
|
||||
/* switch to PROMISCUOUS mode */
|
||||
filter->oper_mode = (OSI_OPER_DIS_PERFECT |
|
||||
ioctl_data->l2_filter.oper_mode = (OSI_OPER_DIS_PERFECT |
|
||||
OSI_OPER_EN_PROMISC |
|
||||
OSI_OPER_DIS_ALLMULTI);
|
||||
dev_dbg(pdata->dev, "enabling Promiscuous mode\n");
|
||||
|
||||
return osi_l2_filter(osi_core, filter);
|
||||
ioctl_data->cmd = OSI_CMD_L2_FILTER;
|
||||
return osi_handle_ioctl(osi_core, ioctl_data);
|
||||
} else {
|
||||
dev_dbg(pdata->dev,
|
||||
"select PERFECT FILTERING for mc addresses, mc_count = %d, num_mac_addr_regs = %d\n",
|
||||
netdev_mc_count(dev), pdata->num_mac_addr_regs);
|
||||
|
||||
filter->oper_mode = (OSI_OPER_EN_PERFECT |
|
||||
ioctl_data->l2_filter.oper_mode = (OSI_OPER_EN_PERFECT |
|
||||
OSI_OPER_ADDR_UPDATE |
|
||||
OSI_OPER_DIS_PROMISC |
|
||||
OSI_OPER_DIS_ALLMULTI);
|
||||
@@ -2317,13 +2358,15 @@ static int ether_prepare_mc_list(struct net_device *dev,
|
||||
"mc addr[%d] = %#x:%#x:%#x:%#x:%#x:%#x\n",
|
||||
i, ha->addr[0], ha->addr[1], ha->addr[2],
|
||||
ha->addr[3], ha->addr[4], ha->addr[5]);
|
||||
filter->index = i;
|
||||
memcpy(filter->mac_address, ha->addr, ETH_ALEN);
|
||||
filter->dma_routing = OSI_DISABLE;
|
||||
filter->dma_chan = 0x0;
|
||||
filter->addr_mask = OSI_AMASK_DISABLE;
|
||||
filter->src_dest = OSI_DA_MATCH;
|
||||
ret = osi_l2_filter(osi_core, filter);
|
||||
ioctl_data->l2_filter.index = i;
|
||||
memcpy(ioctl_data->l2_filter.mac_address, ha->addr,
|
||||
ETH_ALEN);
|
||||
ioctl_data->l2_filter.dma_routing = OSI_DISABLE;
|
||||
ioctl_data->l2_filter.dma_chan = 0x0;
|
||||
ioctl_data->l2_filter.addr_mask = OSI_AMASK_DISABLE;
|
||||
ioctl_data->l2_filter.src_dest = OSI_DA_MATCH;
|
||||
ioctl_data->cmd = OSI_CMD_L2_FILTER;
|
||||
ret = osi_handle_ioctl(osi_core, ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "issue in creating mc list\n");
|
||||
pdata->last_filter_index = i - 1;
|
||||
@@ -2358,7 +2401,7 @@ static int ether_prepare_mc_list(struct net_device *dev,
|
||||
* @retval "negative value" on failure.
|
||||
*/
|
||||
static int ether_prepare_uc_list(struct net_device *dev,
|
||||
struct osi_filter *filter)
|
||||
struct osi_ioctl *ioctl_data)
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(dev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
@@ -2367,36 +2410,36 @@ static int ether_prepare_uc_list(struct net_device *dev,
|
||||
struct netdev_hw_addr *ha;
|
||||
int ret = -1;
|
||||
|
||||
if (filter == NULL) {
|
||||
dev_err(pdata->dev, "filter is NULL\n");
|
||||
if (ioctl_data == NULL) {
|
||||
dev_err(pdata->dev, "ioctl_data is NULL\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(filter, 0x0, sizeof(struct osi_filter));
|
||||
memset(&ioctl_data->l2_filter, 0x0, sizeof(struct osi_filter));
|
||||
|
||||
if (pdata->l2_filtering_mode == OSI_HASH_FILTER_MODE) {
|
||||
dev_err(pdata->dev,
|
||||
"HASH FILTERING for uc addresses not Supported in SW\n");
|
||||
/* Perfect filtering for multicast */
|
||||
filter->oper_mode = (OSI_OPER_EN_PERFECT |
|
||||
ioctl_data->l2_filter.oper_mode = (OSI_OPER_EN_PERFECT |
|
||||
OSI_OPER_DIS_PROMISC |
|
||||
OSI_OPER_DIS_ALLMULTI);
|
||||
|
||||
return osi_l2_filter(osi_core, filter);
|
||||
ioctl_data->cmd = OSI_CMD_L2_FILTER;
|
||||
return osi_handle_ioctl(osi_core, ioctl_data);
|
||||
} else if (netdev_uc_count(dev) > (pdata->num_mac_addr_regs - i)) {
|
||||
/* switch to PROMISCUOUS mode */
|
||||
filter->oper_mode = (OSI_OPER_DIS_PERFECT |
|
||||
ioctl_data->l2_filter.oper_mode = (OSI_OPER_DIS_PERFECT |
|
||||
OSI_OPER_EN_PROMISC |
|
||||
OSI_OPER_DIS_ALLMULTI);
|
||||
dev_dbg(pdata->dev, "enabling Promiscuous mode\n");
|
||||
|
||||
return osi_l2_filter(osi_core, filter);
|
||||
ioctl_data->cmd = OSI_CMD_L2_FILTER;
|
||||
return osi_handle_ioctl(osi_core, ioctl_data);
|
||||
} else {
|
||||
dev_dbg(pdata->dev,
|
||||
"select PERFECT FILTERING for uc addresses: uc_count = %d\n",
|
||||
netdev_uc_count(dev));
|
||||
|
||||
filter->oper_mode = (OSI_OPER_EN_PERFECT |
|
||||
ioctl_data->l2_filter.oper_mode = (OSI_OPER_EN_PERFECT |
|
||||
OSI_OPER_ADDR_UPDATE |
|
||||
OSI_OPER_DIS_PROMISC |
|
||||
OSI_OPER_DIS_ALLMULTI);
|
||||
@@ -2405,13 +2448,16 @@ static int ether_prepare_uc_list(struct net_device *dev,
|
||||
"uc addr[%d] = %#x:%#x:%#x:%#x:%#x:%#x\n",
|
||||
i, ha->addr[0], ha->addr[1], ha->addr[2],
|
||||
ha->addr[3], ha->addr[4], ha->addr[5]);
|
||||
filter->index = i;
|
||||
memcpy(filter->mac_address, ha->addr, ETH_ALEN);
|
||||
filter->dma_routing = OSI_DISABLE;
|
||||
filter->dma_chan = 0x0;
|
||||
filter->addr_mask = OSI_AMASK_DISABLE;
|
||||
filter->src_dest = OSI_DA_MATCH;
|
||||
ret = osi_l2_filter(osi_core, filter);
|
||||
ioctl_data->l2_filter.index = i;
|
||||
memcpy(ioctl_data->l2_filter.mac_address, ha->addr,
|
||||
ETH_ALEN);
|
||||
ioctl_data->l2_filter.dma_routing = OSI_DISABLE;
|
||||
ioctl_data->l2_filter.dma_chan = 0x0;
|
||||
ioctl_data->l2_filter.addr_mask = OSI_AMASK_DISABLE;
|
||||
ioctl_data->l2_filter.src_dest = OSI_DA_MATCH;
|
||||
|
||||
ioctl_data->cmd = OSI_CMD_L2_FILTER;
|
||||
ret = osi_handle_ioctl(osi_core, ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "issue in creating uc list\n");
|
||||
pdata->last_filter_index = i - 1;
|
||||
@@ -2444,20 +2490,23 @@ static 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;
|
||||
struct osi_filter filter;
|
||||
/* store last call last_uc_filter_index in temporary variable */
|
||||
int last_index = pdata->last_filter_index;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
|
||||
int ret = -1;
|
||||
unsigned int i = 0;
|
||||
|
||||
memset(&filter, 0x0, sizeof(struct osi_filter));
|
||||
memset(&ioctl_data.l2_filter, 0x0, sizeof(struct osi_filter));
|
||||
if ((dev->flags & IFF_PROMISC) == IFF_PROMISC) {
|
||||
if (pdata->promisc_mode == OSI_ENABLE) {
|
||||
filter.oper_mode = (OSI_OPER_DIS_PERFECT |
|
||||
ioctl_data.l2_filter.oper_mode =
|
||||
(OSI_OPER_DIS_PERFECT |
|
||||
OSI_OPER_EN_PROMISC |
|
||||
OSI_OPER_DIS_ALLMULTI);
|
||||
dev_dbg(pdata->dev, "enabling Promiscuous mode\n");
|
||||
ret = osi_l2_filter(osi_core, &filter);
|
||||
ioctl_data.cmd = OSI_CMD_L2_FILTER;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev,
|
||||
"Setting Promiscuous mode failed\n");
|
||||
@@ -2469,18 +2518,19 @@ static void ether_set_rx_mode(struct net_device *dev)
|
||||
|
||||
return;
|
||||
} else if ((dev->flags & IFF_ALLMULTI) == IFF_ALLMULTI) {
|
||||
filter.oper_mode = (OSI_OPER_EN_ALLMULTI |
|
||||
ioctl_data.l2_filter.oper_mode = (OSI_OPER_EN_ALLMULTI |
|
||||
OSI_OPER_DIS_PERFECT |
|
||||
OSI_OPER_DIS_PROMISC);
|
||||
dev_dbg(pdata->dev, "pass all multicast pkt\n");
|
||||
ret = osi_l2_filter(osi_core, &filter);
|
||||
ioctl_data.cmd = OSI_CMD_L2_FILTER;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "Setting All Multicast allow mode failed\n");
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (!netdev_mc_empty(dev)) {
|
||||
if (ether_prepare_mc_list(dev, &filter) != 0) {
|
||||
if (ether_prepare_mc_list(dev, &ioctl_data) != 0) {
|
||||
dev_err(pdata->dev, "Setting MC address failed\n");
|
||||
}
|
||||
} else {
|
||||
@@ -2488,22 +2538,23 @@ static void ether_set_rx_mode(struct net_device *dev)
|
||||
}
|
||||
|
||||
if (!netdev_uc_empty(dev)) {
|
||||
if (ether_prepare_uc_list(dev, &filter) != 0) {
|
||||
if (ether_prepare_uc_list(dev, &ioctl_data) != 0) {
|
||||
dev_err(pdata->dev, "Setting UC address failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the filter structure to avoid any old value */
|
||||
memset(&filter, 0x0, sizeof(struct osi_filter));
|
||||
memset(&ioctl_data.l2_filter, 0x0, sizeof(struct osi_filter));
|
||||
/* invalidate remaining ealier address */
|
||||
for (i = pdata->last_filter_index + 1; i <= last_index; i++) {
|
||||
filter.oper_mode = OSI_OPER_ADDR_UPDATE;
|
||||
filter.index = i;
|
||||
filter.dma_routing = OSI_DISABLE;
|
||||
filter.dma_chan = OSI_CHAN_ANY;
|
||||
filter.addr_mask = OSI_AMASK_DISABLE;
|
||||
filter.src_dest = OSI_DA_MATCH;
|
||||
ret = osi_l2_filter(osi_core, &filter);
|
||||
ioctl_data.l2_filter.oper_mode = OSI_OPER_ADDR_DEL;
|
||||
ioctl_data.l2_filter.index = i;
|
||||
ioctl_data.l2_filter.dma_routing = OSI_DISABLE;
|
||||
ioctl_data.l2_filter.dma_chan = OSI_CHAN_ANY;
|
||||
ioctl_data.l2_filter.addr_mask = OSI_AMASK_DISABLE;
|
||||
ioctl_data.l2_filter.src_dest = OSI_DA_MATCH;
|
||||
ioctl_data.cmd = OSI_CMD_L2_FILTER;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "Invalidating expired L2 filter failed\n");
|
||||
return;
|
||||
@@ -2675,6 +2726,7 @@ static int ether_set_features(struct net_device *ndev, netdev_features_t feat)
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
netdev_features_t hw_feat_cur_state = pdata->hw_feat_cur_state;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
|
||||
if (pdata->hw_feat.rx_coe_sel == 0U) {
|
||||
return ret;
|
||||
@@ -2682,16 +2734,18 @@ static int ether_set_features(struct net_device *ndev, netdev_features_t feat)
|
||||
|
||||
if ((feat & NETIF_F_RXCSUM) == NETIF_F_RXCSUM) {
|
||||
if (!(hw_feat_cur_state & NETIF_F_RXCSUM)) {
|
||||
ret = osi_config_rxcsum_offload(osi_core,
|
||||
OSI_ENABLE);
|
||||
ioctl_data.cmd = OSI_CMD_RXCSUM_OFFLOAD;
|
||||
ioctl_data.arg1_u32 = OSI_ENABLE;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
dev_info(pdata->dev, "Rx Csum offload: Enable: %s\n",
|
||||
ret ? "Failed" : "Success");
|
||||
pdata->hw_feat_cur_state |= NETIF_F_RXCSUM;
|
||||
}
|
||||
} else {
|
||||
if ((hw_feat_cur_state & NETIF_F_RXCSUM)) {
|
||||
ret = osi_config_rxcsum_offload(osi_core,
|
||||
OSI_DISABLE);
|
||||
ioctl_data.cmd = OSI_CMD_RXCSUM_OFFLOAD;
|
||||
ioctl_data.arg1_u32 = OSI_DISABLE;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
dev_info(pdata->dev, "Rx Csum offload: Disable: %s\n",
|
||||
ret ? "Failed" : "Success");
|
||||
pdata->hw_feat_cur_state &= ~NETIF_F_RXCSUM;
|
||||
@@ -2725,13 +2779,16 @@ static int ether_vlan_rx_add_vid(struct net_device *ndev, __be16 vlan_proto,
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = -1;
|
||||
|
||||
if (pdata->vlan_hash_filtering == OSI_HASH_FILTER_MODE) {
|
||||
dev_err(pdata->dev,
|
||||
"HASH FILTERING for VLAN tag is not supported in SW\n");
|
||||
} else {
|
||||
ret = osi_update_vlan_id(osi_core, vid);
|
||||
ioctl_data.cmd = OSI_CMD_UPDATE_VLAN_ID;
|
||||
ioctl_data.arg1_u32 = vid;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -2761,6 +2818,7 @@ static int ether_vlan_rx_kill_vid(struct net_device *ndev, __be16 vlan_proto,
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = -1;
|
||||
|
||||
if (!netif_running(ndev)) {
|
||||
@@ -2771,10 +2829,12 @@ static int ether_vlan_rx_kill_vid(struct net_device *ndev, __be16 vlan_proto,
|
||||
dev_err(pdata->dev,
|
||||
"HASH FILTERING for VLAN tag is not supported in SW\n");
|
||||
} else {
|
||||
ioctl_data.cmd = OSI_CMD_UPDATE_VLAN_ID;
|
||||
/* By default, receive only VLAN pkt with VID = 1 because
|
||||
* writing 0 will pass all VLAN pkt
|
||||
*/
|
||||
ret = osi_update_vlan_id(osi_core, 0x1U);
|
||||
ioctl_data.arg1_u32 = 0x1U;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -3497,6 +3557,7 @@ static int ether_configure_car(struct platform_device *pdev,
|
||||
struct device_node *np = dev->of_node;
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
unsigned long csr_clk_rate = 0;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = 0;
|
||||
|
||||
if (osi_core->pre_si) {
|
||||
@@ -3566,10 +3627,19 @@ static int ether_configure_car(struct platform_device *pdev,
|
||||
}
|
||||
|
||||
csr_clk_rate = clk_get_rate(pdata->axi_cbb_clk);
|
||||
osi_set_mdc_clk_rate(pdata->osi_core, csr_clk_rate);
|
||||
ioctl_data.cmd = OSI_CMD_MDC_CONFIG;
|
||||
ioctl_data.arg5_u64 = csr_clk_rate;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to configure MDC\n");
|
||||
goto err_mdc;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err_mdc:
|
||||
if (pdata->mac_rst) {
|
||||
reset_control_assert(pdata->mac_rst);
|
||||
}
|
||||
err_rst:
|
||||
ether_disable_clks(pdata);
|
||||
err_enable_clks:
|
||||
@@ -4244,6 +4314,7 @@ static int ether_probe(struct platform_device *pdev)
|
||||
unsigned int num_dma_chans, mac, num_mtl_queues, chan;
|
||||
struct osi_core_priv_data *osi_core;
|
||||
struct osi_dma_priv_data *osi_dma;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
struct net_device *ndev;
|
||||
int ret = 0, i;
|
||||
|
||||
@@ -4320,18 +4391,23 @@ static int ether_probe(struct platform_device *pdev)
|
||||
goto err_init_res;
|
||||
}
|
||||
|
||||
ret = osi_get_mac_version(osi_core, &osi_core->mac_ver);
|
||||
ioctl_data.cmd = OSI_CMD_GET_MAC_VER;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to get MAC version (%u)\n",
|
||||
osi_core->mac_ver);
|
||||
goto err_dma_mask;
|
||||
}
|
||||
osi_core->mac_ver = ioctl_data.arg1_u32;
|
||||
|
||||
ret = osi_get_hw_features(osi_core, &pdata->hw_feat);
|
||||
ioctl_data.cmd = OSI_CMD_GET_HW_FEAT;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to get HW features\n");
|
||||
goto err_dma_mask;
|
||||
}
|
||||
memcpy(&pdata->hw_feat, &ioctl_data.hw_feat,
|
||||
sizeof(struct osi_hw_features));
|
||||
|
||||
/* Set netdev features based on hw features */
|
||||
ether_set_ndev_features(ndev, pdata);
|
||||
@@ -4474,6 +4550,7 @@ static int ether_suspend_noirq(struct device *dev)
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_dma_priv_data *osi_dma = pdata->osi_dma;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
unsigned int i = 0, chan = 0;
|
||||
|
||||
if (!netif_running(ndev))
|
||||
@@ -4483,7 +4560,8 @@ static int ether_suspend_noirq(struct device *dev)
|
||||
* current configuration so that SW view of HW is maintained across
|
||||
* suspend/resume.
|
||||
*/
|
||||
if (osi_save_registers(osi_core)) {
|
||||
ioctl_data.cmd = OSI_CMD_SAVE_REGISTER;
|
||||
if (osi_handle_ioctl(osi_core, &ioctl_data)) {
|
||||
dev_err(dev, "Failed to backup MAC core registers\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -4539,6 +4617,7 @@ static int ether_resume(struct ether_priv_data *pdata)
|
||||
struct osi_dma_priv_data *osi_dma = pdata->osi_dma;
|
||||
struct device *dev = pdata->dev;
|
||||
struct net_device *ndev = pdata->ndev;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = 0;
|
||||
|
||||
if (pdata->mac_rst) {
|
||||
@@ -4549,13 +4628,15 @@ static int ether_resume(struct ether_priv_data *pdata)
|
||||
}
|
||||
}
|
||||
|
||||
ret = osi_poll_for_mac_reset_complete(osi_core);
|
||||
ioctl_data.cmd = OSI_CMD_POLL_FOR_MAC_RST;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to poll mac software reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = osi_pad_calibrate(osi_core);
|
||||
ioctl_data.cmd = OSI_CMD_PAD_CALIBRATION;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to do pad caliberation\n");
|
||||
return ret;
|
||||
@@ -4592,7 +4673,14 @@ static int ether_resume(struct ether_priv_data *pdata)
|
||||
/* enable NAPI */
|
||||
ether_napi_enable(pdata);
|
||||
/* start the mac */
|
||||
osi_start_mac(osi_core);
|
||||
ioctl_data.cmd = OSI_CMD_START_MAC;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"%s: failed to start MAC %d\n", __func__, ret);
|
||||
goto err_start_mac;
|
||||
}
|
||||
|
||||
if (pdata->phydev && !(device_may_wakeup(&ndev->dev))) {
|
||||
/* configure phy init */
|
||||
phy_init_hw(pdata->phydev);
|
||||
@@ -4605,7 +4693,8 @@ static int ether_resume(struct ether_priv_data *pdata)
|
||||
ether_stats_work_queue_start(pdata);
|
||||
|
||||
return 0;
|
||||
|
||||
err_start_mac:
|
||||
ether_napi_disable(pdata);
|
||||
err_dma:
|
||||
osi_hw_core_deinit(osi_core);
|
||||
err_core:
|
||||
@@ -4630,6 +4719,7 @@ static int ether_resume_noirq(struct device *dev)
|
||||
struct net_device *ndev = dev_get_drvdata(dev);
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = 0;
|
||||
|
||||
if (!netif_running(ndev))
|
||||
@@ -4655,7 +4745,8 @@ static int ether_resume_noirq(struct device *dev)
|
||||
* Restore the backup of the MAC configuration to maintain consistency
|
||||
* between SW/HW state.
|
||||
*/
|
||||
if (osi_restore_registers(osi_core)) {
|
||||
ioctl_data.cmd = OSI_CMD_RESTORE_REGISTER;
|
||||
if (osi_handle_ioctl(osi_core, &ioctl_data)) {
|
||||
//TODO: Ideally, undo MAC init/resume & return.
|
||||
dev_err(dev, "Failed to restore MAC core registers\n");
|
||||
return -EIO;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -313,6 +313,7 @@ static void ether_get_ethtool_stats(struct net_device *dev,
|
||||
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;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int i, j = 0;
|
||||
int ret;
|
||||
|
||||
@@ -322,7 +323,8 @@ static void ether_get_ethtool_stats(struct net_device *dev,
|
||||
}
|
||||
|
||||
if (pdata->hw_feat.mmc_sel == 1U) {
|
||||
ret = osi_read_mmc(osi_core);
|
||||
ioctl_data.cmd = OSI_CMD_READ_MMC;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret == -1) {
|
||||
dev_err(pdata->dev, "Error in reading MMC counter\n");
|
||||
return;
|
||||
@@ -540,6 +542,7 @@ static int ether_set_pauseparam(struct net_device *ndev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
struct phy_device *phydev = pdata->phydev;
|
||||
int curflow_ctrl = OSI_FLOW_CTRL_DISABLE;
|
||||
int ret;
|
||||
@@ -586,8 +589,13 @@ static int ether_set_pauseparam(struct net_device *ndev,
|
||||
}
|
||||
|
||||
/* Configure current flow control settings */
|
||||
ret = osi_configure_flow_control(pdata->osi_core,
|
||||
pdata->osi_core->flow_ctrl);
|
||||
ioctl_data.cmd = OSI_CMD_FLOW_CTRL;
|
||||
ioctl_data.arg1_u32 = pdata->osi_core->flow_ctrl;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "Setting flow control failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -122,9 +122,9 @@ 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;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = -1;
|
||||
|
||||
if (ifdata->ptr == NULL) {
|
||||
@@ -133,7 +133,7 @@ static int ether_set_avb_algo(struct net_device *ndev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (copy_from_user(&l_avb_struct,
|
||||
if (copy_from_user(&ioctl_data.avb,
|
||||
(struct osi_core_avb_algorithm *)ifdata->ptr,
|
||||
sizeof(struct osi_core_avb_algorithm)) != 0U) {
|
||||
dev_err(pdata->dev,
|
||||
@@ -142,16 +142,17 @@ static int ether_set_avb_algo(struct net_device *ndev,
|
||||
}
|
||||
|
||||
/* Check AVB mode disable on slot function enable */
|
||||
tx_ring = osi_dma->tx_ring[l_avb_struct.qindex];
|
||||
tx_ring = osi_dma->tx_ring[ioctl_data.avb.qindex];
|
||||
if (tx_ring && tx_ring->slot_check == OSI_ENABLE &&
|
||||
l_avb_struct.oper_mode == OSI_MTL_QUEUE_ENABLE) {
|
||||
ioctl_data.avb.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);
|
||||
ioctl_data.avb.qindex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return osi_set_avb(osi_core, &l_avb_struct);
|
||||
ioctl_data.cmd = OSI_CMD_SET_AVB;
|
||||
return osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +175,7 @@ static int ether_get_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 avb_data;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret;
|
||||
|
||||
if (ifdata->ptr == NULL) {
|
||||
@@ -183,7 +184,7 @@ static int ether_get_avb_algo(struct net_device *ndev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user(&avb_data,
|
||||
if (copy_from_user(&ioctl_data.avb,
|
||||
(struct osi_core_avb_algorithm *)ifdata->ptr,
|
||||
sizeof(struct osi_core_avb_algorithm)) != 0U) {
|
||||
dev_err(pdata->dev,
|
||||
@@ -191,13 +192,14 @@ static int ether_get_avb_algo(struct net_device *ndev,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = osi_get_avb(osi_core, &avb_data);
|
||||
ioctl_data.cmd = OSI_CMD_GET_AVB;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret != 0) {
|
||||
dev_err(pdata->dev,
|
||||
"Failed to get AVB Struct info from registers\n");
|
||||
return ret;
|
||||
}
|
||||
if (copy_to_user(ifdata->ptr, &avb_data,
|
||||
if (copy_to_user(ifdata->ptr, &ioctl_data.avb,
|
||||
sizeof(struct osi_core_avb_algorithm)) != 0U) {
|
||||
dev_err(pdata->dev, "%s: copy_to_user failed\n", __func__);
|
||||
return -EFAULT;
|
||||
@@ -228,6 +230,8 @@ static int ether_config_arp_offload(struct ether_priv_data *pdata,
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct arp_offload_param param;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
|
||||
/* TODO: Need Spin lock to prevent multiple apps from
|
||||
* requesting same ioctls to the same MAC instance
|
||||
*/
|
||||
@@ -248,8 +252,10 @@ static int ether_config_arp_offload(struct ether_priv_data *pdata,
|
||||
dev_err(pdata->dev, "%s: Invalid IP addr\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
ret = osi_config_arp_offload(pdata->osi_core, ifrd_p->if_flags,
|
||||
param.ip_addr);
|
||||
ioctl_data.cmd = OSI_CMD_ARP_OFFLOAD;
|
||||
ioctl_data.arg1_u32 = ifrd_p->if_flags;
|
||||
ioctl_data.arg7_u8_p = param.ip_addr;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
dev_err(pdata->dev, "ARP offload: %s : %s\n",
|
||||
ifrd_p->if_flags ? "Enable" : "Disable",
|
||||
ret ? "Failed" : "Success");
|
||||
@@ -310,7 +316,7 @@ static int ether_config_ip4_filters(struct net_device *dev,
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_l3_l4_filter *u_l3_filter =
|
||||
(struct osi_l3_l4_filter *)ifdata->ptr;
|
||||
struct osi_l3_l4_filter l_l3_filter;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
unsigned int is_l4_filter = OSI_DISABLE;
|
||||
int ret = -EINVAL;
|
||||
|
||||
@@ -325,20 +331,26 @@ static int ether_config_ip4_filters(struct net_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (copy_from_user(&l_l3_filter, u_l3_filter,
|
||||
if (copy_from_user(&ioctl_data.l3l4_filter, u_l3_filter,
|
||||
sizeof(struct osi_l3_l4_filter)) != 0U) {
|
||||
dev_err(pdata->dev, "%s copy from user failed\n", __func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (l_l3_filter.filter_no > (pdata->hw_feat.l3l4_filter_num - 1U)) {
|
||||
if (ioctl_data.l3l4_filter.filter_no >
|
||||
(pdata->hw_feat.l3l4_filter_num - 1U)) {
|
||||
dev_err(pdata->dev, "%d filter is not supported in the HW\n",
|
||||
l_l3_filter.filter_no);
|
||||
ioctl_data.l3l4_filter.filter_no);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return osi_l3l4_filter(osi_core, l_l3_filter, OSI_IP4_FILTER,
|
||||
OSI_DISABLE, OSI_CHAN_ANY, is_l4_filter);
|
||||
ioctl_data.cmd = OSI_CMD_L3L4_FILTER;
|
||||
ioctl_data.arg1_u32 = OSI_IP4_FILTER;
|
||||
ioctl_data.arg2_u32 = OSI_DISABLE;
|
||||
ioctl_data.arg3_u32 = OSI_CHAN_ANY;
|
||||
ioctl_data.arg4_u32 = is_l4_filter;
|
||||
|
||||
return osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -366,7 +378,7 @@ static int ether_config_ip6_filters(struct net_device *dev,
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_l3_l4_filter *u_l3_filter =
|
||||
(struct osi_l3_l4_filter *)ifdata->ptr;
|
||||
struct osi_l3_l4_filter l_l3_filter;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
unsigned int is_l4_filter = OSI_DISABLE;
|
||||
int ret = -EINVAL;
|
||||
|
||||
@@ -381,20 +393,26 @@ static int ether_config_ip6_filters(struct net_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (copy_from_user(&l_l3_filter, u_l3_filter,
|
||||
if (copy_from_user(&ioctl_data.l3l4_filter, u_l3_filter,
|
||||
sizeof(struct osi_l3_l4_filter)) != 0U) {
|
||||
dev_err(pdata->dev, "%s copy from user failed\n", __func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (l_l3_filter.filter_no > (pdata->hw_feat.l3l4_filter_num - 1U)) {
|
||||
if (ioctl_data.l3l4_filter.filter_no >
|
||||
(pdata->hw_feat.l3l4_filter_num - 1U)) {
|
||||
dev_err(pdata->dev, "%d filter is not supported in the HW\n",
|
||||
l_l3_filter.filter_no);
|
||||
ioctl_data.l3l4_filter.filter_no);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return osi_l3l4_filter(osi_core, l_l3_filter, OSI_IP6_FILTER,
|
||||
OSI_DISABLE, OSI_CHAN_ANY, is_l4_filter);
|
||||
ioctl_data.cmd = OSI_CMD_L3L4_FILTER;
|
||||
ioctl_data.arg1_u32 = OSI_IP6_FILTER;
|
||||
ioctl_data.arg2_u32 = OSI_DISABLE;
|
||||
ioctl_data.arg3_u32 = OSI_CHAN_ANY;
|
||||
ioctl_data.arg4_u32 = is_l4_filter;
|
||||
|
||||
return osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -425,7 +443,7 @@ static int ether_config_tcp_udp_filters(struct net_device *dev,
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_l3_l4_filter *u_l4_filter =
|
||||
(struct osi_l3_l4_filter *)ifdata->ptr;
|
||||
struct osi_l3_l4_filter l_l4_filter;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
unsigned int is_l4_filter = OSI_ENABLE;
|
||||
int ret = -EINVAL;
|
||||
|
||||
@@ -441,20 +459,26 @@ static int ether_config_tcp_udp_filters(struct net_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (copy_from_user(&l_l4_filter, u_l4_filter,
|
||||
if (copy_from_user(&ioctl_data.l3l4_filter, u_l4_filter,
|
||||
sizeof(struct osi_l3_l4_filter)) != 0U) {
|
||||
dev_err(pdata->dev, "%s copy from user failed", __func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (l_l4_filter.filter_no > (pdata->hw_feat.l3l4_filter_num - 1U)) {
|
||||
if (ioctl_data.l3l4_filter.filter_no >
|
||||
(pdata->hw_feat.l3l4_filter_num - 1U)) {
|
||||
dev_err(pdata->dev, "%d filter is not supported in the HW\n",
|
||||
l_l4_filter.filter_no);
|
||||
ioctl_data.l3l4_filter.filter_no);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return osi_l3l4_filter(osi_core, l_l4_filter, tcp_udp,
|
||||
OSI_DISABLE, OSI_CHAN_ANY, is_l4_filter);
|
||||
ioctl_data.cmd = OSI_CMD_L3L4_FILTER;
|
||||
ioctl_data.arg1_u32 = tcp_udp;
|
||||
ioctl_data.arg2_u32 = OSI_DISABLE;
|
||||
ioctl_data.arg3_u32 = OSI_CHAN_ANY;
|
||||
ioctl_data.arg4_u32 = is_l4_filter;
|
||||
|
||||
return osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -480,7 +504,7 @@ static int ether_config_vlan_filter(struct net_device *dev,
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_vlan_filter *u_vlan_filter =
|
||||
(struct osi_vlan_filter *)ifdata->ptr;
|
||||
struct osi_vlan_filter l_vlan_filter;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (ifdata->ptr == NULL) {
|
||||
@@ -489,23 +513,23 @@ static int ether_config_vlan_filter(struct net_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (copy_from_user(&l_vlan_filter, u_vlan_filter,
|
||||
if (copy_from_user(&ioctl_data.vlan_filter, u_vlan_filter,
|
||||
sizeof(struct osi_vlan_filter)) != 0U) {
|
||||
dev_err(pdata->dev, "%s copy from user failed", __func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*0 - perfect and 1 - hash filtering */
|
||||
if (l_vlan_filter.perfect_hash == OSI_HASH_FILTER_MODE) {
|
||||
if (ioctl_data.vlan_filter.perfect_hash == OSI_HASH_FILTER_MODE) {
|
||||
dev_err(pdata->dev, "VLAN HASH filtering is not supported\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = osi_config_vlan_filtering(osi_core, l_vlan_filter.filter_enb_dis,
|
||||
l_vlan_filter.perfect_hash,
|
||||
l_vlan_filter.perfect_inverse_match);
|
||||
ioctl_data.cmd = OSI_CMD_VLAN_FILTER;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret == 0) {
|
||||
pdata->vlan_hash_filtering = l_vlan_filter.perfect_hash;
|
||||
pdata->vlan_hash_filtering =
|
||||
ioctl_data.vlan_filter.perfect_hash;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -535,10 +559,10 @@ static int ether_config_l2_da_filter(struct net_device *dev,
|
||||
struct osi_l2_da_filter *u_l2_da_filter =
|
||||
(struct osi_l2_da_filter *)ifdata->ptr;
|
||||
struct osi_l2_da_filter l_l2_da_filter;
|
||||
struct osi_filter filter;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = -EINVAL;
|
||||
|
||||
memset(&filter, 0x0, sizeof(struct osi_filter));
|
||||
memset(&ioctl_data.l2_filter, 0x0, sizeof(struct osi_filter));
|
||||
|
||||
if (ifdata->ptr == NULL) {
|
||||
dev_err(pdata->dev, "%s: Invalid data for priv ioctl %d\n",
|
||||
@@ -564,12 +588,13 @@ static int ether_config_l2_da_filter(struct net_device *dev,
|
||||
|
||||
/* configure L2 DA perfect/inverse_matching */
|
||||
if (l_l2_da_filter.perfect_inverse_match == OSI_ENABLE) {
|
||||
filter.oper_mode |= OSI_OPER_EN_L2_DA_INV;
|
||||
ioctl_data.l2_filter.oper_mode |= OSI_OPER_EN_L2_DA_INV;
|
||||
} else {
|
||||
filter.oper_mode |= OSI_OPER_DIS_L2_DA_INV;
|
||||
ioctl_data.l2_filter.oper_mode |= OSI_OPER_DIS_L2_DA_INV;
|
||||
}
|
||||
|
||||
ret = osi_l2_filter(osi_core, &filter);
|
||||
ioctl_data.cmd = OSI_CMD_L2_FILTER;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret != 0) {
|
||||
dev_err(pdata->dev, "setting L2_DA_INV failed\n");
|
||||
}
|
||||
@@ -597,14 +622,17 @@ static int ether_reg_save_restore(struct net_device *ndev,
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
|
||||
if (flags == OSI_ENABLE) {
|
||||
if (osi_restore_registers(osi_core)) {
|
||||
ioctl_data.cmd = OSI_CMD_RESTORE_REGISTER;
|
||||
if (osi_handle_ioctl(osi_core, &ioctl_data)) {
|
||||
dev_err(pdata->dev, "Restore MAC registers fail\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
} else if (flags == OSI_DISABLE) {
|
||||
if (osi_save_registers(osi_core)) {
|
||||
ioctl_data.cmd = OSI_CMD_SAVE_REGISTER;
|
||||
if (osi_handle_ioctl(osi_core, &ioctl_data)) {
|
||||
dev_err(pdata->dev, "Save MAC registers fail\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -639,6 +667,7 @@ static int ether_config_loopback_mode(struct net_device *ndev,
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct phy_device *phydev = ndev->phydev;
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = 0;
|
||||
|
||||
if ((flags && (pdata->mac_loopback_mode == OSI_ENABLE)) ||
|
||||
@@ -656,7 +685,10 @@ static int ether_config_loopback_mode(struct net_device *ndev,
|
||||
*/
|
||||
netif_carrier_on(ndev);
|
||||
}
|
||||
ret = osi_config_mac_loopback(osi_core, OSI_ENABLE);
|
||||
|
||||
ioctl_data.arg1_u32 = OSI_ENABLE;
|
||||
ioctl_data.cmd = OSI_CMD_MAC_LB;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev,
|
||||
"Failed to enable MAC Loopback\n");
|
||||
@@ -673,7 +705,10 @@ static int ether_config_loopback_mode(struct net_device *ndev,
|
||||
*/
|
||||
netif_carrier_off(ndev);
|
||||
}
|
||||
ret = osi_config_mac_loopback(osi_core, OSI_DISABLE);
|
||||
|
||||
ioctl_data.arg1_u32 = OSI_DISABLE;
|
||||
ioctl_data.cmd = OSI_CMD_MAC_LB;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev,
|
||||
"Failed to disable MAC Loopback\n");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -75,12 +75,15 @@ static int ether_adjust_time(struct ptp_clock_info *ptp, s64 nsec_delta)
|
||||
struct ether_priv_data,
|
||||
ptp_clock_ops);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
unsigned long flags;
|
||||
int ret = -1;
|
||||
|
||||
raw_spin_lock_irqsave(&pdata->ptp_lock, flags);
|
||||
|
||||
ret = osi_adjust_time(osi_core, nsec_delta);
|
||||
ioctl_data.cmd = OSI_CMD_ADJ_TIME;
|
||||
ioctl_data.arg8_64 = nsec_delta;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev,
|
||||
"%s:failed to adjust time with reason %d\n",
|
||||
@@ -110,12 +113,15 @@ static int ether_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
|
||||
struct ether_priv_data,
|
||||
ptp_clock_ops);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
unsigned long flags;
|
||||
int ret = -1;
|
||||
|
||||
raw_spin_lock_irqsave(&pdata->ptp_lock, flags);
|
||||
|
||||
ret = osi_adjust_freq(osi_core, ppb);
|
||||
ioctl_data.cmd = OSI_CMD_ADJ_FREQ;
|
||||
ioctl_data.arg6_32 = ppb;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev,
|
||||
"%s:failed to adjust frequency with reason code %d\n",
|
||||
@@ -185,12 +191,16 @@ static int ether_set_time(struct ptp_clock_info *ptp,
|
||||
struct ether_priv_data,
|
||||
ptp_clock_ops);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
unsigned long flags;
|
||||
int ret = -1;
|
||||
|
||||
raw_spin_lock_irqsave(&pdata->ptp_lock, flags);
|
||||
|
||||
ret = osi_set_systime_to_mac(osi_core, ts->tv_sec, ts->tv_nsec);
|
||||
ioctl_data.cmd = OSI_CMD_SET_SYSTOHW_TIME;
|
||||
ioctl_data.arg1_u32 = ts->tv_sec;
|
||||
ioctl_data.arg2_u32 = ts->tv_nsec;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev,
|
||||
"%s:failed to set system time with reason %d\n",
|
||||
@@ -270,21 +280,24 @@ 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;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
|
||||
/* 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));
|
||||
memset(&ioctl_data.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) ?
|
||||
ioctl_data.avb.qindex = qinx;
|
||||
ioctl_data.avb.algo = OSI_MTL_TXQ_AVALG_SP;
|
||||
ioctl_data.avb.oper_mode = (set == OSI_ENABLE) ?
|
||||
OSI_MTL_QUEUE_AVB :
|
||||
OSI_MTL_QUEUE_ENABLE;
|
||||
ret = osi_set_avb(osi_core, &avb);
|
||||
|
||||
ioctl_data.cmd = OSI_CMD_SET_AVB;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret != 0) {
|
||||
dev_err(pdata->dev,
|
||||
"Failed to set TXQ:%d AVB info\n",
|
||||
@@ -302,8 +315,10 @@ 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_ioctl ioctl_data = {};
|
||||
struct hwtstamp_config config;
|
||||
unsigned int hwts_rx_en = 1;
|
||||
int ret;
|
||||
#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE
|
||||
struct timespec now;
|
||||
#else
|
||||
@@ -440,7 +455,13 @@ 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);
|
||||
ioctl_data.arg1_u32 = OSI_DISABLE;
|
||||
ioctl_data.cmd = OSI_CMD_CONFIG_PTP;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "Failure to disable CONFIG_PTP\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
ether_config_slot_function(pdata, OSI_DISABLE);
|
||||
} else {
|
||||
/* Store default PTP clock frequency, so that we
|
||||
@@ -458,7 +479,13 @@ int ether_handle_hwtstamp_ioctl(struct ether_priv_data *pdata,
|
||||
/* one nsec accuracy */
|
||||
osi_core->ptp_config.one_nsec_accuracy = OSI_ENABLE;
|
||||
/* Enable the PTP configuration */
|
||||
osi_ptp_configuration(osi_core, OSI_ENABLE);
|
||||
ioctl_data.arg1_u32 = OSI_ENABLE;
|
||||
ioctl_data.cmd = OSI_CMD_CONFIG_PTP;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "Failure to enable CONFIG_PTP\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
#ifdef CONFIG_TEGRA_PTP_NOTIFIER
|
||||
/* Register broadcasting MAC timestamp to clients */
|
||||
tegra_register_hwtime_source(ether_get_ptptime, pdata);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -309,13 +309,15 @@ static int ether_test_phy_loopback(struct ether_priv_data *pdata)
|
||||
static int ether_test_mmc_counters(struct ether_priv_data *pdata)
|
||||
{
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
unsigned int mmc_tx_framecount_g = 0;
|
||||
unsigned int mmc_rx_framecount_gb = 0;
|
||||
unsigned int mmc_rx_ipv4_gd = 0;
|
||||
unsigned int mmc_rx_udp_gd = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = osi_read_mmc(osi_core);
|
||||
ioctl_data.cmd = OSI_CMD_READ_MMC;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -327,8 +329,8 @@ static int ether_test_mmc_counters(struct ether_priv_data *pdata)
|
||||
ret = ether_test_mac_loopback(pdata);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = osi_read_mmc(osi_core);
|
||||
ioctl_data.cmd = OSI_CMD_READ_MMC;
|
||||
ret = osi_handle_ioctl(osi_core, &ioctl_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -382,6 +384,7 @@ void ether_selftest_run(struct net_device *dev,
|
||||
struct ethtool_test *etest, u64 *buf)
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(dev);
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int count = ether_selftest_get_count(pdata);
|
||||
int carrier = netif_carrier_ok(dev);
|
||||
int i, ret;
|
||||
@@ -407,9 +410,12 @@ void ether_selftest_run(struct net_device *dev,
|
||||
break;
|
||||
/* Fallthrough */
|
||||
case ETHER_LOOPBACK_MAC:
|
||||
if (pdata->osi_core)
|
||||
ret = osi_config_mac_loopback(pdata->osi_core,
|
||||
OSI_ENABLE);
|
||||
if (pdata->osi_core) {
|
||||
ioctl_data.cmd = OSI_CMD_MAC_LB;
|
||||
ioctl_data.arg1_u32 = OSI_ENABLE;
|
||||
ret = osi_handle_ioctl(pdata->osi_core,
|
||||
&ioctl_data);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
@@ -436,9 +442,12 @@ void ether_selftest_run(struct net_device *dev,
|
||||
break;
|
||||
/* Fallthrough */
|
||||
case ETHER_LOOPBACK_MAC:
|
||||
if (pdata->osi_core)
|
||||
ret = osi_config_mac_loopback(pdata->osi_core,
|
||||
OSI_DISABLE);
|
||||
if (pdata->osi_core) {
|
||||
ioctl_data.cmd = OSI_CMD_MAC_LB;
|
||||
ioctl_data.arg1_u32 = OSI_DISABLE;
|
||||
ret = osi_handle_ioctl(pdata->osi_core,
|
||||
&ioctl_data);
|
||||
}
|
||||
if (!ret)
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -64,6 +64,7 @@ static ssize_t ether_mac_loopback_store(struct device *dev,
|
||||
struct net_device *ndev = (struct net_device *)dev_get_drvdata(dev);
|
||||
struct phy_device *phydev = ndev->phydev;
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct osi_ioctl ioctl_data = {};
|
||||
int ret = -1;
|
||||
|
||||
/* Interface is not up so LB mode can't be set */
|
||||
@@ -82,7 +83,9 @@ static ssize_t ether_mac_loopback_store(struct device *dev,
|
||||
netif_carrier_on(ndev);
|
||||
}
|
||||
/* Enabling the MAC Loopback Mode */
|
||||
ret = osi_config_mac_loopback(pdata->osi_core, OSI_ENABLE);
|
||||
ioctl_data.arg1_u32 = OSI_ENABLE;
|
||||
ioctl_data.cmd = OSI_CMD_MAC_LB;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "Enabling MAC Loopback failed\n");
|
||||
} else {
|
||||
@@ -99,7 +102,9 @@ static ssize_t ether_mac_loopback_store(struct device *dev,
|
||||
netif_carrier_off(ndev);
|
||||
}
|
||||
/* Disabling the MAC Loopback Mode */
|
||||
ret = osi_config_mac_loopback(pdata->osi_core, OSI_DISABLE);
|
||||
ioctl_data.arg1_u32 = OSI_DISABLE;
|
||||
ioctl_data.cmd = OSI_CMD_MAC_LB;
|
||||
ret = osi_handle_ioctl(pdata->osi_core, &ioctl_data);
|
||||
if (ret < 0) {
|
||||
dev_err(pdata->dev, "Disabling MAC Loopback failed\n");
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user