aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorRalph Campbell <ralph.campbell@qlogic.com>2009-02-27 17:44:32 -0500
committerRoland Dreier <rolandd@cisco.com>2009-02-27 17:44:32 -0500
commitd9620a4c82c61a91c9313f80ba951c902573c028 (patch)
treed49b92e161f7fc8176e04084b3d981d94ff9e2bd /drivers/infiniband
parent1d9bc6d648ece77ffb41c5a577eab81fac5ad4de (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.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,
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
366error4: 365error4: