Skip to content

Commit

Permalink
bnx2x: credit-leakage fixup on vlan_mac_del_all
Browse files Browse the repository at this point in the history
Upon insertion of elements into the execution queue, it is validated
that there are enough credits to support additional vlan-macs,
and the credits are consumed. However, when removing a pending
command in `bnx2x_vland_mac_del_all' the consumed credits are not
released, which might cause leakage and eventually the inability to
add new vlan-macs in certain scenarios.

Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Yuval Mintz authored and David S. Miller committed Jan 23, 2012
1 parent 4ec7ac1 commit 460a25c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
44 changes: 43 additions & 1 deletion drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
int exe_len,
union bnx2x_qable_obj *owner,
exe_q_validate validate,
exe_q_remove remove,
exe_q_optimize optimize,
exe_q_execute exec,
exe_q_get get)
Expand All @@ -66,6 +67,7 @@ static inline void bnx2x_exe_queue_init(struct bnx2x *bp,

/* Owner specific callbacks */
o->validate = validate;
o->remove = remove;
o->optimize = optimize;
o->execute = exec;
o->get = get;
Expand Down Expand Up @@ -1340,6 +1342,35 @@ static int bnx2x_validate_vlan_mac(struct bnx2x *bp,
}
}

static int bnx2x_remove_vlan_mac(struct bnx2x *bp,
union bnx2x_qable_obj *qo,
struct bnx2x_exeq_elem *elem)
{
int rc = 0;

/* If consumption wasn't required, nothing to do */
if (test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
&elem->cmd_data.vlan_mac.vlan_mac_flags))
return 0;

switch (elem->cmd_data.vlan_mac.cmd) {
case BNX2X_VLAN_MAC_ADD:
case BNX2X_VLAN_MAC_MOVE:
rc = qo->vlan_mac.put_credit(&qo->vlan_mac);
break;
case BNX2X_VLAN_MAC_DEL:
rc = qo->vlan_mac.get_credit(&qo->vlan_mac);
break;
default:
return -EINVAL;
}

if (rc != true)
return -EINVAL;

return 0;
}

/**
* bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
*
Expand Down Expand Up @@ -1801,8 +1832,14 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,

list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
*vlan_mac_flags)
*vlan_mac_flags) {
rc = exeq->remove(bp, exeq->owner, exeq_pos);
if (rc) {
BNX2X_ERR("Failed to remove command\n");
return rc;
}
list_del(&exeq_pos->link);
}
}

spin_unlock_bh(&exeq->lock);
Expand Down Expand Up @@ -1908,6 +1945,7 @@ void bnx2x_init_mac_obj(struct bnx2x *bp,
bnx2x_exe_queue_init(bp,
&mac_obj->exe_queue, 1, qable_obj,
bnx2x_validate_vlan_mac,
bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_mac);
Expand All @@ -1924,6 +1962,7 @@ void bnx2x_init_mac_obj(struct bnx2x *bp,
bnx2x_exe_queue_init(bp,
&mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
qable_obj, bnx2x_validate_vlan_mac,
bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_mac);
Expand Down Expand Up @@ -1963,6 +2002,7 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
bnx2x_exe_queue_init(bp,
&vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
qable_obj, bnx2x_validate_vlan_mac,
bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_vlan);
Expand Down Expand Up @@ -2009,6 +2049,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
bnx2x_exe_queue_init(bp,
&vlan_mac_obj->exe_queue, 1, qable_obj,
bnx2x_validate_vlan_mac,
bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_vlan_mac);
Expand All @@ -2025,6 +2066,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
&vlan_mac_obj->exe_queue,
CLASSIFY_RULES_COUNT,
qable_obj, bnx2x_validate_vlan_mac,
bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_vlan_mac);
Expand Down
11 changes: 11 additions & 0 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ typedef int (*exe_q_validate)(struct bnx2x *bp,
union bnx2x_qable_obj *o,
struct bnx2x_exeq_elem *elem);

typedef int (*exe_q_remove)(struct bnx2x *bp,
union bnx2x_qable_obj *o,
struct bnx2x_exeq_elem *elem);

/**
* @return positive is entry was optimized, 0 - if not, negative
* in case of an error.
Expand Down Expand Up @@ -203,11 +207,18 @@ struct bnx2x_exe_queue_obj {
*/
exe_q_validate validate;

/**
* Called before removing pending commands, cleaning allocated
* resources (e.g., credits from validate)
*/
exe_q_remove remove;

/**
* This will try to cancel the current pending commands list
* considering the new command.
*
* Returns the number of optimized commands or a negative error code
*
* Must run under exe_queue->lock
*/
exe_q_optimize optimize;
Expand Down

0 comments on commit 460a25c

Please sign in to comment.