summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Campbell <ralph.campbell@qlogic.com>2009-02-28 01:44:32 +0300
committerRoland Dreier <rolandd@cisco.com>2009-02-28 01:44:32 +0300
commitd9620a4c82c61a91c9313f80ba951c902573c028 (patch)
treed49b92e161f7fc8176e04084b3d981d94ff9e2bd
parent1d9bc6d648ece77ffb41c5a577eab81fac5ad4de (diff)
downloadlinux-d9620a4c82c61a91c9313f80ba951c902573c028.tar.xz
IB/mad: initialize mad_agent_priv before putting on lists
There is a potential race in ib_register_mad_agent() where the struct ib_mad_agent_private is not fully initialized before it is added to the list of agents per IB port. This means the ib_mad_agent_private could be seen before the refcount, spin locks, and linked lists are initialized. The fix is to initialize the structure earlier. Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/core/mad.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 735ad4ea10f0..dbcd285405ec 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -301,6 +301,16 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
mad_agent_priv->agent.context = context;
mad_agent_priv->agent.qp = port_priv->qp_info[qpn].qp;
mad_agent_priv->agent.port_num = port_num;
+ spin_lock_init(&mad_agent_priv->lock);
+ INIT_LIST_HEAD(&mad_agent_priv->send_list);
+ INIT_LIST_HEAD(&mad_agent_priv->wait_list);
+ INIT_LIST_HEAD(&mad_agent_priv->done_list);
+ INIT_LIST_HEAD(&mad_agent_priv->rmpp_list);
+ INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends);
+ INIT_LIST_HEAD(&mad_agent_priv->local_list);
+ INIT_WORK(&mad_agent_priv->local_work, local_completions);
+ atomic_set(&mad_agent_priv->refcount, 1);
+ init_completion(&mad_agent_priv->comp);
spin_lock_irqsave(&port_priv->reg_lock, flags);
mad_agent_priv->agent.hi_tid = ++ib_mad_client_id;
@@ -350,17 +360,6 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
list_add_tail(&mad_agent_priv->agent_list, &port_priv->agent_list);
spin_unlock_irqrestore(&port_priv->reg_lock, flags);
- spin_lock_init(&mad_agent_priv->lock);
- INIT_LIST_HEAD(&mad_agent_priv->send_list);
- INIT_LIST_HEAD(&mad_agent_priv->wait_list);
- INIT_LIST_HEAD(&mad_agent_priv->done_list);
- INIT_LIST_HEAD(&mad_agent_priv->rmpp_list);
- INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends);
- INIT_LIST_HEAD(&mad_agent_priv->local_list);
- INIT_WORK(&mad_agent_priv->local_work, local_completions);
- atomic_set(&mad_agent_priv->refcount, 1);
- init_completion(&mad_agent_priv->comp);
-
return &mad_agent_priv->agent;
error4: