Commit 94b3b542 authored by Igor Russkikh's avatar Igor Russkikh Committed by David S. Miller

net: aquantia: vlan unicast address list correct handling

Setting up macvlan/macvtap networks over atlantic NIC results
in no traffic over these networks because ndo_set_rx_mode did
not listed UC MACs as registered in unicast filter.

Here we fix that taking into account maximum number of UC
filters supported by hardware. If more than MAX addresses were
registered, we just enable promisc  and/or allmulti to pass
the traffic in.

We also remove MULTICAST_ADDRESS_MAX constant from aq_cfg since
thats not a configurable parameter at all.

Fixes: b21f502f ("net:ethernet:aquantia: Fix for multicast filter handling.")
Signed-off-by: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 96f1206d
...@@ -63,8 +63,6 @@ ...@@ -63,8 +63,6 @@
#define AQ_CFG_NAPI_WEIGHT 64U #define AQ_CFG_NAPI_WEIGHT 64U
#define AQ_CFG_MULTICAST_ADDRESS_MAX 32U
/*#define AQ_CFG_MAC_ADDR_PERMANENT {0x30, 0x0E, 0xE3, 0x12, 0x34, 0x56}*/ /*#define AQ_CFG_MAC_ADDR_PERMANENT {0x30, 0x0E, 0xE3, 0x12, 0x34, 0x56}*/
#define AQ_NIC_FC_OFF 0U #define AQ_NIC_FC_OFF 0U
......
...@@ -98,6 +98,8 @@ struct aq_stats_s { ...@@ -98,6 +98,8 @@ struct aq_stats_s {
#define AQ_HW_MEDIA_TYPE_TP 1U #define AQ_HW_MEDIA_TYPE_TP 1U
#define AQ_HW_MEDIA_TYPE_FIBRE 2U #define AQ_HW_MEDIA_TYPE_FIBRE 2U
#define AQ_HW_MULTICAST_ADDRESS_MAX 32U
struct aq_hw_s { struct aq_hw_s {
atomic_t flags; atomic_t flags;
u8 rbl_enabled:1; u8 rbl_enabled:1;
...@@ -177,7 +179,7 @@ struct aq_hw_ops { ...@@ -177,7 +179,7 @@ struct aq_hw_ops {
unsigned int packet_filter); unsigned int packet_filter);
int (*hw_multicast_list_set)(struct aq_hw_s *self, int (*hw_multicast_list_set)(struct aq_hw_s *self,
u8 ar_mac[AQ_CFG_MULTICAST_ADDRESS_MAX] u8 ar_mac[AQ_HW_MULTICAST_ADDRESS_MAX]
[ETH_ALEN], [ETH_ALEN],
u32 count); u32 count);
......
...@@ -135,17 +135,10 @@ static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr) ...@@ -135,17 +135,10 @@ static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr)
static void aq_ndev_set_multicast_settings(struct net_device *ndev) static void aq_ndev_set_multicast_settings(struct net_device *ndev)
{ {
struct aq_nic_s *aq_nic = netdev_priv(ndev); struct aq_nic_s *aq_nic = netdev_priv(ndev);
int err = 0;
err = aq_nic_set_packet_filter(aq_nic, ndev->flags); aq_nic_set_packet_filter(aq_nic, ndev->flags);
if (err < 0)
return;
if (netdev_mc_count(ndev)) { aq_nic_set_multicast_list(aq_nic, ndev);
err = aq_nic_set_multicast_list(aq_nic, ndev);
if (err < 0)
return;
}
} }
static const struct net_device_ops aq_ndev_ops = { static const struct net_device_ops aq_ndev_ops = {
......
...@@ -563,34 +563,41 @@ int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags) ...@@ -563,34 +563,41 @@ int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags)
int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev)
{ {
unsigned int packet_filter = self->packet_filter;
struct netdev_hw_addr *ha = NULL; struct netdev_hw_addr *ha = NULL;
unsigned int i = 0U; unsigned int i = 0U;
self->mc_list.count = 0U; self->mc_list.count = 0;
if (netdev_uc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) {
netdev_for_each_mc_addr(ha, ndev) { packet_filter |= IFF_PROMISC;
ether_addr_copy(self->mc_list.ar[i++], ha->addr); } else {
++self->mc_list.count; netdev_for_each_uc_addr(ha, ndev) {
ether_addr_copy(self->mc_list.ar[i++], ha->addr);
if (i >= AQ_CFG_MULTICAST_ADDRESS_MAX) if (i >= AQ_HW_MULTICAST_ADDRESS_MAX)
break; break;
}
} }
if (i >= AQ_CFG_MULTICAST_ADDRESS_MAX) { if (i + netdev_mc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) {
/* Number of filters is too big: atlantic does not support this. packet_filter |= IFF_ALLMULTI;
* Force all multi filter to support this.
* With this we disable all UC filters and setup "all pass"
* multicast mask
*/
self->packet_filter |= IFF_ALLMULTI;
self->aq_nic_cfg.mc_list_count = 0;
return self->aq_hw_ops->hw_packet_filter_set(self->aq_hw,
self->packet_filter);
} else { } else {
return self->aq_hw_ops->hw_multicast_list_set(self->aq_hw, netdev_for_each_mc_addr(ha, ndev) {
self->mc_list.ar, ether_addr_copy(self->mc_list.ar[i++], ha->addr);
self->mc_list.count);
if (i >= AQ_HW_MULTICAST_ADDRESS_MAX)
break;
}
}
if (i > 0 && i < AQ_HW_MULTICAST_ADDRESS_MAX) {
packet_filter |= IFF_MULTICAST;
self->mc_list.count = i;
self->aq_hw_ops->hw_multicast_list_set(self->aq_hw,
self->mc_list.ar,
self->mc_list.count);
} }
return aq_nic_set_packet_filter(self, packet_filter);
} }
int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu) int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu)
......
...@@ -75,7 +75,7 @@ struct aq_nic_s { ...@@ -75,7 +75,7 @@ struct aq_nic_s {
struct aq_hw_link_status_s link_status; struct aq_hw_link_status_s link_status;
struct { struct {
u32 count; u32 count;
u8 ar[AQ_CFG_MULTICAST_ADDRESS_MAX][ETH_ALEN]; u8 ar[AQ_HW_MULTICAST_ADDRESS_MAX][ETH_ALEN];
} mc_list; } mc_list;
struct pci_dev *pdev; struct pci_dev *pdev;
......
...@@ -765,7 +765,7 @@ static int hw_atl_a0_hw_packet_filter_set(struct aq_hw_s *self, ...@@ -765,7 +765,7 @@ static int hw_atl_a0_hw_packet_filter_set(struct aq_hw_s *self,
static int hw_atl_a0_hw_multicast_list_set(struct aq_hw_s *self, static int hw_atl_a0_hw_multicast_list_set(struct aq_hw_s *self,
u8 ar_mac u8 ar_mac
[AQ_CFG_MULTICAST_ADDRESS_MAX] [AQ_HW_MULTICAST_ADDRESS_MAX]
[ETH_ALEN], [ETH_ALEN],
u32 count) u32 count)
{ {
......
...@@ -784,7 +784,7 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self, ...@@ -784,7 +784,7 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self,
static int hw_atl_b0_hw_multicast_list_set(struct aq_hw_s *self, static int hw_atl_b0_hw_multicast_list_set(struct aq_hw_s *self,
u8 ar_mac u8 ar_mac
[AQ_CFG_MULTICAST_ADDRESS_MAX] [AQ_HW_MULTICAST_ADDRESS_MAX]
[ETH_ALEN], [ETH_ALEN],
u32 count) u32 count)
{ {
...@@ -812,7 +812,7 @@ static int hw_atl_b0_hw_multicast_list_set(struct aq_hw_s *self, ...@@ -812,7 +812,7 @@ static int hw_atl_b0_hw_multicast_list_set(struct aq_hw_s *self,
hw_atl_rpfl2_uc_flr_en_set(self, hw_atl_rpfl2_uc_flr_en_set(self,
(self->aq_nic_cfg->is_mc_list_enabled), (self->aq_nic_cfg->is_mc_list_enabled),
HW_ATL_B0_MAC_MIN + i); HW_ATL_B0_MAC_MIN + i);
} }
err = aq_hw_err_from_flags(self); err = aq_hw_err_from_flags(self);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment