diff options
author | Ralph Campbell <ralph.campbell@qlogic.com> | 2009-02-27 17:44:32 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-02-27 17:44:32 -0500 |
commit | d9620a4c82c61a91c9313f80ba951c902573c028 (patch) | |
tree | d49b92e161f7fc8176e04084b3d981d94ff9e2bd /drivers/infiniband | |
parent | 1d9bc6d648ece77ffb41c5a577eab81fac5ad4de (diff) |
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>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/mad.c | 21 |
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, | |||
301 | mad_agent_priv->agent.context = context; | 301 | mad_agent_priv->agent.context = context; |
302 | mad_agent_priv->agent.qp = port_priv->qp_info[qpn].qp; | 302 | mad_agent_priv->agent.qp = port_priv->qp_info[qpn].qp; |
303 | mad_agent_priv->agent.port_num = port_num; | 303 | mad_agent_priv->agent.port_num = port_num; |
304 | spin_lock_init(&mad_agent_priv->lock); | ||
305 | INIT_LIST_HEAD(&mad_agent_priv->send_list); | ||
306 | INIT_LIST_HEAD(&mad_agent_priv->wait_list); | ||
307 | INIT_LIST_HEAD(&mad_agent_priv->done_list); | ||
308 | INIT_LIST_HEAD(&mad_agent_priv->rmpp_list); | ||
309 | INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends); | ||
310 | INIT_LIST_HEAD(&mad_agent_priv->local_list); | ||
311 | INIT_WORK(&mad_agent_priv->local_work, local_completions); | ||
312 | atomic_set(&mad_agent_priv->refcount, 1); | ||
313 | init_completion(&mad_agent_priv->comp); | ||
304 | 314 | ||
305 | spin_lock_irqsave(&port_priv->reg_lock, flags); | 315 | spin_lock_irqsave(&port_priv->reg_lock, flags); |
306 | mad_agent_priv->agent.hi_tid = ++ib_mad_client_id; | 316 | 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, | |||
350 | list_add_tail(&mad_agent_priv->agent_list, &port_priv->agent_list); | 360 | list_add_tail(&mad_agent_priv->agent_list, &port_priv->agent_list); |
351 | spin_unlock_irqrestore(&port_priv->reg_lock, flags); | 361 | spin_unlock_irqrestore(&port_priv->reg_lock, flags); |
352 | 362 | ||
353 | spin_lock_init(&mad_agent_priv->lock); | ||
354 | INIT_LIST_HEAD(&mad_agent_priv->send_list); | ||
355 | INIT_LIST_HEAD(&mad_agent_priv->wait_list); | ||
356 | INIT_LIST_HEAD(&mad_agent_priv->done_list); | ||
357 | INIT_LIST_HEAD(&mad_agent_priv->rmpp_list); | ||
358 | INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends); | ||
359 | INIT_LIST_HEAD(&mad_agent_priv->local_list); | ||
360 | INIT_WORK(&mad_agent_priv->local_work, local_completions); | ||
361 | atomic_set(&mad_agent_priv->refcount, 1); | ||
362 | init_completion(&mad_agent_priv->comp); | ||
363 | |||
364 | return &mad_agent_priv->agent; | 363 | return &mad_agent_priv->agent; |
365 | 364 | ||
366 | error4: | 365 | error4: |