nvethernet: eqos: Use single API to enable/configure filter

Update OSI driver calls in ioctl path and set_rx_mode
to use single API

Bug 2715384

Change-Id: I521471060a31b985ea2f17a1e5ef91830820c285
Signed-off-by: Rakesh Goyal <rgoyal@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2216069
GVS: Gerrit_Virtual_Submit
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Rakesh Goyal
2019-10-12 01:03:24 +05:30
committed by Revanth Kumar Uppala
parent a95d243909
commit c45ba21f05
3 changed files with 172 additions and 197 deletions

View File

@@ -1253,7 +1253,6 @@ static int ether_open(struct net_device *dev)
/* As all registers reset as part of ether_close(), reset private /* As all registers reset as part of ether_close(), reset private
* structure variable as well */ * structure variable as well */
pdata->vlan_hash_filtering = OSI_PERFECT_FILTER_MODE; pdata->vlan_hash_filtering = OSI_PERFECT_FILTER_MODE;
pdata->l3_l4_filter = OSI_DISABLE;
pdata->l2_filtering_mode = OSI_PERFECT_FILTER_MODE; pdata->l2_filtering_mode = OSI_PERFECT_FILTER_MODE;
/* Initialize PTP */ /* Initialize PTP */
@@ -1768,53 +1767,69 @@ static int ether_start_xmit(struct sk_buff *skb, struct net_device *ndev)
* *
* @note MAC and PHY need to be initialized. * @note MAC and PHY need to be initialized.
* *
* @retval 0 if perfect filtering is seleted * @retval 0 on success
* @retval 1 if hash filtering is seleted. * @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 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 netdev_hw_addr *ha; struct netdev_hw_addr *ha;
int ret = OSI_PERFECT_FILTER_MODE, i = 1; unsigned int i = 1;
int cnt; int ret = -1;
if (filter == NULL) {
dev_err(pdata->dev, "filter is NULL\n");
return ret;
}
memset(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,
"select HASH FILTERING for mc addresses is not supported in SW\n"); "HASH FILTERING for mc addresses not Supported in SW\n");
/* only perfect filter is supported */ filter->oper_mode = (OSI_OPER_EN_PERFECT |
OSI_OPER_DIS_PROMISC |
OSI_OPER_DIS_ALLMULTI);
return osi_l2_filter(osi_core, filter);
/* 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 |
OSI_OPER_EN_PROMISC |
OSI_OPER_DIS_ALLMULTI);
dev_dbg(pdata->dev, "enabling Promiscuous mode\n");
return osi_l2_filter(osi_core, filter);
} 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), netdev_mc_count(dev), pdata->num_mac_addr_regs);
pdata->num_mac_addr_regs);
/* Clear previously set filters */
for (cnt = 1; cnt <= pdata->last_uc_filter_index; cnt++) {
if (osi_update_mac_addr_low_high_reg(osi_core,
(unsigned int)cnt,
NULL,
OSI_DISABLE, 0x0,
OSI_AMASK_DISABLE,
OSI_DA_MATCH) !=
0) {
dev_err(pdata->dev, "issue in cleaning mc list\n");
}
}
filter->oper_mode = (OSI_OPER_EN_PERFECT |
OSI_OPER_ADDR_UPDATE |
OSI_OPER_DIS_PROMISC |
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, i, ha->addr[0], ha->addr[1], ha->addr[2],
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]);
if (osi_update_mac_addr_low_high_reg(osi_core, filter->index = i;
(unsigned int)i, filter->mac_address = ha->addr;
ha->addr, filter->dma_routing = OSI_DISABLE;
OSI_DISABLE, 0x0, filter->dma_chan = 0x0;
OSI_AMASK_DISABLE, filter->addr_mask = OSI_AMASK_DISABLE;
OSI_DA_MATCH) != filter->src_dest = OSI_DA_MATCH;
0) { ret = osi_l2_filter(osi_core, filter);
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;
return ret;
} }
if (i == EQOS_MAX_MAC_ADDRESS_FILTER - 1) { if (i == EQOS_MAX_MAC_ADDRESS_FILTER - 1) {
@@ -1823,8 +1838,8 @@ static int ether_prepare_mc_list(struct net_device *dev)
} }
i++; i++;
} }
/* preserve last MC filter index to passon to UC */ /* preserve last filter index to pass on to UC */
pdata->last_mc_filter_index = i - 1; pdata->last_filter_index = i - 1;
} }
return ret; return ret;
@@ -1841,53 +1856,68 @@ static int ether_prepare_mc_list(struct net_device *dev)
* *
* @note MAC and PHY need to be initialized. * @note MAC and PHY need to be initialized.
* *
* @retval 0 if perfect filtering is seleted * @retval 0 on success
* @retval 1 if hash filtering is seleted. * @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 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;
int i = pdata->last_mc_filter_index + 1; /* last valid MC/MAC DA + 1 should be start of UC addresses */
int ret = OSI_PERFECT_FILTER_MODE; unsigned int i = pdata->last_filter_index + 1;
struct netdev_hw_addr *ha; struct netdev_hw_addr *ha;
int cnt; int ret = -1;
if (filter == NULL) {
dev_err(pdata->dev, "filter is NULL\n");
return ret;
}
memset(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,
"select HASH FILTERING for uc addresses not Supported in SW\n"); "HASH FILTERING for uc addresses not Supported in SW\n");
/* only perfect filter is supported */ /* Perfect filtering for multicast */
filter->oper_mode = (OSI_OPER_EN_PERFECT |
OSI_OPER_DIS_PROMISC |
OSI_OPER_DIS_ALLMULTI);
return osi_l2_filter(osi_core, filter);
} else if (netdev_uc_count(dev) > (pdata->num_mac_addr_regs - i)) {
/* switch to PROMISCUOUS mode */
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);
} 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));
/* Clear previously set filters */
for (cnt = pdata->last_mc_filter_index + 1;
cnt <= pdata->last_uc_filter_index; cnt++) {
if (osi_update_mac_addr_low_high_reg(osi_core,
(unsigned int)cnt,
NULL,
OSI_DISABLE, 0x0,
OSI_AMASK_DISABLE,
OSI_DA_MATCH) !=
0) {
dev_err(pdata->dev, "issue in cleaning uc list\n");
}
}
filter->oper_mode = (OSI_OPER_EN_PERFECT |
OSI_OPER_ADDR_UPDATE |
OSI_OPER_DIS_PROMISC |
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]);
if (osi_update_mac_addr_low_high_reg(osi_core, filter->index = i;
(unsigned int)i, filter->mac_address = ha->addr;
ha->addr, filter->dma_routing = OSI_DISABLE;
OSI_DISABLE, 0x0, filter->dma_chan = 0x0;
OSI_AMASK_DISABLE, filter->addr_mask = OSI_AMASK_DISABLE;
OSI_DA_MATCH) != filter->src_dest = OSI_DA_MATCH;
0) { ret = osi_l2_filter(osi_core, filter);
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;
return ret;
} }
if (i == EQOS_MAX_MAC_ADDRESS_FILTER - 1) { if (i == EQOS_MAX_MAC_ADDRESS_FILTER - 1) {
@@ -1896,7 +1926,7 @@ static int ether_prepare_uc_list(struct net_device *dev)
} }
i++; i++;
} }
pdata->last_uc_filter_index = i - 1; pdata->last_filter_index = i - 1;
} }
return ret; return ret;
@@ -1916,57 +1946,67 @@ 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 = {0}; struct osi_filter filter;
int mode, ret; /* store last call last_uc_filter_index in temporary variable */
int last_index = pdata->last_filter_index;
int ret = -1;
unsigned int i = 0;
memset(&filter, 0x0, sizeof(struct osi_filter));
if ((dev->flags & IFF_PROMISC) == IFF_PROMISC) { if ((dev->flags & IFF_PROMISC) == IFF_PROMISC) {
filter.oper_mode = (OSI_OPER_DIS_PERFECT | OSI_OPER_EN_PROMISC |
OSI_OPER_DIS_ALLMULTI);
dev_dbg(pdata->dev, "enabling Promiscuous mode\n"); dev_dbg(pdata->dev, "enabling Promiscuous mode\n");
filter.pr_mode = OSI_ENABLE; ret = osi_l2_filter(osi_core, &filter);
if (ret < 0) {
dev_err(pdata->dev, "Setting Promiscuous mode failed\n");
}
return;
} else if ((dev->flags & IFF_ALLMULTI) == IFF_ALLMULTI) { } else if ((dev->flags & IFF_ALLMULTI) == IFF_ALLMULTI) {
filter.oper_mode = (OSI_OPER_EN_ALLMULTI |
OSI_OPER_DIS_PERFECT |
OSI_OPER_DIS_PROMISC);
dev_dbg(pdata->dev, "pass all multicast pkt\n"); dev_dbg(pdata->dev, "pass all multicast pkt\n");
filter.pm_mode = OSI_ENABLE; ret = osi_l2_filter(osi_core, &filter);
if (ret < 0) {
dev_err(pdata->dev, "Setting All Multicast allow mode failed\n");
}
return;
} else if (!netdev_mc_empty(dev)) { } else if (!netdev_mc_empty(dev)) {
dev_dbg(pdata->dev, "pass list of multicast pkt\n"); if (ether_prepare_mc_list(dev, &filter) != 0) {
if (netdev_mc_count(dev) > (pdata->num_mac_addr_regs - 1)) { dev_err(pdata->dev, "Setting MC address failed\n");
/* switch to PROMISCUOUS mode */
filter.pr_mode = OSI_ENABLE;
} else {
mode = ether_prepare_mc_list(dev);
if (mode == OSI_HASH_FILTER_MODE) {
/* Hash filtering for multicast */
filter.hmc_mode = OSI_ENABLE;
} else {
/* Perfect filtering for multicast */
filter.hmc_mode = OSI_DISABLE;
filter.hpf_mode = OSI_ENABLE;
}
} }
} else { } else {
pdata->last_mc_filter_index = 0; pdata->last_filter_index = 0;
} }
/* Handle multiple unicast addresses */ if (!netdev_uc_empty(dev)) {
if (netdev_uc_count(dev) > (pdata->num_mac_addr_regs - 1)) { if (ether_prepare_uc_list(dev, &filter) != 0) {
/* switch to PROMISCUOUS mode */ dev_err(pdata->dev, "Setting UC address failed\n");
filter.pr_mode = OSI_ENABLE;
} else if (!netdev_uc_empty(dev)) {
mode = ether_prepare_uc_list(dev);
if (mode == OSI_HASH_FILTER_MODE) {
/* Hash filtering for unicast */
filter.huc_mode = OSI_ENABLE;
} else {
/* Perfect filtering for unicast */
filter.huc_mode = OSI_DISABLE;
filter.hpf_mode = OSI_ENABLE;
} }
} else {
pdata->last_uc_filter_index = pdata->last_mc_filter_index;
} }
ret = osi_config_mac_pkt_filter_reg(osi_core, filter); /* Reset the filter structure to avoid any old value */
if (ret != 0) { memset(&filter, 0x0, sizeof(struct osi_filter));
dev_err(pdata->dev, "osi_config_mac_pkt_filter_reg failed\n"); /* 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.mac_address = NULL;
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);
if (ret < 0) {
dev_err(pdata->dev, "Invalidating expired L2 filter failed\n");
return;
}
} }
return;
} }
/** /**
@@ -3675,6 +3715,8 @@ static int ether_resume(struct ether_priv_data *pdata)
osi_start_mac(osi_core); osi_start_mac(osi_core);
/* start phy */ /* start phy */
phy_start(pdata->phydev); phy_start(pdata->phydev);
/* call dev_set_rx_mode so it will be serialized and avoid race*/
dev_set_rx_mode(ndev);
/* start network queues */ /* start network queues */
netif_tx_start_all_queues(ndev); netif_tx_start_all_queues(ndev);
/* re-start workqueue */ /* re-start workqueue */

View File

@@ -278,15 +278,11 @@ struct ether_priv_data {
spinlock_t rlock; spinlock_t rlock;
/** max address register count, 2*mac_addr64_sel */ /** max address register count, 2*mac_addr64_sel */
int num_mac_addr_regs; int num_mac_addr_regs;
/** Last Multicast address reg filter index, If 0,no MC address added */ /** Last address reg filter index added in last call*/
int last_mc_filter_index; int last_filter_index;
/** Last Unicast address reg filter index, If 0,no MC address added */
int last_uc_filter_index;
/** L3_l4 filter enabled 1: enabled */
unsigned int l3_l4_filter;
/** vlan hash filter 1: hash, 0: perfect */ /** vlan hash filter 1: hash, 0: perfect */
unsigned int vlan_hash_filtering; unsigned int vlan_hash_filtering;
/** PTP clock operations structure */ /** L2 filter mode */
unsigned int l2_filtering_mode; unsigned int l2_filtering_mode;
/** PTP clock operations structure */ /** PTP clock operations structure */
struct ptp_clock_info ptp_clock_ops; struct ptp_clock_info ptp_clock_ops;

View File

@@ -181,21 +181,10 @@ static int ether_config_l3_l4_filtering(struct net_device *dev,
unsigned int filter_flags) unsigned int filter_flags)
{ {
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;
int ret = 0;
if (filter_flags == pdata->l3_l4_filter) { dev_err(pdata->dev, "%s: This ioctl is deprecated, directly set the filter using ioctl command EQOS_IPV4/IPV6/TCP/UDP_FILTERING_CMD instead\n",
dev_err(pdata->dev, "L3/L4 filtering is already %d\n", __func__);
filter_flags); return -1;
return ret;
}
ret = osi_config_l3_l4_filter_enable(osi_core, filter_flags);
if (ret == 0) {
pdata->l3_l4_filter = filter_flags;
}
return ret;
} }
/** /**
@@ -225,6 +214,7 @@ static int ether_config_ip4_filters(struct net_device *dev,
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_l3_l4_filter l_l3_filter;
unsigned int is_l4_filter = OSI_DISABLE;
int ret = -EINVAL; int ret = -EINVAL;
if (pdata->hw_feat.l3l4_filter_num == OSI_DISABLE) { if (pdata->hw_feat.l3l4_filter_num == OSI_DISABLE) {
@@ -250,31 +240,8 @@ static int ether_config_ip4_filters(struct net_device *dev,
return ret; return ret;
} }
/* enable IPFE bit in MAC_Packet_Filter for L3/L4 if already not */ return osi_l3l4_filter(osi_core, l_l3_filter, OSI_IP4_FILTER,
if (pdata->l3_l4_filter == OSI_DISABLE) { OSI_DISABLE, OSI_CHAN_ANY, is_l4_filter);
ret = osi_config_l3_l4_filter_enable(osi_core, OSI_ENABLE);
if (ret == 0) {
pdata->l3_l4_filter = OSI_ENABLE;
}
}
/* configure the L3 filters */
ret = osi_config_l3_filters(osi_core, l_l3_filter.filter_no,
l_l3_filter.filter_enb_dis,
OSI_IP4_FILTER,
l_l3_filter.src_dst_addr_match,
l_l3_filter.perfect_inverse_match,
OSI_DISABLE, 0x0U);
if (ret != 0) {
dev_err(pdata->dev, "osi_config_l3_filters failed\n");
return ret;
}
ret = osi_update_ip4_addr(osi_core, l_l3_filter.filter_no,
l_l3_filter.ip4_addr,
l_l3_filter.src_dst_addr_match);
return ret;
} }
/** /**
@@ -303,6 +270,7 @@ static int ether_config_ip6_filters(struct net_device *dev,
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_l3_l4_filter l_l3_filter;
unsigned int is_l4_filter = OSI_DISABLE;
int ret = -EINVAL; int ret = -EINVAL;
if (pdata->hw_feat.l3l4_filter_num == OSI_DISABLE) { if (pdata->hw_feat.l3l4_filter_num == OSI_DISABLE) {
@@ -328,28 +296,8 @@ static int ether_config_ip6_filters(struct net_device *dev,
return ret; return ret;
} }
/* enable IPFE bit in MAC_Packet_Filter for L3/L4 if already not */ return osi_l3l4_filter(osi_core, l_l3_filter, OSI_IP6_FILTER,
if (pdata->l3_l4_filter == OSI_DISABLE) { OSI_DISABLE, OSI_CHAN_ANY, is_l4_filter);
ret = osi_config_l3_l4_filter_enable(osi_core, OSI_ENABLE);
if (ret == 0) {
pdata->l3_l4_filter = OSI_ENABLE;
}
}
/* configure the L3 filters */
ret = osi_config_l3_filters(osi_core, l_l3_filter.filter_no,
l_l3_filter.filter_enb_dis,
OSI_IP6_FILTER,
l_l3_filter.src_dst_addr_match,
l_l3_filter.perfect_inverse_match,
OSI_DISABLE, 0x0U);
if (ret != 0) {
dev_err(pdata->dev, "osi_config_l3_filters failed\n");
return ret;
}
return osi_update_ip6_addr(osi_core, l_l3_filter.filter_no,
l_l3_filter.ip6_addr);
} }
/** /**
@@ -381,6 +329,7 @@ static int ether_config_tcp_udp_filters(struct net_device *dev,
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_l3_l4_filter l_l4_filter;
unsigned int is_l4_filter = OSI_ENABLE;
int ret = -EINVAL; int ret = -EINVAL;
if (ifdata->ptr == NULL) { if (ifdata->ptr == NULL) {
@@ -407,31 +356,8 @@ static int ether_config_tcp_udp_filters(struct net_device *dev,
return ret; return ret;
} }
/* enable IPFE bit in MAC_Packet_Filter for L3/L4 if already not */ return osi_l3l4_filter(osi_core, l_l4_filter, tcp_udp,
if (pdata->l3_l4_filter == OSI_DISABLE) { OSI_DISABLE, OSI_CHAN_ANY, is_l4_filter);
ret = osi_config_l3_l4_filter_enable(osi_core, OSI_ENABLE);
if (ret == 0) {
pdata->l3_l4_filter = OSI_ENABLE;
}
}
/* configure the L4 filters */
ret = osi_config_l4_filters(osi_core, l_l4_filter.filter_no,
l_l4_filter.filter_enb_dis,
tcp_udp,
l_l4_filter.src_dst_addr_match,
l_l4_filter.perfect_inverse_match,
OSI_DISABLE, 0x0U);
if (ret != 0) {
dev_err(pdata->dev, "osi_config_l4_filters failed\n");
return ret;
}
ret = osi_update_l4_port_no(osi_core, l_l4_filter.filter_no,
l_l4_filter.port_no,
l_l4_filter.src_dst_addr_match);
return ret;
} }
/** /**
@@ -477,8 +403,7 @@ static int ether_config_vlan_filter(struct net_device *dev,
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;
} }
/* configure the vlan filter FIXME: Current code supports VLAN
filtering for last VLAN tag/id added or default tag/vid 1. */
ret = osi_config_vlan_filtering(osi_core, l_vlan_filter.filter_enb_dis, ret = osi_config_vlan_filtering(osi_core, l_vlan_filter.filter_enb_dis,
l_vlan_filter.perfect_hash, l_vlan_filter.perfect_hash,
l_vlan_filter.perfect_inverse_match); l_vlan_filter.perfect_inverse_match);
@@ -513,8 +438,11 @@ 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;
int ret = -EINVAL; int ret = -EINVAL;
memset(&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",
__func__, ifdata->ifcmd); __func__, ifdata->ifcmd);
@@ -525,6 +453,7 @@ static int ether_config_l2_da_filter(struct net_device *dev,
sizeof(struct osi_l2_da_filter)) != 0U) { sizeof(struct osi_l2_da_filter)) != 0U) {
return -EFAULT; return -EFAULT;
} }
if (l_l2_da_filter.perfect_hash == OSI_HASH_FILTER_MODE) { if (l_l2_da_filter.perfect_hash == OSI_HASH_FILTER_MODE) {
dev_err(pdata->dev, dev_err(pdata->dev,
"select HASH FILTERING for L2 DA is not Supported in SW\n"); "select HASH FILTERING for L2 DA is not Supported in SW\n");
@@ -537,8 +466,16 @@ static int ether_config_l2_da_filter(struct net_device *dev,
} }
/* configure L2 DA perfect/inverse_matching */ /* configure L2 DA perfect/inverse_matching */
ret = osi_config_l2_da_perfect_inverse_match(osi_core, if (l_l2_da_filter.perfect_inverse_match == OSI_ENABLE) {
l_l2_da_filter.perfect_inverse_match); filter.oper_mode |= OSI_OPER_EN_L2_DA_INV;
} else {
filter.oper_mode |= OSI_OPER_DIS_L2_DA_INV;
}
ret = osi_l2_filter(osi_core, &filter);
if (ret != 0) {
dev_err(pdata->dev, "setting L2_DA_INV failed\n");
}
return ret; return ret;
} }