Skip to content

Commit

Permalink
cnic: Don't take rcu_read_lock in cnic_rcv_netevent()
Browse files Browse the repository at this point in the history
Because the called function, such as bnx2fc_indicate_netevent(), can sleep,
we cannot take rcu_lock().  To prevent the rcu protected ulp_ops from going
away, we use the cnic_lock mutex and set the ULP_F_CALL_PENDING flag.
The code already waits for ULP_F_CALL_PENDING flag to clear in
cnic_unregister_device().

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Michael Chan authored and David S. Miller committed Jun 3, 2014
1 parent 74f4392 commit 20f30c2
Showing 1 changed file with 11 additions and 4 deletions.
15 changes: 11 additions & 4 deletions drivers/net/ethernet/broadcom/cnic.c
Original file line number Diff line number Diff line change
Expand Up @@ -5624,20 +5624,27 @@ static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event,
{
int if_type;

rcu_read_lock();
for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
struct cnic_ulp_ops *ulp_ops;
void *ctx;

ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
if (!ulp_ops || !ulp_ops->indicate_netevent)
mutex_lock(&cnic_lock);
ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type],
lockdep_is_held(&cnic_lock));
if (!ulp_ops || !ulp_ops->indicate_netevent) {
mutex_unlock(&cnic_lock);
continue;
}

ctx = cp->ulp_handle[if_type];

set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
mutex_unlock(&cnic_lock);

ulp_ops->indicate_netevent(ctx, event, vlan_id);

clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
}
rcu_read_unlock();
}

/* netdev event handler */
Expand Down

0 comments on commit 20f30c2

Please sign in to comment.