aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Baron <jbaron@akamai.com>2016-09-22 17:12:26 -0400
committerDavid S. Miller <davem@davemloft.net>2016-09-26 09:43:06 -0400
commit3129e1599c6edfafc2a0a8be9f2eb344c7feb920 (patch)
tree48ea93455bc0ee13261a953028a0c1db473a25c6
parente8c6ae9fbf8ca70ef0c2de0d2f3995acb0dc8968 (diff)
bnx2x: allocate mac filtering pending list in PAGE_SIZE increments
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 <jbaron@akamai.com> Cc: Yuval Mintz <Yuval.Mintz@qlogic.com> Cc: Ariel Elior <Ariel.Elior@qlogic.com> Acked-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c123
1 files 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 {
2606 int type; /* BNX2X_MCAST_CMD_SET_{ADD, DEL} */ 2606 int type; /* BNX2X_MCAST_CMD_SET_{ADD, DEL} */
2607}; 2607};
2608 2608
2609union bnx2x_mcast_elem {
2610 struct bnx2x_mcast_bin_elem bin_elem;
2611 struct bnx2x_mcast_mac_elem mac_elem;
2612};
2613
2614struct bnx2x_mcast_elem_group {
2615 struct list_head mcast_group_link;
2616 union bnx2x_mcast_elem mcast_elems[];
2617};
2618
2619#define MCAST_MAC_ELEMS_PER_PG \
2620 ((PAGE_SIZE - sizeof(struct bnx2x_mcast_elem_group)) / \
2621 sizeof(union bnx2x_mcast_elem))
2622
2609struct bnx2x_pending_mcast_cmd { 2623struct bnx2x_pending_mcast_cmd {
2610 struct list_head link; 2624 struct list_head link;
2625 struct list_head group_head;
2611 int type; /* BNX2X_MCAST_CMD_X */ 2626 int type; /* BNX2X_MCAST_CMD_X */
2612 union { 2627 union {
2613 struct list_head macs_head; 2628 struct list_head macs_head;
@@ -2638,16 +2653,29 @@ static int bnx2x_mcast_wait(struct bnx2x *bp,
2638 return 0; 2653 return 0;
2639} 2654}
2640 2655
2656static void bnx2x_free_groups(struct list_head *mcast_group_list)
2657{
2658 struct bnx2x_mcast_elem_group *current_mcast_group;
2659
2660 while (!list_empty(mcast_group_list)) {
2661 current_mcast_group = list_first_entry(mcast_group_list,
2662 struct bnx2x_mcast_elem_group,
2663 mcast_group_link);
2664 list_del(&current_mcast_group->mcast_group_link);
2665 free_page((unsigned long)current_mcast_group);
2666 }
2667}
2668
2641static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp, 2669static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
2642 struct bnx2x_mcast_obj *o, 2670 struct bnx2x_mcast_obj *o,
2643 struct bnx2x_mcast_ramrod_params *p, 2671 struct bnx2x_mcast_ramrod_params *p,
2644 enum bnx2x_mcast_cmd cmd) 2672 enum bnx2x_mcast_cmd cmd)
2645{ 2673{
2646 int total_sz;
2647 struct bnx2x_pending_mcast_cmd *new_cmd; 2674 struct bnx2x_pending_mcast_cmd *new_cmd;
2648 struct bnx2x_mcast_mac_elem *cur_mac = NULL;
2649 struct bnx2x_mcast_list_elem *pos; 2675 struct bnx2x_mcast_list_elem *pos;
2650 int macs_list_len = 0, macs_list_len_size; 2676 struct bnx2x_mcast_elem_group *elem_group;
2677 struct bnx2x_mcast_mac_elem *mac_elem;
2678 int total_elems = 0, macs_list_len = 0, offset = 0;
2651 2679
2652 /* When adding MACs we'll need to store their values */ 2680 /* When adding MACs we'll need to store their values */
2653 if (cmd == BNX2X_MCAST_CMD_ADD || cmd == BNX2X_MCAST_CMD_SET) 2681 if (cmd == BNX2X_MCAST_CMD_ADD || cmd == BNX2X_MCAST_CMD_SET)
@@ -2657,50 +2685,61 @@ static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
2657 if (!p->mcast_list_len) 2685 if (!p->mcast_list_len)
2658 return 0; 2686 return 0;
2659 2687
2660 /* For a set command, we need to allocate sufficient memory for all
2661 * the bins, since we can't analyze at this point how much memory would
2662 * be required.
2663 */
2664 macs_list_len_size = macs_list_len *
2665 sizeof(struct bnx2x_mcast_mac_elem);
2666 if (cmd == BNX2X_MCAST_CMD_SET) {
2667 int bin_size = BNX2X_MCAST_BINS_NUM *
2668 sizeof(struct bnx2x_mcast_bin_elem);
2669
2670 if (bin_size > macs_list_len_size)
2671 macs_list_len_size = bin_size;
2672 }
2673 total_sz = sizeof(*new_cmd) + macs_list_len_size;
2674
2675 /* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */ 2688 /* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
2676 new_cmd = kzalloc(total_sz, GFP_ATOMIC); 2689 new_cmd = kzalloc(sizeof(*new_cmd), GFP_ATOMIC);
2677
2678 if (!new_cmd) 2690 if (!new_cmd)
2679 return -ENOMEM; 2691 return -ENOMEM;
2680 2692
2681 DP(BNX2X_MSG_SP, "About to enqueue a new %d command. macs_list_len=%d\n",
2682 cmd, macs_list_len);
2683
2684 INIT_LIST_HEAD(&new_cmd->data.macs_head); 2693 INIT_LIST_HEAD(&new_cmd->data.macs_head);
2685 2694 INIT_LIST_HEAD(&new_cmd->group_head);
2686 new_cmd->type = cmd; 2695 new_cmd->type = cmd;
2687 new_cmd->done = false; 2696 new_cmd->done = false;
2688 2697
2698 DP(BNX2X_MSG_SP, "About to enqueue a new %d command. macs_list_len=%d\n",
2699 cmd, macs_list_len);
2700
2689 switch (cmd) { 2701 switch (cmd) {
2690 case BNX2X_MCAST_CMD_ADD: 2702 case BNX2X_MCAST_CMD_ADD:
2691 case BNX2X_MCAST_CMD_SET: 2703 case BNX2X_MCAST_CMD_SET:
2692 cur_mac = (struct bnx2x_mcast_mac_elem *) 2704 /* For a set command, we need to allocate sufficient memory for
2693 ((u8 *)new_cmd + sizeof(*new_cmd)); 2705 * all the bins, since we can't analyze at this point how much
2694 2706 * memory would be required.
2695 /* Push the MACs of the current command into the pending command
2696 * MACs list: FIFO
2697 */ 2707 */
2708 total_elems = macs_list_len;
2709 if (cmd == BNX2X_MCAST_CMD_SET) {
2710 if (total_elems < BNX2X_MCAST_BINS_NUM)
2711 total_elems = BNX2X_MCAST_BINS_NUM;
2712 }
2713 while (total_elems > 0) {
2714 elem_group = (struct bnx2x_mcast_elem_group *)
2715 __get_free_page(GFP_ATOMIC | __GFP_ZERO);
2716 if (!elem_group) {
2717 kfree(new_cmd);
2718 bnx2x_free_groups(&new_cmd->group_head);
2719 return -ENOMEM;
2720 }
2721 total_elems -= MCAST_MAC_ELEMS_PER_PG;
2722 list_add_tail(&elem_group->mcast_group_link,
2723 &new_cmd->group_head);
2724 }
2725 elem_group = list_first_entry(&new_cmd->group_head,
2726 struct bnx2x_mcast_elem_group,
2727 mcast_group_link);
2698 list_for_each_entry(pos, &p->mcast_list, link) { 2728 list_for_each_entry(pos, &p->mcast_list, link) {
2699 memcpy(cur_mac->mac, pos->mac, ETH_ALEN); 2729 mac_elem = &elem_group->mcast_elems[offset].mac_elem;
2700 list_add_tail(&cur_mac->link, &new_cmd->data.macs_head); 2730 memcpy(mac_elem->mac, pos->mac, ETH_ALEN);
2701 cur_mac++; 2731 /* Push the MACs of the current command into the pending
2732 * command MACs list: FIFO
2733 */
2734 list_add_tail(&mac_elem->link,
2735 &new_cmd->data.macs_head);
2736 offset++;
2737 if (offset == MCAST_MAC_ELEMS_PER_PG) {
2738 offset = 0;
2739 elem_group = list_next_entry(elem_group,
2740 mcast_group_link);
2741 }
2702 } 2742 }
2703
2704 break; 2743 break;
2705 2744
2706 case BNX2X_MCAST_CMD_DEL: 2745 case BNX2X_MCAST_CMD_DEL:
@@ -2978,7 +3017,8 @@ bnx2x_mcast_hdl_pending_set_e2_convert(struct bnx2x *bp,
2978 u64 cur[BNX2X_MCAST_VEC_SZ], req[BNX2X_MCAST_VEC_SZ]; 3017 u64 cur[BNX2X_MCAST_VEC_SZ], req[BNX2X_MCAST_VEC_SZ];
2979 struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n; 3018 struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
2980 struct bnx2x_mcast_bin_elem *p_item; 3019 struct bnx2x_mcast_bin_elem *p_item;
2981 int i, cnt = 0, mac_cnt = 0; 3020 struct bnx2x_mcast_elem_group *elem_group;
3021 int cnt = 0, mac_cnt = 0, offset = 0, i;
2982 3022
2983 memset(req, 0, sizeof(u64) * BNX2X_MCAST_VEC_SZ); 3023 memset(req, 0, sizeof(u64) * BNX2X_MCAST_VEC_SZ);
2984 memcpy(cur, o->registry.aprox_match.vec, 3024 memcpy(cur, o->registry.aprox_match.vec,
@@ -3001,9 +3041,10 @@ bnx2x_mcast_hdl_pending_set_e2_convert(struct bnx2x *bp,
3001 * a list that will be used to configure bins. 3041 * a list that will be used to configure bins.
3002 */ 3042 */
3003 cmd_pos->set_convert = true; 3043 cmd_pos->set_convert = true;
3004 p_item = (struct bnx2x_mcast_bin_elem *)(cmd_pos + 1);
3005 INIT_LIST_HEAD(&cmd_pos->data.macs_head); 3044 INIT_LIST_HEAD(&cmd_pos->data.macs_head);
3006 3045 elem_group = list_first_entry(&cmd_pos->group_head,
3046 struct bnx2x_mcast_elem_group,
3047 mcast_group_link);
3007 for (i = 0; i < BNX2X_MCAST_BINS_NUM; i++) { 3048 for (i = 0; i < BNX2X_MCAST_BINS_NUM; i++) {
3008 bool b_current = !!BIT_VEC64_TEST_BIT(cur, i); 3049 bool b_current = !!BIT_VEC64_TEST_BIT(cur, i);
3009 bool b_required = !!BIT_VEC64_TEST_BIT(req, i); 3050 bool b_required = !!BIT_VEC64_TEST_BIT(req, i);
@@ -3011,12 +3052,18 @@ bnx2x_mcast_hdl_pending_set_e2_convert(struct bnx2x *bp,
3011 if (b_current == b_required) 3052 if (b_current == b_required)
3012 continue; 3053 continue;
3013 3054
3055 p_item = &elem_group->mcast_elems[offset].bin_elem;
3014 p_item->bin = i; 3056 p_item->bin = i;
3015 p_item->type = b_required ? BNX2X_MCAST_CMD_SET_ADD 3057 p_item->type = b_required ? BNX2X_MCAST_CMD_SET_ADD
3016 : BNX2X_MCAST_CMD_SET_DEL; 3058 : BNX2X_MCAST_CMD_SET_DEL;
3017 list_add_tail(&p_item->link , &cmd_pos->data.macs_head); 3059 list_add_tail(&p_item->link , &cmd_pos->data.macs_head);
3018 p_item++;
3019 cnt++; 3060 cnt++;
3061 offset++;
3062 if (offset == MCAST_MAC_ELEMS_PER_PG) {
3063 offset = 0;
3064 elem_group = list_next_entry(elem_group,
3065 mcast_group_link);
3066 }
3020 } 3067 }
3021 3068
3022 /* We now definitely know how many commands are hiding here. 3069 /* We now definitely know how many commands are hiding here.
@@ -3103,6 +3150,7 @@ static inline int bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x *bp,
3103 */ 3150 */
3104 if (cmd_pos->done) { 3151 if (cmd_pos->done) {
3105 list_del(&cmd_pos->link); 3152 list_del(&cmd_pos->link);
3153 bnx2x_free_groups(&cmd_pos->group_head);
3106 kfree(cmd_pos); 3154 kfree(cmd_pos);
3107 } 3155 }
3108 3156
@@ -3741,6 +3789,7 @@ static inline int bnx2x_mcast_handle_pending_cmds_e1(
3741 } 3789 }
3742 3790
3743 list_del(&cmd_pos->link); 3791 list_del(&cmd_pos->link);
3792 bnx2x_free_groups(&cmd_pos->group_head);
3744 kfree(cmd_pos); 3793 kfree(cmd_pos);
3745 3794
3746 return cnt; 3795 return cnt;