提交 92fbb1df 编写于 作者: S Sriharsha Basavapatna 提交者: David S. Miller

be2net: Avoid unnecessary firmware updates of multicast list

Eachtime the ndo_set_rx_mode() routine is called, the driver programs the
multicast list in the adapter without checking if there are any changes to
the list. This leads to a flood of RX_FILTER cmds when a number of vlan
interfaces are configured over the device, as the ndo_ gets
called for each vlan interface. To avoid this, we now use __dev_mc_sync()
and __dev_uc_sync() API, but only to detect if there is a change in the
mc/uc lists. Now that we use this API, the code has to be-designed to
issue these API calls for each invocation of the be_set_rx_mode() call.
Signed-off-by: NSriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: NSathya Perla <sathya.perla@broadcom.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 0aff1fbf
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -573,6 +573,8 @@ struct be_adapter {
u32 uc_macs; /* Count of secondary UC MAC programmed */
unsigned long vids[BITS_TO_LONGS(VLAN_N_VID)];
u16 vlans_added;
bool update_uc_list;
bool update_mc_list;
u32 beacon_state; /* for set_phys_id */
......
......@@ -1420,8 +1420,8 @@ static int be_vid_config(struct be_adapter *adapter)
u16 num = 0, i = 0;
int status = 0;
/* No need to further configure vids if in promiscuous mode */
if (be_in_all_promisc(adapter))
/* No need to change the VLAN state if the I/F is in promiscuous */
if (adapter->netdev->flags & IFF_PROMISC)
return 0;
if (adapter->vlans_added > be_max_vlans(adapter))
......@@ -1483,12 +1483,6 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid)
return be_vid_config(adapter);
}
static void be_clear_all_promisc(struct be_adapter *adapter)
{
be_cmd_rx_filter(adapter, BE_IF_FLAGS_ALL_PROMISCUOUS, OFF);
adapter->if_flags &= ~BE_IF_FLAGS_ALL_PROMISCUOUS;
}
static void be_set_all_promisc(struct be_adapter *adapter)
{
be_cmd_rx_filter(adapter, BE_IF_FLAGS_ALL_PROMISCUOUS, ON);
......@@ -1507,42 +1501,144 @@ static void be_set_mc_promisc(struct be_adapter *adapter)
adapter->if_flags |= BE_IF_FLAGS_MCAST_PROMISCUOUS;
}
static void be_set_mc_list(struct be_adapter *adapter)
static void be_set_uc_promisc(struct be_adapter *adapter)
{
int status;
status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_MULTICAST, ON);
if (adapter->if_flags & BE_IF_FLAGS_PROMISCUOUS)
return;
status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_PROMISCUOUS, ON);
if (!status)
adapter->if_flags &= ~BE_IF_FLAGS_MCAST_PROMISCUOUS;
else
adapter->if_flags |= BE_IF_FLAGS_PROMISCUOUS;
}
static void be_clear_uc_promisc(struct be_adapter *adapter)
{
int status;
if (!(adapter->if_flags & BE_IF_FLAGS_PROMISCUOUS))
return;
status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_PROMISCUOUS, OFF);
if (!status)
adapter->if_flags &= ~BE_IF_FLAGS_PROMISCUOUS;
}
/* The below 2 functions are the callback args for __dev_mc_sync/dev_uc_sync().
* We use a single callback function for both sync and unsync. We really don't
* add/remove addresses through this callback. But, we use it to detect changes
* to the uc/mc lists. The entire uc/mc list is programmed in be_set_rx_mode().
*/
static int be_uc_list_update(struct net_device *netdev,
const unsigned char *addr)
{
struct be_adapter *adapter = netdev_priv(netdev);
adapter->update_uc_list = true;
return 0;
}
static int be_mc_list_update(struct net_device *netdev,
const unsigned char *addr)
{
struct be_adapter *adapter = netdev_priv(netdev);
adapter->update_mc_list = true;
return 0;
}
static void be_set_mc_list(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
bool mc_promisc = false;
int status;
__dev_mc_sync(netdev, be_mc_list_update, be_mc_list_update);
if (netdev->flags & IFF_PROMISC) {
adapter->update_mc_list = false;
} else if (netdev->flags & IFF_ALLMULTI ||
netdev_mc_count(netdev) > be_max_mc(adapter)) {
/* Enable multicast promisc if num configured exceeds
* what we support
*/
mc_promisc = true;
adapter->update_mc_list = false;
} else if (adapter->if_flags & BE_IF_FLAGS_MCAST_PROMISCUOUS) {
/* Update mc-list unconditionally if the iface was previously
* in mc-promisc mode and now is out of that mode.
*/
adapter->update_mc_list = true;
}
if (mc_promisc) {
be_set_mc_promisc(adapter);
} else if (adapter->update_mc_list) {
status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_MULTICAST, ON);
if (!status)
adapter->if_flags &= ~BE_IF_FLAGS_MCAST_PROMISCUOUS;
else
be_set_mc_promisc(adapter);
adapter->update_mc_list = false;
}
}
static void be_clear_mc_list(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
__dev_mc_unsync(netdev, NULL);
be_cmd_rx_filter(adapter, BE_IF_FLAGS_MULTICAST, OFF);
}
static void be_set_uc_list(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct netdev_hw_addr *ha;
bool uc_promisc = false;
int i = 1; /* First slot is claimed by the Primary MAC */
for (; adapter->uc_macs > 0; adapter->uc_macs--, i++)
be_cmd_pmac_del(adapter, adapter->if_handle,
adapter->pmac_id[i], 0);
__dev_uc_sync(netdev, be_uc_list_update, be_uc_list_update);
if (netdev_uc_count(adapter->netdev) > be_max_uc(adapter)) {
be_set_all_promisc(adapter);
return;
if (netdev->flags & IFF_PROMISC) {
adapter->update_uc_list = false;
} else if (netdev_uc_count(netdev) > (be_max_uc(adapter) - 1)) {
uc_promisc = true;
adapter->update_uc_list = false;
} else if (adapter->if_flags & BE_IF_FLAGS_PROMISCUOUS) {
/* Update uc-list unconditionally if the iface was previously
* in uc-promisc mode and now is out of that mode.
*/
adapter->update_uc_list = true;
}
netdev_for_each_uc_addr(ha, adapter->netdev) {
adapter->uc_macs++; /* First slot is for Primary MAC */
be_cmd_pmac_add(adapter, (u8 *)ha->addr, adapter->if_handle,
&adapter->pmac_id[adapter->uc_macs], 0);
if (uc_promisc) {
be_set_uc_promisc(adapter);
} else if (adapter->update_uc_list) {
be_clear_uc_promisc(adapter);
for (; adapter->uc_macs > 0; adapter->uc_macs--, i++)
be_cmd_pmac_del(adapter, adapter->if_handle,
adapter->pmac_id[i], 0);
netdev_for_each_uc_addr(ha, adapter->netdev) {
adapter->uc_macs++; /* First slot is for Primary MAC */
be_cmd_pmac_add(adapter,
(u8 *)ha->addr, adapter->if_handle,
&adapter->pmac_id[adapter->uc_macs], 0);
}
adapter->update_uc_list = false;
}
}
static void be_clear_uc_list(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
int i;
__dev_uc_unsync(netdev, NULL);
for (i = 1; i < (adapter->uc_macs + 1); i++)
be_cmd_pmac_del(adapter, adapter->if_handle,
adapter->pmac_id[i], 0);
......@@ -1554,27 +1650,17 @@ static void be_set_rx_mode(struct net_device *netdev)
struct be_adapter *adapter = netdev_priv(netdev);
if (netdev->flags & IFF_PROMISC) {
be_set_all_promisc(adapter);
return;
}
/* Interface was previously in promiscuous mode; disable it */
if (be_in_all_promisc(adapter)) {
be_clear_all_promisc(adapter);
if (adapter->vlans_added)
be_vid_config(adapter);
}
/* Enable multicast promisc if num configured exceeds what we support */
if (netdev->flags & IFF_ALLMULTI ||
netdev_mc_count(netdev) > be_max_mc(adapter)) {
be_set_mc_promisc(adapter);
return;
if (!be_in_all_promisc(adapter))
be_set_all_promisc(adapter);
} else if (be_in_all_promisc(adapter)) {
/* We need to re-program the vlan-list or clear
* vlan-promisc mode (if needed) when the interface
* comes out of promisc mode.
*/
be_vid_config(adapter);
}
if (netdev_uc_count(netdev) != adapter->uc_macs)
be_set_uc_list(adapter);
be_set_uc_list(adapter);
be_set_mc_list(adapter);
}
......@@ -3426,6 +3512,7 @@ static void be_disable_if_filters(struct be_adapter *adapter)
adapter->pmac_id[0], 0);
be_clear_uc_list(adapter);
be_clear_mc_list(adapter);
/* The IFACE flags are enabled in the open path and cleared
* in the close path. When a VF gets detached from the host and
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部