RE: [PATCH v2 net-next 2/2] bnx2x: allocate mac filtering pending list in PAGE_SIZE increments

2016-09-26 Thread Mintz, Yuval
> From: Jason Baron 
> 
> Currently, we can have high order page allocations that specify GFP_ATOMIC
> when configuring multicast MAC address filters.
> 
> For example, we have seen order 2 page allocation failures with
> ~500 multicast addresses configured.
> 
> Convert the allocation for the pending list to be done in PAGE_SIZE 
> increments.
> 
> Signed-off-by: Jason Baron 
> Cc: Yuval Mintz 
> Cc: Ariel Elior 

Thanks Jason.
Acked-by: Yuval Mintz 


[PATCH v2 net-next 2/2] bnx2x: allocate mac filtering pending list in PAGE_SIZE increments

2016-09-22 Thread Jason Baron
From: Jason Baron 

Currently, we can have high order page allocations that specify
GFP_ATOMIC when configuring multicast MAC address filters.

For example, we have seen order 2 page allocation failures with
~500 multicast addresses configured.

Convert the allocation for the pending list to be done in PAGE_SIZE
increments.

Signed-off-by: Jason Baron 
Cc: Yuval Mintz 
Cc: Ariel Elior 
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 123 +
 1 file changed, 86 insertions(+), 37 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c 
b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index d468380c2a23..4947a9cbf0c1 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -2606,8 +2606,23 @@ struct bnx2x_mcast_bin_elem {
int type; /* BNX2X_MCAST_CMD_SET_{ADD, DEL} */
 };
 
+union bnx2x_mcast_elem {
+   struct bnx2x_mcast_bin_elem bin_elem;
+   struct bnx2x_mcast_mac_elem mac_elem;
+};
+
+struct bnx2x_mcast_elem_group {
+   struct list_head mcast_group_link;
+   union bnx2x_mcast_elem mcast_elems[];
+};
+
+#define MCAST_MAC_ELEMS_PER_PG \
+   ((PAGE_SIZE - sizeof(struct bnx2x_mcast_elem_group)) / \
+   sizeof(union bnx2x_mcast_elem))
+
 struct bnx2x_pending_mcast_cmd {
struct list_head link;
+   struct list_head group_head;
int type; /* BNX2X_MCAST_CMD_X */
union {
struct list_head macs_head;
@@ -2638,16 +2653,29 @@ static int bnx2x_mcast_wait(struct bnx2x *bp,
return 0;
 }
 
+static void bnx2x_free_groups(struct list_head *mcast_group_list)
+{
+   struct bnx2x_mcast_elem_group *current_mcast_group;
+
+   while (!list_empty(mcast_group_list)) {
+   current_mcast_group = list_first_entry(mcast_group_list,
+ struct bnx2x_mcast_elem_group,
+ mcast_group_link);
+   list_del(_mcast_group->mcast_group_link);
+   free_page((unsigned long)current_mcast_group);
+   }
+}
+
 static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
   struct bnx2x_mcast_obj *o,
   struct bnx2x_mcast_ramrod_params *p,
   enum bnx2x_mcast_cmd cmd)
 {
-   int total_sz;
struct bnx2x_pending_mcast_cmd *new_cmd;
-   struct bnx2x_mcast_mac_elem *cur_mac = NULL;
struct bnx2x_mcast_list_elem *pos;
-   int macs_list_len = 0, macs_list_len_size;
+   struct bnx2x_mcast_elem_group *elem_group;
+   struct bnx2x_mcast_mac_elem *mac_elem;
+   int total_elems = 0, macs_list_len = 0, offset = 0;
 
/* When adding MACs we'll need to store their values */
if (cmd == BNX2X_MCAST_CMD_ADD || cmd == BNX2X_MCAST_CMD_SET)
@@ -2657,50 +2685,61 @@ static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
if (!p->mcast_list_len)
return 0;
 
-   /* For a set command, we need to allocate sufficient memory for all
-* the bins, since we can't analyze at this point how much memory would
-* be required.
-*/
-   macs_list_len_size = macs_list_len *
-sizeof(struct bnx2x_mcast_mac_elem);
-   if (cmd == BNX2X_MCAST_CMD_SET) {
-   int bin_size = BNX2X_MCAST_BINS_NUM *
-  sizeof(struct bnx2x_mcast_bin_elem);
-
-   if (bin_size > macs_list_len_size)
-   macs_list_len_size = bin_size;
-   }
-   total_sz = sizeof(*new_cmd) + macs_list_len_size;
-
/* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
-   new_cmd = kzalloc(total_sz, GFP_ATOMIC);
-
+   new_cmd = kzalloc(sizeof(*new_cmd), GFP_ATOMIC);
if (!new_cmd)
return -ENOMEM;
 
-   DP(BNX2X_MSG_SP, "About to enqueue a new %d command. 
macs_list_len=%d\n",
-  cmd, macs_list_len);
-
INIT_LIST_HEAD(_cmd->data.macs_head);
-
+   INIT_LIST_HEAD(_cmd->group_head);
new_cmd->type = cmd;
new_cmd->done = false;
 
+   DP(BNX2X_MSG_SP, "About to enqueue a new %d command. 
macs_list_len=%d\n",
+  cmd, macs_list_len);
+
switch (cmd) {
case BNX2X_MCAST_CMD_ADD:
case BNX2X_MCAST_CMD_SET:
-   cur_mac = (struct bnx2x_mcast_mac_elem *)
- ((u8 *)new_cmd + sizeof(*new_cmd));
-
-   /* Push the MACs of the current command into the pending command
-* MACs list: FIFO
+   /* For a set command, we need to allocate sufficient memory for
+* all the bins, since we can't analyze at this point how much
+* memory would be required.
 */
+   total_elems = macs_list_len;
+   if (cmd ==