Commit c7b7b483 authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller

bnx2x: Don't flush multicast MACs

When ndo_set_rx_mode() is called for bnx2x, as part of process of
configuring the new MAC address filters [both unicast & multicast]
driver begins by flushing the existing configuration and then iterating
over the network device's list of addresses and configures those instead.

This has the side-effect of creating a short gap where traffic wouldn't
be properly classified, as no filters are configured in HW.
While for unicasts this is rather insignificant [as unicast MACs don't
frequently change while interface is actually running],
for multicast traffic it does pose an issue as there are multicast-based
networks where new multicast groups would constantly be removed and
added.

This patch tries to remedy this [at least for the newer adapters] -
Instead of flushing & reconfiguring all existing multicast filters,
the driver would instead create the approximate hash match that would
result from the required filters. It would then compare it against the
currently configured approximate hash match, and only add and remove the
delta between those.
Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6546c78e
...@@ -12560,8 +12560,10 @@ static int bnx2x_init_mcast_macs_list(struct bnx2x *bp, ...@@ -12560,8 +12560,10 @@ static int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
kcalloc(mc_count, sizeof(*mc_mac), GFP_ATOMIC); kcalloc(mc_count, sizeof(*mc_mac), GFP_ATOMIC);
struct netdev_hw_addr *ha; struct netdev_hw_addr *ha;
if (!mc_mac) if (!mc_mac) {
BNX2X_ERR("Failed to allocate mc MAC list\n");
return -ENOMEM; return -ENOMEM;
}
INIT_LIST_HEAD(&p->mcast_list); INIT_LIST_HEAD(&p->mcast_list);
...@@ -12632,7 +12634,7 @@ static int bnx2x_set_uc_list(struct bnx2x *bp) ...@@ -12632,7 +12634,7 @@ static int bnx2x_set_uc_list(struct bnx2x *bp)
BNX2X_UC_LIST_MAC, &ramrod_flags); BNX2X_UC_LIST_MAC, &ramrod_flags);
} }
static int bnx2x_set_mc_list(struct bnx2x *bp) static int bnx2x_set_mc_list_e1x(struct bnx2x *bp)
{ {
struct net_device *dev = bp->dev; struct net_device *dev = bp->dev;
struct bnx2x_mcast_ramrod_params rparam = {NULL}; struct bnx2x_mcast_ramrod_params rparam = {NULL};
...@@ -12650,11 +12652,8 @@ static int bnx2x_set_mc_list(struct bnx2x *bp) ...@@ -12650,11 +12652,8 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
/* then, configure a new MACs list */ /* then, configure a new MACs list */
if (netdev_mc_count(dev)) { if (netdev_mc_count(dev)) {
rc = bnx2x_init_mcast_macs_list(bp, &rparam); rc = bnx2x_init_mcast_macs_list(bp, &rparam);
if (rc) { if (rc)
BNX2X_ERR("Failed to create multicast MACs list: %d\n",
rc);
return rc; return rc;
}
/* Now add the new MACs */ /* Now add the new MACs */
rc = bnx2x_config_mcast(bp, &rparam, rc = bnx2x_config_mcast(bp, &rparam,
...@@ -12669,6 +12668,42 @@ static int bnx2x_set_mc_list(struct bnx2x *bp) ...@@ -12669,6 +12668,42 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
return rc; return rc;
} }
static int bnx2x_set_mc_list(struct bnx2x *bp)
{
struct bnx2x_mcast_ramrod_params rparam = {NULL};
struct net_device *dev = bp->dev;
int rc = 0;
/* On older adapters, we need to flush and re-add filters */
if (CHIP_IS_E1x(bp))
return bnx2x_set_mc_list_e1x(bp);
rparam.mcast_obj = &bp->mcast_obj;
if (netdev_mc_count(dev)) {
rc = bnx2x_init_mcast_macs_list(bp, &rparam);
if (rc)
return rc;
/* Override the curently configured set of mc filters */
rc = bnx2x_config_mcast(bp, &rparam,
BNX2X_MCAST_CMD_SET);
if (rc < 0)
BNX2X_ERR("Failed to set a new multicast configuration: %d\n",
rc);
bnx2x_free_mcast_macs_list(&rparam);
} else {
/* If no mc addresses are required, flush the configuration */
rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
if (rc)
BNX2X_ERR("Failed to clear multicast configuration %d\n",
rc);
}
return rc;
}
/* If bp->state is OPEN, should be called with netif_addr_lock_bh() */ /* If bp->state is OPEN, should be called with netif_addr_lock_bh() */
static void bnx2x_set_rx_mode(struct net_device *dev) static void bnx2x_set_rx_mode(struct net_device *dev)
{ {
......
...@@ -536,6 +536,15 @@ enum bnx2x_mcast_cmd { ...@@ -536,6 +536,15 @@ enum bnx2x_mcast_cmd {
BNX2X_MCAST_CMD_CONT, BNX2X_MCAST_CMD_CONT,
BNX2X_MCAST_CMD_DEL, BNX2X_MCAST_CMD_DEL,
BNX2X_MCAST_CMD_RESTORE, BNX2X_MCAST_CMD_RESTORE,
/* Following this, multicast configuration should equal to approx
* the set of MACs provided [i.e., remove all else].
* The two sub-commands are used internally to decide whether a given
* bin is to be added or removed
*/
BNX2X_MCAST_CMD_SET,
BNX2X_MCAST_CMD_SET_ADD,
BNX2X_MCAST_CMD_SET_DEL,
}; };
struct bnx2x_mcast_obj { struct bnx2x_mcast_obj {
...@@ -635,7 +644,8 @@ struct bnx2x_mcast_obj { ...@@ -635,7 +644,8 @@ struct bnx2x_mcast_obj {
*/ */
void (*revert)(struct bnx2x *bp, void (*revert)(struct bnx2x *bp,
struct bnx2x_mcast_ramrod_params *p, struct bnx2x_mcast_ramrod_params *p,
int old_num_bins); int old_num_bins,
enum bnx2x_mcast_cmd cmd);
int (*get_registry_size)(struct bnx2x_mcast_obj *o); int (*get_registry_size)(struct bnx2x_mcast_obj *o);
void (*set_registry_size)(struct bnx2x_mcast_obj *o, int n); void (*set_registry_size)(struct bnx2x_mcast_obj *o, int n);
......
...@@ -573,17 +573,6 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf, ...@@ -573,17 +573,6 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf,
} }
} }
/* clear existing mcasts */
mcast.mcast_list_len = vf->mcast_list_len;
vf->mcast_list_len = mc_num;
rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_DEL);
if (rc) {
BNX2X_ERR("Failed to remove multicasts\n");
kfree(mc);
return rc;
}
/* update mcast list on the ramrod params */
if (mc_num) { if (mc_num) {
INIT_LIST_HEAD(&mcast.mcast_list); INIT_LIST_HEAD(&mcast.mcast_list);
for (i = 0; i < mc_num; i++) { for (i = 0; i < mc_num; i++) {
...@@ -594,12 +583,18 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf, ...@@ -594,12 +583,18 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf,
/* add new mcasts */ /* add new mcasts */
mcast.mcast_list_len = mc_num; mcast.mcast_list_len = mc_num;
rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_ADD); rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_SET);
if (rc) if (rc)
BNX2X_ERR("Faled to add multicasts\n"); BNX2X_ERR("Faled to set multicasts\n");
kfree(mc); } else {
/* clear existing mcasts */
rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_DEL);
if (rc)
BNX2X_ERR("Failed to remove multicasts\n");
} }
kfree(mc);
return rc; return rc;
} }
...@@ -1583,7 +1578,6 @@ int bnx2x_iov_nic_init(struct bnx2x *bp) ...@@ -1583,7 +1578,6 @@ int bnx2x_iov_nic_init(struct bnx2x *bp)
* It needs to be initialized here so that it can be safely * It needs to be initialized here so that it can be safely
* handled by a subsequent FLR flow. * handled by a subsequent FLR flow.
*/ */
vf->mcast_list_len = 0;
bnx2x_init_mcast_obj(bp, &vf->mcast_obj, 0xFF, bnx2x_init_mcast_obj(bp, &vf->mcast_obj, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
bnx2x_vf_sp(bp, vf, mcast_rdata), bnx2x_vf_sp(bp, vf, mcast_rdata),
......
...@@ -195,7 +195,6 @@ struct bnx2x_virtf { ...@@ -195,7 +195,6 @@ struct bnx2x_virtf {
int leading_rss; int leading_rss;
/* MCAST object */ /* MCAST object */
int mcast_list_len;
struct bnx2x_mcast_obj mcast_obj; struct bnx2x_mcast_obj mcast_obj;
/* RSS configuration object */ /* RSS configuration object */
......
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