|
@@ -12563,43 +12563,64 @@ static int bnx2x_close(struct net_device *dev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
|
|
|
- struct bnx2x_mcast_ramrod_params *p)
|
|
|
+struct bnx2x_mcast_list_elem_group
|
|
|
{
|
|
|
- int mc_count = netdev_mc_count(bp->dev);
|
|
|
- struct bnx2x_mcast_list_elem *mc_mac =
|
|
|
- kcalloc(mc_count, sizeof(*mc_mac), GFP_ATOMIC);
|
|
|
- struct netdev_hw_addr *ha;
|
|
|
+ struct list_head mcast_group_link;
|
|
|
+ struct bnx2x_mcast_list_elem mcast_elems[];
|
|
|
+};
|
|
|
|
|
|
- if (!mc_mac) {
|
|
|
- BNX2X_ERR("Failed to allocate mc MAC list\n");
|
|
|
- return -ENOMEM;
|
|
|
+#define MCAST_ELEMS_PER_PG \
|
|
|
+ ((PAGE_SIZE - sizeof(struct bnx2x_mcast_list_elem_group)) / \
|
|
|
+ sizeof(struct bnx2x_mcast_list_elem))
|
|
|
+
|
|
|
+static void bnx2x_free_mcast_macs_list(struct list_head *mcast_group_list)
|
|
|
+{
|
|
|
+ struct bnx2x_mcast_list_elem_group *current_mcast_group;
|
|
|
+
|
|
|
+ while (!list_empty(mcast_group_list)) {
|
|
|
+ current_mcast_group = list_first_entry(mcast_group_list,
|
|
|
+ struct bnx2x_mcast_list_elem_group,
|
|
|
+ mcast_group_link);
|
|
|
+ list_del(¤t_mcast_group->mcast_group_link);
|
|
|
+ free_page((unsigned long)current_mcast_group);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- INIT_LIST_HEAD(&p->mcast_list);
|
|
|
+static int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
|
|
|
+ struct bnx2x_mcast_ramrod_params *p,
|
|
|
+ struct list_head *mcast_group_list)
|
|
|
+{
|
|
|
+ struct bnx2x_mcast_list_elem *mc_mac;
|
|
|
+ struct netdev_hw_addr *ha;
|
|
|
+ struct bnx2x_mcast_list_elem_group *current_mcast_group = NULL;
|
|
|
+ int mc_count = netdev_mc_count(bp->dev);
|
|
|
+ int offset = 0;
|
|
|
|
|
|
+ INIT_LIST_HEAD(&p->mcast_list);
|
|
|
netdev_for_each_mc_addr(ha, bp->dev) {
|
|
|
+ if (!offset) {
|
|
|
+ current_mcast_group =
|
|
|
+ (struct bnx2x_mcast_list_elem_group *)
|
|
|
+ __get_free_page(GFP_ATOMIC);
|
|
|
+ if (!current_mcast_group) {
|
|
|
+ bnx2x_free_mcast_macs_list(mcast_group_list);
|
|
|
+ BNX2X_ERR("Failed to allocate mc MAC list\n");
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ list_add(¤t_mcast_group->mcast_group_link,
|
|
|
+ mcast_group_list);
|
|
|
+ }
|
|
|
+ mc_mac = ¤t_mcast_group->mcast_elems[offset];
|
|
|
mc_mac->mac = bnx2x_mc_addr(ha);
|
|
|
list_add_tail(&mc_mac->link, &p->mcast_list);
|
|
|
- mc_mac++;
|
|
|
+ offset++;
|
|
|
+ if (offset == MCAST_ELEMS_PER_PG)
|
|
|
+ offset = 0;
|
|
|
}
|
|
|
-
|
|
|
p->mcast_list_len = mc_count;
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void bnx2x_free_mcast_macs_list(
|
|
|
- struct bnx2x_mcast_ramrod_params *p)
|
|
|
-{
|
|
|
- struct bnx2x_mcast_list_elem *mc_mac =
|
|
|
- list_first_entry(&p->mcast_list, struct bnx2x_mcast_list_elem,
|
|
|
- link);
|
|
|
-
|
|
|
- WARN_ON(!mc_mac);
|
|
|
- kfree(mc_mac);
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* bnx2x_set_uc_list - configure a new unicast MACs list.
|
|
|
*
|
|
@@ -12647,6 +12668,7 @@ static int bnx2x_set_uc_list(struct bnx2x *bp)
|
|
|
|
|
|
static int bnx2x_set_mc_list_e1x(struct bnx2x *bp)
|
|
|
{
|
|
|
+ LIST_HEAD(mcast_group_list);
|
|
|
struct net_device *dev = bp->dev;
|
|
|
struct bnx2x_mcast_ramrod_params rparam = {NULL};
|
|
|
int rc = 0;
|
|
@@ -12662,7 +12684,7 @@ static int bnx2x_set_mc_list_e1x(struct bnx2x *bp)
|
|
|
|
|
|
/* then, configure a new MACs list */
|
|
|
if (netdev_mc_count(dev)) {
|
|
|
- rc = bnx2x_init_mcast_macs_list(bp, &rparam);
|
|
|
+ rc = bnx2x_init_mcast_macs_list(bp, &rparam, &mcast_group_list);
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
@@ -12673,7 +12695,7 @@ static int bnx2x_set_mc_list_e1x(struct bnx2x *bp)
|
|
|
BNX2X_ERR("Failed to set a new multicast configuration: %d\n",
|
|
|
rc);
|
|
|
|
|
|
- bnx2x_free_mcast_macs_list(&rparam);
|
|
|
+ bnx2x_free_mcast_macs_list(&mcast_group_list);
|
|
|
}
|
|
|
|
|
|
return rc;
|
|
@@ -12681,6 +12703,7 @@ static int bnx2x_set_mc_list_e1x(struct bnx2x *bp)
|
|
|
|
|
|
static int bnx2x_set_mc_list(struct bnx2x *bp)
|
|
|
{
|
|
|
+ LIST_HEAD(mcast_group_list);
|
|
|
struct bnx2x_mcast_ramrod_params rparam = {NULL};
|
|
|
struct net_device *dev = bp->dev;
|
|
|
int rc = 0;
|
|
@@ -12692,7 +12715,7 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
|
|
|
rparam.mcast_obj = &bp->mcast_obj;
|
|
|
|
|
|
if (netdev_mc_count(dev)) {
|
|
|
- rc = bnx2x_init_mcast_macs_list(bp, &rparam);
|
|
|
+ rc = bnx2x_init_mcast_macs_list(bp, &rparam, &mcast_group_list);
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
@@ -12703,7 +12726,7 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
|
|
|
BNX2X_ERR("Failed to set a new multicast configuration: %d\n",
|
|
|
rc);
|
|
|
|
|
|
- bnx2x_free_mcast_macs_list(&rparam);
|
|
|
+ bnx2x_free_mcast_macs_list(&mcast_group_list);
|
|
|
} else {
|
|
|
/* If no mc addresses are required, flush the configuration */
|
|
|
rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
|