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:
rakesh goyal
2021-02-18 21:49:45 +05:30
committed by Revanth Kumar Uppala
parent 71fa042ce4
commit f4d30eb89b
6 changed files with 352 additions and 177 deletions

View File

@@ -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 *pdata = container_of(dwork,
struct ether_priv_data, ether_stats_work); struct ether_priv_data, ether_stats_work);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
int ret; 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) { if (ret < 0) {
dev_err(pdata->dev, "failed to read MMC counters %s\n", dev_err(pdata->dev, "failed to read MMC counters %s\n",
__func__); __func__);
@@ -240,6 +242,7 @@ int ether_conf_eee(struct ether_priv_data *pdata, unsigned int tx_lpi_enable)
int ret = 0; int ret = 0;
struct phy_device *phydev = pdata->phydev; struct phy_device *phydev = pdata->phydev;
unsigned int enable = tx_lpi_enable; unsigned int enable = tx_lpi_enable;
struct osi_ioctl ioctl_data = {};
if (tx_lpi_enable) { if (tx_lpi_enable) {
/* phy_init_eee() returns 0 if EEE is supported by the PHY */ /* 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 */ /* Enable EEE */
ret = osi_configure_eee(pdata->osi_core, ioctl_data.cmd = OSI_CMD_CONFIG_EEE;
enable, ioctl_data.arg1_u32 = enable;
pdata->tx_lpi_timer); 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 */ /* Return current status of EEE based on OSI API success/failure */
if (ret != 0) { if (ret != 0) {
if (enable) { if (enable) {
@@ -291,6 +296,7 @@ static void ether_adjust_link(struct net_device *dev)
int new_state = 0, speed_changed = 0; int new_state = 0, speed_changed = 0;
unsigned long val; unsigned long val;
unsigned int eee_enable = OSI_DISABLE; unsigned int eee_enable = OSI_DISABLE;
struct osi_ioctl ioctl_data = {};
int ret = 0; int ret = 0;
if (phydev == NULL) { if (phydev == NULL) {
@@ -300,20 +306,33 @@ static void ether_adjust_link(struct net_device *dev)
if (phydev->link) { if (phydev->link) {
if ((pdata->osi_core->pause_frames == OSI_PAUSE_FRAMES_ENABLE) if ((pdata->osi_core->pause_frames == OSI_PAUSE_FRAMES_ENABLE)
&& (phydev->pause || phydev->asym_pause)) { && (phydev->pause || phydev->asym_pause)) {
osi_configure_flow_control(pdata->osi_core, ioctl_data.cmd = OSI_CMD_FLOW_CTRL;
pdata->osi_core->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) { if (phydev->duplex != pdata->oldduplex) {
new_state = 1; 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; pdata->oldduplex = phydev->duplex;
} }
if (phydev->speed != pdata->speed) { if (phydev->speed != pdata->speed) {
new_state = 1; new_state = 1;
speed_changed = 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) { if (ret < 0) {
netdev_err(dev, "Failed to set speed\n"); netdev_err(dev, "Failed to set speed\n");
return; return;
@@ -351,9 +370,12 @@ static void ether_adjust_link(struct net_device *dev)
(phydev->speed == (phydev->speed ==
SPEED_100) ? 25000 * 1000 : 125000 * 1000); SPEED_100) ? 25000 * 1000 : 125000 * 1000);
if (phydev->speed != SPEED_10) { 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, dev_err(pdata->dev,
"failed to do pad caliberation\n"); "failed to do pad caliberation\n");
}
} }
} }
@@ -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) static irqreturn_t ether_common_isr(int irq, void *data)
{ {
struct ether_priv_data *pdata = (struct ether_priv_data *)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; 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 ether_priv_data *pdata = tcd->devdata;
struct device *dev = pdata->dev; struct device *dev = pdata->dev;
struct osi_ioctl ioctl_data = {};
/* Thermal framework will take care of making sure state is within /* Thermal framework will take care of making sure state is within
* valid bounds, based on the get_max_state callback. So no need * 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); 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"); dev_err(dev, "Therm state changed, failed pad calibration\n");
return -1; return -1;
} }
@@ -1616,6 +1648,7 @@ static int ether_open(struct net_device *dev)
{ {
struct ether_priv_data *pdata = netdev_priv(dev); struct ether_priv_data *pdata = netdev_priv(dev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
int ret = 0; int ret = 0;
/* Reset the PHY */ /* 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) { if (ret < 0) {
dev_err(&dev->dev, "failed to poll MAC Software reset\n"); dev_err(&dev->dev, "failed to poll MAC Software reset\n");
goto err_poll_swr; goto err_poll_swr;
@@ -1723,8 +1757,14 @@ static int ether_open(struct net_device *dev)
ether_init_eee_params(pdata); ether_init_eee_params(pdata);
/* Start the MAC */ /* 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 */ /* start PHY */
phy_start(pdata->phydev); 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. * @retval "negative value" on failure.
*/ */
static int ether_prepare_mc_list(struct net_device *dev, 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 ether_priv_data *pdata = netdev_priv(dev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
@@ -2277,53 +2317,56 @@ static int ether_prepare_mc_list(struct net_device *dev,
unsigned int i = 1; unsigned int i = 1;
int ret = -1; int ret = -1;
if (filter == NULL) { if (ioctl_data == NULL) {
dev_err(pdata->dev, "filter is NULL\n"); dev_err(pdata->dev, "ioctl_data is NULL\n");
return ret; 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) { if (pdata->l2_filtering_mode == OSI_HASH_FILTER_MODE) {
dev_err(pdata->dev, dev_err(pdata->dev,
"HASH FILTERING for mc addresses not Supported in SW\n"); "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_PROMISC |
OSI_OPER_DIS_ALLMULTI); OSI_OPER_DIS_ALLMULTI);
ioctl_data->cmd = OSI_CMD_L2_FILTER;
return osi_l2_filter(osi_core, filter); return osi_handle_ioctl(osi_core, ioctl_data);
/* address 0 is used for DUT DA so compare with /* address 0 is used for DUT DA so compare with
* pdata->num_mac_addr_regs - 1 * pdata->num_mac_addr_regs - 1
*/ */
} else if (netdev_mc_count(dev) > (pdata->num_mac_addr_regs - 1)) { } else if (netdev_mc_count(dev) > (pdata->num_mac_addr_regs - 1)) {
/* switch to PROMISCUOUS mode */ /* 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_EN_PROMISC |
OSI_OPER_DIS_ALLMULTI); OSI_OPER_DIS_ALLMULTI);
dev_dbg(pdata->dev, "enabling Promiscuous mode\n"); 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 { } else {
dev_dbg(pdata->dev, dev_dbg(pdata->dev,
"select PERFECT FILTERING for mc addresses, mc_count = %d, num_mac_addr_regs = %d\n", "select PERFECT FILTERING for mc addresses, mc_count = %d, num_mac_addr_regs = %d\n",
netdev_mc_count(dev), pdata->num_mac_addr_regs); 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_ADDR_UPDATE |
OSI_OPER_DIS_PROMISC | OSI_OPER_DIS_PROMISC |
OSI_OPER_DIS_ALLMULTI); OSI_OPER_DIS_ALLMULTI);
netdev_for_each_mc_addr(ha, dev) { netdev_for_each_mc_addr(ha, dev) {
dev_dbg(pdata->dev, dev_dbg(pdata->dev,
"mc addr[%d] = %#x:%#x:%#x:%#x:%#x:%#x\n", "mc addr[%d] = %#x:%#x:%#x:%#x:%#x:%#x\n",
i, ha->addr[0], ha->addr[1], ha->addr[2], i, ha->addr[0], ha->addr[1], ha->addr[2],
ha->addr[3], ha->addr[4], ha->addr[5]); ha->addr[3], ha->addr[4], ha->addr[5]);
filter->index = i; ioctl_data->l2_filter.index = i;
memcpy(filter->mac_address, ha->addr, ETH_ALEN); memcpy(ioctl_data->l2_filter.mac_address, ha->addr,
filter->dma_routing = OSI_DISABLE; ETH_ALEN);
filter->dma_chan = 0x0; ioctl_data->l2_filter.dma_routing = OSI_DISABLE;
filter->addr_mask = OSI_AMASK_DISABLE; ioctl_data->l2_filter.dma_chan = 0x0;
filter->src_dest = OSI_DA_MATCH; ioctl_data->l2_filter.addr_mask = OSI_AMASK_DISABLE;
ret = osi_l2_filter(osi_core, filter); 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) { if (ret < 0) {
dev_err(pdata->dev, "issue in creating mc list\n"); dev_err(pdata->dev, "issue in creating mc list\n");
pdata->last_filter_index = i - 1; 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. * @retval "negative value" on failure.
*/ */
static int ether_prepare_uc_list(struct net_device *dev, 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 ether_priv_data *pdata = netdev_priv(dev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
@@ -2367,51 +2410,54 @@ static int ether_prepare_uc_list(struct net_device *dev,
struct netdev_hw_addr *ha; struct netdev_hw_addr *ha;
int ret = -1; int ret = -1;
if (filter == NULL) { if (ioctl_data == NULL) {
dev_err(pdata->dev, "filter is NULL\n"); dev_err(pdata->dev, "ioctl_data is NULL\n");
return ret; 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) { if (pdata->l2_filtering_mode == OSI_HASH_FILTER_MODE) {
dev_err(pdata->dev, dev_err(pdata->dev,
"HASH FILTERING for uc addresses not Supported in SW\n"); "HASH FILTERING for uc addresses not Supported in SW\n");
/* Perfect filtering for multicast */ /* 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_PROMISC |
OSI_OPER_DIS_ALLMULTI); OSI_OPER_DIS_ALLMULTI);
ioctl_data->cmd = OSI_CMD_L2_FILTER;
return osi_l2_filter(osi_core, filter); return osi_handle_ioctl(osi_core, ioctl_data);
} else if (netdev_uc_count(dev) > (pdata->num_mac_addr_regs - i)) { } else if (netdev_uc_count(dev) > (pdata->num_mac_addr_regs - i)) {
/* switch to PROMISCUOUS mode */ /* 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_EN_PROMISC |
OSI_OPER_DIS_ALLMULTI); OSI_OPER_DIS_ALLMULTI);
dev_dbg(pdata->dev, "enabling Promiscuous mode\n"); dev_dbg(pdata->dev, "enabling Promiscuous mode\n");
ioctl_data->cmd = OSI_CMD_L2_FILTER;
return osi_l2_filter(osi_core, filter); return osi_handle_ioctl(osi_core, ioctl_data);
} else { } else {
dev_dbg(pdata->dev, dev_dbg(pdata->dev,
"select PERFECT FILTERING for uc addresses: uc_count = %d\n", "select PERFECT FILTERING for uc addresses: uc_count = %d\n",
netdev_uc_count(dev)); 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_ADDR_UPDATE |
OSI_OPER_DIS_PROMISC | OSI_OPER_DIS_PROMISC |
OSI_OPER_DIS_ALLMULTI); OSI_OPER_DIS_ALLMULTI);
netdev_for_each_uc_addr(ha, dev) { netdev_for_each_uc_addr(ha, dev) {
dev_dbg(pdata->dev, dev_dbg(pdata->dev,
"uc addr[%d] = %#x:%#x:%#x:%#x:%#x:%#x\n", "uc addr[%d] = %#x:%#x:%#x:%#x:%#x:%#x\n",
i, ha->addr[0], ha->addr[1], ha->addr[2], i, ha->addr[0], ha->addr[1], ha->addr[2],
ha->addr[3], ha->addr[4], ha->addr[5]); ha->addr[3], ha->addr[4], ha->addr[5]);
filter->index = i; ioctl_data->l2_filter.index = i;
memcpy(filter->mac_address, ha->addr, ETH_ALEN); memcpy(ioctl_data->l2_filter.mac_address, ha->addr,
filter->dma_routing = OSI_DISABLE; ETH_ALEN);
filter->dma_chan = 0x0; ioctl_data->l2_filter.dma_routing = OSI_DISABLE;
filter->addr_mask = OSI_AMASK_DISABLE; ioctl_data->l2_filter.dma_chan = 0x0;
filter->src_dest = OSI_DA_MATCH; ioctl_data->l2_filter.addr_mask = OSI_AMASK_DISABLE;
ret = osi_l2_filter(osi_core, filter); 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) { if (ret < 0) {
dev_err(pdata->dev, "issue in creating uc list\n"); dev_err(pdata->dev, "issue in creating uc list\n");
pdata->last_filter_index = i - 1; 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 ether_priv_data *pdata = netdev_priv(dev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_filter filter;
/* store last call last_uc_filter_index in temporary variable */ /* store last call last_uc_filter_index in temporary variable */
int last_index = pdata->last_filter_index; int last_index = pdata->last_filter_index;
struct osi_ioctl ioctl_data = {};
int ret = -1; int ret = -1;
unsigned int i = 0; 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 ((dev->flags & IFF_PROMISC) == IFF_PROMISC) {
if (pdata->promisc_mode == OSI_ENABLE) { if (pdata->promisc_mode == OSI_ENABLE) {
filter.oper_mode = (OSI_OPER_DIS_PERFECT | ioctl_data.l2_filter.oper_mode =
OSI_OPER_EN_PROMISC | (OSI_OPER_DIS_PERFECT |
OSI_OPER_DIS_ALLMULTI); OSI_OPER_EN_PROMISC |
OSI_OPER_DIS_ALLMULTI);
dev_dbg(pdata->dev, "enabling Promiscuous mode\n"); 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) { if (ret < 0) {
dev_err(pdata->dev, dev_err(pdata->dev,
"Setting Promiscuous mode failed\n"); "Setting Promiscuous mode failed\n");
@@ -2469,18 +2518,19 @@ static void ether_set_rx_mode(struct net_device *dev)
return; return;
} else if ((dev->flags & IFF_ALLMULTI) == IFF_ALLMULTI) { } 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_PERFECT |
OSI_OPER_DIS_PROMISC); OSI_OPER_DIS_PROMISC);
dev_dbg(pdata->dev, "pass all multicast pkt\n"); 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) { if (ret < 0) {
dev_err(pdata->dev, "Setting All Multicast allow mode failed\n"); dev_err(pdata->dev, "Setting All Multicast allow mode failed\n");
} }
return; return;
} else if (!netdev_mc_empty(dev)) { } 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"); dev_err(pdata->dev, "Setting MC address failed\n");
} }
} else { } else {
@@ -2488,22 +2538,23 @@ static void ether_set_rx_mode(struct net_device *dev)
} }
if (!netdev_uc_empty(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"); dev_err(pdata->dev, "Setting UC address failed\n");
} }
} }
/* Reset the filter structure to avoid any old value */ /* 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 */ /* invalidate remaining ealier address */
for (i = pdata->last_filter_index + 1; i <= last_index; i++) { for (i = pdata->last_filter_index + 1; i <= last_index; i++) {
filter.oper_mode = OSI_OPER_ADDR_UPDATE; ioctl_data.l2_filter.oper_mode = OSI_OPER_ADDR_DEL;
filter.index = i; ioctl_data.l2_filter.index = i;
filter.dma_routing = OSI_DISABLE; ioctl_data.l2_filter.dma_routing = OSI_DISABLE;
filter.dma_chan = OSI_CHAN_ANY; ioctl_data.l2_filter.dma_chan = OSI_CHAN_ANY;
filter.addr_mask = OSI_AMASK_DISABLE; ioctl_data.l2_filter.addr_mask = OSI_AMASK_DISABLE;
filter.src_dest = OSI_DA_MATCH; ioctl_data.l2_filter.src_dest = OSI_DA_MATCH;
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) { if (ret < 0) {
dev_err(pdata->dev, "Invalidating expired L2 filter failed\n"); dev_err(pdata->dev, "Invalidating expired L2 filter failed\n");
return; 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 ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
netdev_features_t hw_feat_cur_state = pdata->hw_feat_cur_state; 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) { if (pdata->hw_feat.rx_coe_sel == 0U) {
return ret; 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 ((feat & NETIF_F_RXCSUM) == NETIF_F_RXCSUM) {
if (!(hw_feat_cur_state & NETIF_F_RXCSUM)) { if (!(hw_feat_cur_state & NETIF_F_RXCSUM)) {
ret = osi_config_rxcsum_offload(osi_core, ioctl_data.cmd = OSI_CMD_RXCSUM_OFFLOAD;
OSI_ENABLE); ioctl_data.arg1_u32 = OSI_ENABLE;
ret = osi_handle_ioctl(osi_core, &ioctl_data);
dev_info(pdata->dev, "Rx Csum offload: Enable: %s\n", dev_info(pdata->dev, "Rx Csum offload: Enable: %s\n",
ret ? "Failed" : "Success"); ret ? "Failed" : "Success");
pdata->hw_feat_cur_state |= NETIF_F_RXCSUM; pdata->hw_feat_cur_state |= NETIF_F_RXCSUM;
} }
} else { } else {
if ((hw_feat_cur_state & NETIF_F_RXCSUM)) { if ((hw_feat_cur_state & NETIF_F_RXCSUM)) {
ret = osi_config_rxcsum_offload(osi_core, ioctl_data.cmd = OSI_CMD_RXCSUM_OFFLOAD;
OSI_DISABLE); ioctl_data.arg1_u32 = OSI_DISABLE;
ret = osi_handle_ioctl(osi_core, &ioctl_data);
dev_info(pdata->dev, "Rx Csum offload: Disable: %s\n", dev_info(pdata->dev, "Rx Csum offload: Disable: %s\n",
ret ? "Failed" : "Success"); ret ? "Failed" : "Success");
pdata->hw_feat_cur_state &= ~NETIF_F_RXCSUM; 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 ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
int ret = -1; int ret = -1;
if (pdata->vlan_hash_filtering == OSI_HASH_FILTER_MODE) { if (pdata->vlan_hash_filtering == OSI_HASH_FILTER_MODE) {
dev_err(pdata->dev, dev_err(pdata->dev,
"HASH FILTERING for VLAN tag is not supported in SW\n"); "HASH FILTERING for VLAN tag is not supported in SW\n");
} else { } 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; 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 ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
int ret = -1; int ret = -1;
if (!netif_running(ndev)) { 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, dev_err(pdata->dev,
"HASH FILTERING for VLAN tag is not supported in SW\n"); "HASH FILTERING for VLAN tag is not supported in SW\n");
} else { } else {
ioctl_data.cmd = OSI_CMD_UPDATE_VLAN_ID;
/* By default, receive only VLAN pkt with VID = 1 because /* By default, receive only VLAN pkt with VID = 1 because
* writing 0 will pass all VLAN pkt * 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; return ret;
@@ -3497,6 +3557,7 @@ static int ether_configure_car(struct platform_device *pdev,
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
unsigned long csr_clk_rate = 0; unsigned long csr_clk_rate = 0;
struct osi_ioctl ioctl_data = {};
int ret = 0; int ret = 0;
if (osi_core->pre_si) { 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); 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; return ret;
err_mdc:
if (pdata->mac_rst) {
reset_control_assert(pdata->mac_rst);
}
err_rst: err_rst:
ether_disable_clks(pdata); ether_disable_clks(pdata);
err_enable_clks: 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; unsigned int num_dma_chans, mac, num_mtl_queues, chan;
struct osi_core_priv_data *osi_core; struct osi_core_priv_data *osi_core;
struct osi_dma_priv_data *osi_dma; struct osi_dma_priv_data *osi_dma;
struct osi_ioctl ioctl_data = {};
struct net_device *ndev; struct net_device *ndev;
int ret = 0, i; int ret = 0, i;
@@ -4320,18 +4391,23 @@ static int ether_probe(struct platform_device *pdev)
goto err_init_res; 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) { if (ret < 0) {
dev_err(&pdev->dev, "failed to get MAC version (%u)\n", dev_err(&pdev->dev, "failed to get MAC version (%u)\n",
osi_core->mac_ver); osi_core->mac_ver);
goto err_dma_mask; 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) { if (ret < 0) {
dev_err(&pdev->dev, "failed to get HW features\n"); dev_err(&pdev->dev, "failed to get HW features\n");
goto err_dma_mask; goto err_dma_mask;
} }
memcpy(&pdata->hw_feat, &ioctl_data.hw_feat,
sizeof(struct osi_hw_features));
/* Set netdev features based on hw features */ /* Set netdev features based on hw features */
ether_set_ndev_features(ndev, pdata); 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 ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_dma_priv_data *osi_dma = pdata->osi_dma; struct osi_dma_priv_data *osi_dma = pdata->osi_dma;
struct osi_ioctl ioctl_data = {};
unsigned int i = 0, chan = 0; unsigned int i = 0, chan = 0;
if (!netif_running(ndev)) 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 * current configuration so that SW view of HW is maintained across
* suspend/resume. * 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"); dev_err(dev, "Failed to backup MAC core registers\n");
return -EBUSY; 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 osi_dma_priv_data *osi_dma = pdata->osi_dma;
struct device *dev = pdata->dev; struct device *dev = pdata->dev;
struct net_device *ndev = pdata->ndev; struct net_device *ndev = pdata->ndev;
struct osi_ioctl ioctl_data = {};
int ret = 0; int ret = 0;
if (pdata->mac_rst) { 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) { if (ret < 0) {
dev_err(dev, "failed to poll mac software reset\n"); dev_err(dev, "failed to poll mac software reset\n");
return ret; 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) { if (ret < 0) {
dev_err(dev, "failed to do pad caliberation\n"); dev_err(dev, "failed to do pad caliberation\n");
return ret; return ret;
@@ -4592,7 +4673,14 @@ static int ether_resume(struct ether_priv_data *pdata)
/* enable NAPI */ /* enable NAPI */
ether_napi_enable(pdata); ether_napi_enable(pdata);
/* start the mac */ /* 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))) { if (pdata->phydev && !(device_may_wakeup(&ndev->dev))) {
/* configure phy init */ /* configure phy init */
phy_init_hw(pdata->phydev); phy_init_hw(pdata->phydev);
@@ -4605,7 +4693,8 @@ static int ether_resume(struct ether_priv_data *pdata)
ether_stats_work_queue_start(pdata); ether_stats_work_queue_start(pdata);
return 0; return 0;
err_start_mac:
ether_napi_disable(pdata);
err_dma: err_dma:
osi_hw_core_deinit(osi_core); osi_hw_core_deinit(osi_core);
err_core: err_core:
@@ -4630,6 +4719,7 @@ static int ether_resume_noirq(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev); struct net_device *ndev = dev_get_drvdata(dev);
struct ether_priv_data *pdata = netdev_priv(ndev); struct ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
int ret = 0; int ret = 0;
if (!netif_running(ndev)) 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 * Restore the backup of the MAC configuration to maintain consistency
* between SW/HW state. * 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. //TODO: Ideally, undo MAC init/resume & return.
dev_err(dev, "Failed to restore MAC core registers\n"); dev_err(dev, "Failed to restore MAC core registers\n");
return -EIO; return -EIO;

View File

@@ -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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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 ether_priv_data *pdata = netdev_priv(dev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_dma_priv_data *osi_dma = pdata->osi_dma; struct osi_dma_priv_data *osi_dma = pdata->osi_dma;
struct osi_ioctl ioctl_data = {};
int i, j = 0; int i, j = 0;
int ret; int ret;
@@ -322,7 +323,8 @@ static void ether_get_ethtool_stats(struct net_device *dev,
} }
if (pdata->hw_feat.mmc_sel == 1U) { 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) { if (ret == -1) {
dev_err(pdata->dev, "Error in reading MMC counter\n"); dev_err(pdata->dev, "Error in reading MMC counter\n");
return; return;
@@ -540,6 +542,7 @@ static int ether_set_pauseparam(struct net_device *ndev,
struct ethtool_pauseparam *pause) struct ethtool_pauseparam *pause)
{ {
struct ether_priv_data *pdata = netdev_priv(ndev); struct ether_priv_data *pdata = netdev_priv(ndev);
struct osi_ioctl ioctl_data = {};
struct phy_device *phydev = pdata->phydev; struct phy_device *phydev = pdata->phydev;
int curflow_ctrl = OSI_FLOW_CTRL_DISABLE; int curflow_ctrl = OSI_FLOW_CTRL_DISABLE;
int ret; int ret;
@@ -586,8 +589,13 @@ static int ether_set_pauseparam(struct net_device *ndev,
} }
/* Configure current flow control settings */ /* Configure current flow control settings */
ret = osi_configure_flow_control(pdata->osi_core, ioctl_data.cmd = OSI_CMD_FLOW_CTRL;
pdata->osi_core->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; return ret;
} }

View File

@@ -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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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 ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core; 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_dma_priv_data *osi_dma = pdata->osi_dma;
struct osi_tx_ring *tx_ring = NULL; struct osi_tx_ring *tx_ring = NULL;
struct osi_ioctl ioctl_data = {};
int ret = -1; int ret = -1;
if (ifdata->ptr == NULL) { if (ifdata->ptr == NULL) {
@@ -133,7 +133,7 @@ static int ether_set_avb_algo(struct net_device *ndev,
return ret; return ret;
} }
if (copy_from_user(&l_avb_struct, if (copy_from_user(&ioctl_data.avb,
(struct osi_core_avb_algorithm *)ifdata->ptr, (struct osi_core_avb_algorithm *)ifdata->ptr,
sizeof(struct osi_core_avb_algorithm)) != 0U) { sizeof(struct osi_core_avb_algorithm)) != 0U) {
dev_err(pdata->dev, 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 */ /* 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 && 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, dev_err(pdata->dev,
"Can't disable queue:%d AVB mode when slot is enabled", "Can't disable queue:%d AVB mode when slot is enabled",
l_avb_struct.qindex); ioctl_data.avb.qindex);
return -EINVAL; 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 ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_core_avb_algorithm avb_data; struct osi_ioctl ioctl_data = {};
int ret; int ret;
if (ifdata->ptr == NULL) { if (ifdata->ptr == NULL) {
@@ -183,7 +184,7 @@ static int ether_get_avb_algo(struct net_device *ndev,
return -EINVAL; return -EINVAL;
} }
if (copy_from_user(&avb_data, if (copy_from_user(&ioctl_data.avb,
(struct osi_core_avb_algorithm *)ifdata->ptr, (struct osi_core_avb_algorithm *)ifdata->ptr,
sizeof(struct osi_core_avb_algorithm)) != 0U) { sizeof(struct osi_core_avb_algorithm)) != 0U) {
dev_err(pdata->dev, dev_err(pdata->dev,
@@ -191,13 +192,14 @@ static int ether_get_avb_algo(struct net_device *ndev,
return -EFAULT; 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) { if (ret != 0) {
dev_err(pdata->dev, dev_err(pdata->dev,
"Failed to get AVB Struct info from registers\n"); "Failed to get AVB Struct info from registers\n");
return ret; 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) { sizeof(struct osi_core_avb_algorithm)) != 0U) {
dev_err(pdata->dev, "%s: copy_to_user failed\n", __func__); dev_err(pdata->dev, "%s: copy_to_user failed\n", __func__);
return -EFAULT; return -EFAULT;
@@ -228,6 +230,8 @@ static int ether_config_arp_offload(struct ether_priv_data *pdata,
{ {
int ret = -EINVAL; int ret = -EINVAL;
struct arp_offload_param param; struct arp_offload_param param;
struct osi_ioctl ioctl_data = {};
/* TODO: Need Spin lock to prevent multiple apps from /* TODO: Need Spin lock to prevent multiple apps from
* requesting same ioctls to the same MAC instance * 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__); dev_err(pdata->dev, "%s: Invalid IP addr\n", __func__);
return ret; return ret;
} }
ret = osi_config_arp_offload(pdata->osi_core, ifrd_p->if_flags, ioctl_data.cmd = OSI_CMD_ARP_OFFLOAD;
param.ip_addr); 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", dev_err(pdata->dev, "ARP offload: %s : %s\n",
ifrd_p->if_flags ? "Enable" : "Disable", ifrd_p->if_flags ? "Enable" : "Disable",
ret ? "Failed" : "Success"); 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_core_priv_data *osi_core = pdata->osi_core;
struct osi_l3_l4_filter *u_l3_filter = struct osi_l3_l4_filter *u_l3_filter =
(struct osi_l3_l4_filter *)ifdata->ptr; (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; unsigned int is_l4_filter = OSI_DISABLE;
int ret = -EINVAL; int ret = -EINVAL;
@@ -325,20 +331,26 @@ static int ether_config_ip4_filters(struct net_device *dev,
return ret; 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) { sizeof(struct osi_l3_l4_filter)) != 0U) {
dev_err(pdata->dev, "%s copy from user failed\n", __func__); dev_err(pdata->dev, "%s copy from user failed\n", __func__);
return -EFAULT; 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", 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 ret;
} }
return osi_l3l4_filter(osi_core, l_l3_filter, OSI_IP4_FILTER, ioctl_data.cmd = OSI_CMD_L3L4_FILTER;
OSI_DISABLE, OSI_CHAN_ANY, is_l4_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_core_priv_data *osi_core = pdata->osi_core;
struct osi_l3_l4_filter *u_l3_filter = struct osi_l3_l4_filter *u_l3_filter =
(struct osi_l3_l4_filter *)ifdata->ptr; (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; unsigned int is_l4_filter = OSI_DISABLE;
int ret = -EINVAL; int ret = -EINVAL;
@@ -381,20 +393,26 @@ static int ether_config_ip6_filters(struct net_device *dev,
return ret; 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) { sizeof(struct osi_l3_l4_filter)) != 0U) {
dev_err(pdata->dev, "%s copy from user failed\n", __func__); dev_err(pdata->dev, "%s copy from user failed\n", __func__);
return -EFAULT; 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", 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 ret;
} }
return osi_l3l4_filter(osi_core, l_l3_filter, OSI_IP6_FILTER, ioctl_data.cmd = OSI_CMD_L3L4_FILTER;
OSI_DISABLE, OSI_CHAN_ANY, is_l4_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_core_priv_data *osi_core = pdata->osi_core;
struct osi_l3_l4_filter *u_l4_filter = struct osi_l3_l4_filter *u_l4_filter =
(struct osi_l3_l4_filter *)ifdata->ptr; (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; unsigned int is_l4_filter = OSI_ENABLE;
int ret = -EINVAL; int ret = -EINVAL;
@@ -441,20 +459,26 @@ static int ether_config_tcp_udp_filters(struct net_device *dev,
return ret; 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) { sizeof(struct osi_l3_l4_filter)) != 0U) {
dev_err(pdata->dev, "%s copy from user failed", __func__); dev_err(pdata->dev, "%s copy from user failed", __func__);
return -EFAULT; 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", 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 ret;
} }
return osi_l3l4_filter(osi_core, l_l4_filter, tcp_udp, ioctl_data.cmd = OSI_CMD_L3L4_FILTER;
OSI_DISABLE, OSI_CHAN_ANY, is_l4_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_core_priv_data *osi_core = pdata->osi_core;
struct osi_vlan_filter *u_vlan_filter = struct osi_vlan_filter *u_vlan_filter =
(struct osi_vlan_filter *)ifdata->ptr; (struct osi_vlan_filter *)ifdata->ptr;
struct osi_vlan_filter l_vlan_filter; struct osi_ioctl ioctl_data = {};
int ret = -EINVAL; int ret = -EINVAL;
if (ifdata->ptr == NULL) { if (ifdata->ptr == NULL) {
@@ -489,23 +513,23 @@ static int ether_config_vlan_filter(struct net_device *dev,
return ret; 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) { sizeof(struct osi_vlan_filter)) != 0U) {
dev_err(pdata->dev, "%s copy from user failed", __func__); dev_err(pdata->dev, "%s copy from user failed", __func__);
return -EFAULT; return -EFAULT;
} }
/*0 - perfect and 1 - hash filtering */ /*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"); dev_err(pdata->dev, "VLAN HASH filtering is not supported\n");
return ret; return ret;
} }
ret = osi_config_vlan_filtering(osi_core, l_vlan_filter.filter_enb_dis, ioctl_data.cmd = OSI_CMD_VLAN_FILTER;
l_vlan_filter.perfect_hash, ret = osi_handle_ioctl(osi_core, &ioctl_data);
l_vlan_filter.perfect_inverse_match);
if (ret == 0) { if (ret == 0) {
pdata->vlan_hash_filtering = l_vlan_filter.perfect_hash; pdata->vlan_hash_filtering =
ioctl_data.vlan_filter.perfect_hash;
} }
return ret; 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 *u_l2_da_filter =
(struct osi_l2_da_filter *)ifdata->ptr; (struct osi_l2_da_filter *)ifdata->ptr;
struct osi_l2_da_filter l_l2_da_filter; struct osi_l2_da_filter l_l2_da_filter;
struct osi_filter filter; struct osi_ioctl ioctl_data = {};
int ret = -EINVAL; int ret = -EINVAL;
memset(&filter, 0x0, sizeof(struct osi_filter)); memset(&ioctl_data.l2_filter, 0x0, sizeof(struct osi_filter));
if (ifdata->ptr == NULL) { if (ifdata->ptr == NULL) {
dev_err(pdata->dev, "%s: Invalid data for priv ioctl %d\n", 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 */ /* configure L2 DA perfect/inverse_matching */
if (l_l2_da_filter.perfect_inverse_match == OSI_ENABLE) { 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 { } 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) { if (ret != 0) {
dev_err(pdata->dev, "setting L2_DA_INV failed\n"); 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 ether_priv_data *pdata = netdev_priv(ndev);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
if (flags == OSI_ENABLE) { 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"); dev_err(pdata->dev, "Restore MAC registers fail\n");
return -EBUSY; return -EBUSY;
} }
} else if (flags == OSI_DISABLE) { } 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"); dev_err(pdata->dev, "Save MAC registers fail\n");
return -EBUSY; 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 ether_priv_data *pdata = netdev_priv(ndev);
struct phy_device *phydev = ndev->phydev; struct phy_device *phydev = ndev->phydev;
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
int ret = 0; int ret = 0;
if ((flags && (pdata->mac_loopback_mode == OSI_ENABLE)) || 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); 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) { if (ret < 0) {
dev_err(pdata->dev, dev_err(pdata->dev,
"Failed to enable MAC Loopback\n"); "Failed to enable MAC Loopback\n");
@@ -673,7 +705,10 @@ static int ether_config_loopback_mode(struct net_device *ndev,
*/ */
netif_carrier_off(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) { if (ret < 0) {
dev_err(pdata->dev, dev_err(pdata->dev,
"Failed to disable MAC Loopback\n"); "Failed to disable MAC Loopback\n");

View File

@@ -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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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, struct ether_priv_data,
ptp_clock_ops); ptp_clock_ops);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
unsigned long flags; unsigned long flags;
int ret = -1; int ret = -1;
raw_spin_lock_irqsave(&pdata->ptp_lock, flags); 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) { if (ret < 0) {
dev_err(pdata->dev, dev_err(pdata->dev,
"%s:failed to adjust time with reason %d\n", "%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, struct ether_priv_data,
ptp_clock_ops); ptp_clock_ops);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
unsigned long flags; unsigned long flags;
int ret = -1; int ret = -1;
raw_spin_lock_irqsave(&pdata->ptp_lock, flags); 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) { if (ret < 0) {
dev_err(pdata->dev, dev_err(pdata->dev,
"%s:failed to adjust frequency with reason code %d\n", "%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, struct ether_priv_data,
ptp_clock_ops); ptp_clock_ops);
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
unsigned long flags; unsigned long flags;
int ret = -1; int ret = -1;
raw_spin_lock_irqsave(&pdata->ptp_lock, flags); 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) { if (ret < 0) {
dev_err(pdata->dev, dev_err(pdata->dev,
"%s:failed to set system time with reason %d\n", "%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_dma_priv_data *osi_dma = pdata->osi_dma;
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
unsigned int ret, i, chan, qinx; unsigned int ret, i, chan, qinx;
struct osi_core_avb_algorithm avb; struct osi_ioctl ioctl_data = {};
/* Configure TXQ AVB mode */ /* Configure TXQ AVB mode */
for (i = 0; i < osi_dma->num_dma_chans; i++) { for (i = 0; i < osi_dma->num_dma_chans; i++) {
chan = osi_dma->dma_chans[i]; chan = osi_dma->dma_chans[i];
if (osi_dma->slot_enabled[chan] == OSI_ENABLE) { if (osi_dma->slot_enabled[chan] == OSI_ENABLE) {
/* Set TXQ AVB info */ /* 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]; qinx = osi_core->mtl_queues[i];
avb.qindex = qinx; ioctl_data.avb.qindex = qinx;
avb.algo = OSI_MTL_TXQ_AVALG_SP; ioctl_data.avb.algo = OSI_MTL_TXQ_AVALG_SP;
avb.oper_mode = (set == OSI_ENABLE) ? ioctl_data.avb.oper_mode = (set == OSI_ENABLE) ?
OSI_MTL_QUEUE_AVB : OSI_MTL_QUEUE_AVB :
OSI_MTL_QUEUE_ENABLE; 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) { if (ret != 0) {
dev_err(pdata->dev, dev_err(pdata->dev,
"Failed to set TXQ:%d AVB info\n", "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 ifreq *ifr)
{ {
struct osi_core_priv_data *osi_core = pdata->osi_core; struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
struct hwtstamp_config config; struct hwtstamp_config config;
unsigned int hwts_rx_en = 1; unsigned int hwts_rx_en = 1;
int ret;
#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE #if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE
struct timespec now; struct timespec now;
#else #else
@@ -440,7 +455,13 @@ int ether_handle_hwtstamp_ioctl(struct ether_priv_data *pdata,
if (!pdata->hwts_tx_en && !hwts_rx_en) { if (!pdata->hwts_tx_en && !hwts_rx_en) {
/* disable the PTP configuration */ /* 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); ether_config_slot_function(pdata, OSI_DISABLE);
} else { } else {
/* Store default PTP clock frequency, so that we /* 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 */ /* one nsec accuracy */
osi_core->ptp_config.one_nsec_accuracy = OSI_ENABLE; osi_core->ptp_config.one_nsec_accuracy = OSI_ENABLE;
/* Enable the PTP configuration */ /* 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 #ifdef CONFIG_TEGRA_PTP_NOTIFIER
/* Register broadcasting MAC timestamp to clients */ /* Register broadcasting MAC timestamp to clients */
tegra_register_hwtime_source(ether_get_ptptime, pdata); tegra_register_hwtime_source(ether_get_ptptime, pdata);

View File

@@ -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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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) static int ether_test_mmc_counters(struct ether_priv_data *pdata)
{ {
struct osi_core_priv_data *osi_core = pdata->osi_core; 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_tx_framecount_g = 0;
unsigned int mmc_rx_framecount_gb = 0; unsigned int mmc_rx_framecount_gb = 0;
unsigned int mmc_rx_ipv4_gd = 0; unsigned int mmc_rx_ipv4_gd = 0;
unsigned int mmc_rx_udp_gd = 0; unsigned int mmc_rx_udp_gd = 0;
int ret = 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) if (ret < 0)
return ret; return ret;
@@ -327,8 +329,8 @@ static int ether_test_mmc_counters(struct ether_priv_data *pdata)
ret = ether_test_mac_loopback(pdata); ret = ether_test_mac_loopback(pdata);
if (ret < 0) if (ret < 0)
return ret; return ret;
ioctl_data.cmd = OSI_CMD_READ_MMC;
ret = osi_read_mmc(osi_core); ret = osi_handle_ioctl(osi_core, &ioctl_data);
if (ret < 0) if (ret < 0)
return ret; return ret;
@@ -382,6 +384,7 @@ void ether_selftest_run(struct net_device *dev,
struct ethtool_test *etest, u64 *buf) struct ethtool_test *etest, u64 *buf)
{ {
struct ether_priv_data *pdata = netdev_priv(dev); struct ether_priv_data *pdata = netdev_priv(dev);
struct osi_ioctl ioctl_data = {};
int count = ether_selftest_get_count(pdata); int count = ether_selftest_get_count(pdata);
int carrier = netif_carrier_ok(dev); int carrier = netif_carrier_ok(dev);
int i, ret; int i, ret;
@@ -407,9 +410,12 @@ void ether_selftest_run(struct net_device *dev,
break; break;
/* Fallthrough */ /* Fallthrough */
case ETHER_LOOPBACK_MAC: case ETHER_LOOPBACK_MAC:
if (pdata->osi_core) if (pdata->osi_core) {
ret = osi_config_mac_loopback(pdata->osi_core, ioctl_data.cmd = OSI_CMD_MAC_LB;
OSI_ENABLE); ioctl_data.arg1_u32 = OSI_ENABLE;
ret = osi_handle_ioctl(pdata->osi_core,
&ioctl_data);
}
break; break;
default: default:
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
@@ -436,9 +442,12 @@ void ether_selftest_run(struct net_device *dev,
break; break;
/* Fallthrough */ /* Fallthrough */
case ETHER_LOOPBACK_MAC: case ETHER_LOOPBACK_MAC:
if (pdata->osi_core) if (pdata->osi_core) {
ret = osi_config_mac_loopback(pdata->osi_core, ioctl_data.cmd = OSI_CMD_MAC_LB;
OSI_DISABLE); ioctl_data.arg1_u32 = OSI_DISABLE;
ret = osi_handle_ioctl(pdata->osi_core,
&ioctl_data);
}
if (!ret) if (!ret)
break; break;
default: default:

View File

@@ -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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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 net_device *ndev = (struct net_device *)dev_get_drvdata(dev);
struct phy_device *phydev = ndev->phydev; struct phy_device *phydev = ndev->phydev;
struct ether_priv_data *pdata = netdev_priv(ndev); struct ether_priv_data *pdata = netdev_priv(ndev);
struct osi_ioctl ioctl_data = {};
int ret = -1; int ret = -1;
/* Interface is not up so LB mode can't be set */ /* 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); netif_carrier_on(ndev);
} }
/* Enabling the MAC Loopback Mode */ /* 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) { if (ret < 0) {
dev_err(pdata->dev, "Enabling MAC Loopback failed\n"); dev_err(pdata->dev, "Enabling MAC Loopback failed\n");
} else { } else {
@@ -99,7 +102,9 @@ static ssize_t ether_mac_loopback_store(struct device *dev,
netif_carrier_off(ndev); netif_carrier_off(ndev);
} }
/* Disabling the MAC Loopback Mode */ /* 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) { if (ret < 0) {
dev_err(pdata->dev, "Disabling MAC Loopback failed\n"); dev_err(pdata->dev, "Disabling MAC Loopback failed\n");
} else { } else {