aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalph Campbell <ralph.campbell@qlogic.com>2009-03-03 17:22:17 -0500
committerRoland Dreier <rolandd@cisco.com>2009-03-03 17:22:17 -0500
commit4780c1953f9bef07365b13af01ae4e8238ecd3de (patch)
treece68e77fc5ad410b9c320cf80ad7f76faa1bc7f1
parentd9620a4c82c61a91c9313f80ba951c902573c028 (diff)
IB/mad: Fix ib_post_send_mad() returning 0 with no generate send comp
If ib_post_send_mad() returns 0, the API guarantees that there will be a callback to send_buf->mad_agent->send_handler() so that the sender can call ib_free_send_mad(). Otherwise, the ib_mad_send_buf will be leaked and the mad_agent reference count will never go to zero and the IB device module cannot be unloaded. The above can happen without this patch if process_mad() returns (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED). If process_mad() returns IB_MAD_RESULT_SUCCESS and there is no agent registered to receive the mad being sent, handle_outgoing_dr_smp() returns zero which causes a MAD packet which is at the end of the directed route to be incorrectly sent on the wire but doesn't cause a hang since the HCA generates a send completion. Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/core/mad.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index dbcd285405ec..de922a04ca2d 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -742,9 +742,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
742 break; 742 break;
743 case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED: 743 case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED:
744 kmem_cache_free(ib_mad_cache, mad_priv); 744 kmem_cache_free(ib_mad_cache, mad_priv);
745 kfree(local); 745 break;
746 ret = 1;
747 goto out;
748 case IB_MAD_RESULT_SUCCESS: 746 case IB_MAD_RESULT_SUCCESS:
749 /* Treat like an incoming receive MAD */ 747 /* Treat like an incoming receive MAD */
750 port_priv = ib_get_mad_port(mad_agent_priv->agent.device, 748 port_priv = ib_get_mad_port(mad_agent_priv->agent.device,
@@ -755,10 +753,12 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
755 &mad_priv->mad.mad); 753 &mad_priv->mad.mad);
756 } 754 }
757 if (!port_priv || !recv_mad_agent) { 755 if (!port_priv || !recv_mad_agent) {
756 /*
757 * No receiving agent so drop packet and
758 * generate send completion.
759 */
758 kmem_cache_free(ib_mad_cache, mad_priv); 760 kmem_cache_free(ib_mad_cache, mad_priv);
759 kfree(local); 761 break;
760 ret = 0;
761 goto out;
762 } 762 }
763 local->mad_priv = mad_priv; 763 local->mad_priv = mad_priv;
764 local->recv_mad_agent = recv_mad_agent; 764 local->recv_mad_agent = recv_mad_agent;