Commit 20f30c2d authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

cnic: Don't take rcu_read_lock in cnic_rcv_netevent()

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: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 74f43922
...@@ -5624,20 +5624,27 @@ static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event, ...@@ -5624,20 +5624,27 @@ static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event,
{ {
int if_type; int if_type;
rcu_read_lock();
for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
struct cnic_ulp_ops *ulp_ops; struct cnic_ulp_ops *ulp_ops;
void *ctx; void *ctx;
ulp_ops = rcu_dereference(cp->ulp_ops[if_type]); mutex_lock(&cnic_lock);
if (!ulp_ops || !ulp_ops->indicate_netevent) 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; continue;
}
ctx = cp->ulp_handle[if_type]; 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); 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 */ /* netdev event handler */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment