Version: 1
-Previous: 1397d161d2dc8fa13f1645c7340b79f3f83398b1
+Previous: 815c34644aa17ec9daf6cd3de69e94fed9e31a11
Head: d6d2302f2d258fa2c07e55a2e124a9bdd75367a0
Applied:
rm-build: d6d2302f2d258fa2c07e55a2e124a9bdd75367a0
Unapplied:
old-bld-32: bd1bd1d366e3927b7646da33e243213a5d59c235
old-apphang: 7a6f7ff02c6035e54fc262414eb9484ea98018b9
- cm_send_cb: 70dceed7518c8429e4c9e0646c7ec035f1cf53cb
+ old-cm_send_cb: 70dceed7518c8429e4c9e0646c7ec035f1cf53cb
queue_mads: a9c572c34ae693764a33e87173125d3065a6d1c5
epdisc: 4c931f6af5e37a502f7a10b78a902747f9738623
Hidden:
+++ /dev/null
-Bottom: ed7908e04b3bbaa4e2413f01b2efe982eb5349d8
-Top: 7edcb31c25e21f961a1e6f9af11bf03fa5d98c65
-Author: U-AMR\MSHEFTY <MSHEFTY@mshefty-MOBL2.amr.corp.intel.com>
-Date: 2009-12-07 10:36:50 -0800
-
-ib/cm: fix handling failed send completions
-
-__cep_mad_send_cb() assumes that the mad being processed is
-associated with the current state of the CEP. This may not be
-the case.
-
-For example, for a short lived connection, it was observed that
-a REP mad completed with status canceled. This is normal. However,
-the user already attempted to disconnect the connection by sending
-a DREQ. This left the cep in the DREQ_SENT state by the time that
-the REP mad completed. Since the REP failed, but the state was
-DREQ_SENT, the code assumed that the DREQ had failed and transitioned
-the cep into TIMEWAIT. The result is that the DREQ is never
-matched with a DREP or canceled, but holds a reference on the CEP.
-
-Until the DREQ times out (time depends on connection, but easily
-up to a minute), attempts to destroy the CEP are blocked.
-
-Fix this by simply discarding any completed sends that were not
-sent from the current state of the cep when the completion handler
-is invoked.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/trunk/core/al/kernel/al_cm.c b/trunk/core/al/kernel/al_cm.c
-index 48b0cb5..955985a 100644
---- a/trunk/core/al/kernel/al_cm.c
-+++ b/trunk/core/al/kernel/al_cm.c
-@@ -37,7 +37,7 @@
- typedef struct _iba_cm_id_priv\r
- {\r
- iba_cm_id id;\r
-- KEVENT destroy_event; \r
-+ KEVENT destroy_event;\r
- \r
- } iba_cm_id_priv;\r
- \r
-diff --git a/trunk/core/al/kernel/al_cm_cep.c b/trunk/core/al/kernel/al_cm_cep.c
-index 49fa417..4987207 100644
---- a/trunk/core/al/kernel/al_cm_cep.c
-+++ b/trunk/core/al/kernel/al_cm_cep.c
-@@ -27,7 +27,7 @@
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
-- * $Id$\r
-+ * $Id: al_cm_cep.c 2540 2009-11-03 17:23:09Z shefty $\r
- */\r
- \r
- \r
-@@ -2213,10 +2213,7 @@ __cep_mad_send_cb(
- \r
- p_cep = (kcep_t*)p_mad->context1;\r
- \r
-- /*\r
-- * The connection context is not set when performing immediate responses,\r
-- * such as repeating MADS.\r
-- */\r
-+ /* The cep context is only set for MADs that are retried. */\r
- if( !p_cep )\r
- {\r
- ib_put_mad( p_mad );\r
-@@ -2224,94 +2221,71 @@ __cep_mad_send_cb(
- return;\r
- }\r
- \r
-+ CL_ASSERT( p_mad->status != IB_WCS_SUCCESS );\r
- p_mad->context1 = NULL;\r
- \r
- KeAcquireInStackQueuedSpinLockAtDpcLevel( &gp_cep_mgr->lock, &hdl );\r
-- /* Clear the sent MAD pointer so that we don't try cancelling again. */\r
-- if( p_cep->p_send_mad == p_mad )\r
-- p_cep->p_send_mad = NULL;\r
--\r
-- switch( p_mad->status )\r
-+ if( p_cep->p_send_mad != p_mad )\r
- {\r
-- case IB_WCS_SUCCESS:\r
- KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
- ib_put_mad( p_mad );\r
-- break;\r
--\r
-- case IB_WCS_CANCELED:\r
-- if( p_cep->state != CEP_STATE_REQ_SENT &&\r
-- p_cep->state != CEP_STATE_REQ_MRA_RCVD &&\r
-- p_cep->state != CEP_STATE_REP_SENT &&\r
-- p_cep->state != CEP_STATE_REP_MRA_RCVD &&\r
-- p_cep->state != CEP_STATE_LAP_SENT &&\r
-- p_cep->state != CEP_STATE_LAP_MRA_RCVD &&\r
-- p_cep->state != CEP_STATE_DREQ_SENT &&\r
-- p_cep->state != CEP_STATE_SREQ_SENT )\r
-- {\r
-- KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
-- ib_put_mad( p_mad );\r
-- break;\r
-- }\r
-- /* Treat as a timeout so we don't stall the state machine. */\r
-- p_mad->status = IB_WCS_TIMEOUT_RETRY_ERR;\r
--\r
-- /* Fall through. */\r
-- case IB_WCS_TIMEOUT_RETRY_ERR:\r
-- default:\r
-- /* Timeout. Reject the connection. */\r
-- switch( p_cep->state )\r
-- {\r
-- case CEP_STATE_REQ_SENT:\r
-- case CEP_STATE_REQ_MRA_RCVD:\r
-- case CEP_STATE_REP_SENT:\r
-- case CEP_STATE_REP_MRA_RCVD:\r
-- /* Send the REJ. */\r
-- __reject_timeout( p_port_cep, p_cep, p_mad );\r
-- __remove_cep( p_cep );\r
-- p_cep->state = CEP_STATE_IDLE;\r
-- break;\r
--\r
-- case CEP_STATE_DREQ_DESTROY:\r
-- p_cep->state = CEP_STATE_DESTROY;\r
-- __insert_timewait( p_cep );\r
-- /* Fall through. */\r
-+ goto done;\r
-+ }\r
- \r
-- case CEP_STATE_DESTROY:\r
-- KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
-- ib_put_mad( p_mad );\r
-- goto done;\r
-+ /* Clear the sent MAD pointer so that we don't try cancelling again. */\r
-+ p_cep->p_send_mad = NULL;\r
- \r
-- case CEP_STATE_DREQ_SENT:\r
-- /*\r
-- * Make up a DREP mad so we can respond if we receive\r
-- * a DREQ while in timewait.\r
-- */\r
-- __format_mad_hdr( &p_cep->mads.drep.hdr, p_cep, CM_DREP_ATTR_ID );\r
-- __format_drep( p_cep, NULL, 0, &p_cep->mads.drep );\r
-- p_cep->state = CEP_STATE_TIMEWAIT;\r
-- __insert_timewait( p_cep );\r
-- break;\r
-+ switch( p_cep->state )\r
-+ {\r
-+ case CEP_STATE_REQ_SENT:\r
-+ case CEP_STATE_REQ_MRA_RCVD:\r
-+ case CEP_STATE_REP_SENT:\r
-+ case CEP_STATE_REP_MRA_RCVD:\r
-+ /* Send the REJ. */\r
-+ __reject_timeout( p_port_cep, p_cep, p_mad );\r
-+ __remove_cep( p_cep );\r
-+ p_cep->state = CEP_STATE_IDLE;\r
-+ break;\r
- \r
-- case CEP_STATE_LAP_SENT:\r
-- /*\r
-- * Before CEP was sent, we have been in CEP_STATE_ESTABLISHED as we\r
-- * failed to send, we return to that state.\r
-- */\r
-- p_cep->state = CEP_STATE_ESTABLISHED;\r
-- break;\r
-- default:\r
-- break;\r
-- }\r
-+ case CEP_STATE_DREQ_DESTROY:\r
-+ p_cep->state = CEP_STATE_DESTROY;\r
-+ __insert_timewait( p_cep );\r
-+ /* Fall through. */\r
- \r
-- status = __cep_queue_mad( p_cep, p_mad );\r
-- CL_ASSERT( status != IB_INVALID_STATE );\r
-+ case CEP_STATE_DESTROY:\r
- KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
-+ ib_put_mad( p_mad );\r
-+ goto done;\r
- \r
-- if( status == IB_SUCCESS )\r
-- __process_cep( p_cep );\r
-+ case CEP_STATE_DREQ_SENT:\r
-+ /*\r
-+ * Make up a DREP mad so we can respond if we receive\r
-+ * a DREQ while in timewait.\r
-+ */\r
-+ __format_mad_hdr( &p_cep->mads.drep.hdr, p_cep, CM_DREP_ATTR_ID );\r
-+ __format_drep( p_cep, NULL, 0, &p_cep->mads.drep );\r
-+ p_cep->state = CEP_STATE_TIMEWAIT;\r
-+ __insert_timewait( p_cep );\r
-+ break;\r
-+\r
-+ case CEP_STATE_LAP_SENT:\r
-+ /*\r
-+ * Before CEP was sent, we have been in CEP_STATE_ESTABLISHED as we\r
-+ * failed to send, we return to that state.\r
-+ */\r
-+ p_cep->state = CEP_STATE_ESTABLISHED;\r
-+ break;\r
-+ default:\r
- break;\r
- }\r
- \r
-+ status = __cep_queue_mad( p_cep, p_mad );\r
-+ CL_ASSERT( status != IB_INVALID_STATE );\r
-+ KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
-+\r
-+ if( status == IB_SUCCESS )\r
-+ __process_cep( p_cep );\r
-+\r
- done:\r
- pfn_destroy_cb = p_cep->pfn_destroy_cb;\r
- cep_context = p_cep->context;\r
-@@ -3938,12 +3912,8 @@ __cleanup_cep(
- CL_ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL );\r
- \r
- /* If we've already come through here, we're done. */\r
-- if( p_cep->state == CEP_STATE_DESTROY ||\r
-- p_cep->state == CEP_STATE_DREQ_DESTROY )\r
-- {\r
-- AL_EXIT( AL_DBG_CM );\r
-- return -1;\r
-- }\r
-+ CL_ASSERT( p_cep->state != CEP_STATE_DESTROY &&\r
-+ p_cep->state != CEP_STATE_DREQ_DESTROY );\r
- \r
- /* Cleanup the pending MAD list. */\r
- while( p_cep->p_mad_head )
--- /dev/null
+Bottom: ed7908e04b3bbaa4e2413f01b2efe982eb5349d8
+Top: 7edcb31c25e21f961a1e6f9af11bf03fa5d98c65
+Author: U-AMR\MSHEFTY <MSHEFTY@mshefty-MOBL2.amr.corp.intel.com>
+Date: 2009-12-07 10:36:50 -0800
+
+ib/cm: fix handling failed send completions
+
+__cep_mad_send_cb() assumes that the mad being processed is
+associated with the current state of the CEP. This may not be
+the case.
+
+For example, for a short lived connection, it was observed that
+a REP mad completed with status canceled. This is normal. However,
+the user already attempted to disconnect the connection by sending
+a DREQ. This left the cep in the DREQ_SENT state by the time that
+the REP mad completed. Since the REP failed, but the state was
+DREQ_SENT, the code assumed that the DREQ had failed and transitioned
+the cep into TIMEWAIT. The result is that the DREQ is never
+matched with a DREP or canceled, but holds a reference on the CEP.
+
+Until the DREQ times out (time depends on connection, but easily
+up to a minute), attempts to destroy the CEP are blocked.
+
+Fix this by simply discarding any completed sends that were not
+sent from the current state of the cep when the completion handler
+is invoked.
+
+Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+
+
+---
+
+diff --git a/trunk/core/al/kernel/al_cm.c b/trunk/core/al/kernel/al_cm.c
+index 48b0cb5..955985a 100644
+--- a/trunk/core/al/kernel/al_cm.c
++++ b/trunk/core/al/kernel/al_cm.c
+@@ -37,7 +37,7 @@
+ typedef struct _iba_cm_id_priv\r
+ {\r
+ iba_cm_id id;\r
+- KEVENT destroy_event; \r
++ KEVENT destroy_event;\r
+ \r
+ } iba_cm_id_priv;\r
+ \r
+diff --git a/trunk/core/al/kernel/al_cm_cep.c b/trunk/core/al/kernel/al_cm_cep.c
+index 49fa417..4987207 100644
+--- a/trunk/core/al/kernel/al_cm_cep.c
++++ b/trunk/core/al/kernel/al_cm_cep.c
+@@ -27,7 +27,7 @@
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+- * $Id$\r
++ * $Id: al_cm_cep.c 2540 2009-11-03 17:23:09Z shefty $\r
+ */\r
+ \r
+ \r
+@@ -2213,10 +2213,7 @@ __cep_mad_send_cb(
+ \r
+ p_cep = (kcep_t*)p_mad->context1;\r
+ \r
+- /*\r
+- * The connection context is not set when performing immediate responses,\r
+- * such as repeating MADS.\r
+- */\r
++ /* The cep context is only set for MADs that are retried. */\r
+ if( !p_cep )\r
+ {\r
+ ib_put_mad( p_mad );\r
+@@ -2224,94 +2221,71 @@ __cep_mad_send_cb(
+ return;\r
+ }\r
+ \r
++ CL_ASSERT( p_mad->status != IB_WCS_SUCCESS );\r
+ p_mad->context1 = NULL;\r
+ \r
+ KeAcquireInStackQueuedSpinLockAtDpcLevel( &gp_cep_mgr->lock, &hdl );\r
+- /* Clear the sent MAD pointer so that we don't try cancelling again. */\r
+- if( p_cep->p_send_mad == p_mad )\r
+- p_cep->p_send_mad = NULL;\r
+-\r
+- switch( p_mad->status )\r
++ if( p_cep->p_send_mad != p_mad )\r
+ {\r
+- case IB_WCS_SUCCESS:\r
+ KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
+ ib_put_mad( p_mad );\r
+- break;\r
+-\r
+- case IB_WCS_CANCELED:\r
+- if( p_cep->state != CEP_STATE_REQ_SENT &&\r
+- p_cep->state != CEP_STATE_REQ_MRA_RCVD &&\r
+- p_cep->state != CEP_STATE_REP_SENT &&\r
+- p_cep->state != CEP_STATE_REP_MRA_RCVD &&\r
+- p_cep->state != CEP_STATE_LAP_SENT &&\r
+- p_cep->state != CEP_STATE_LAP_MRA_RCVD &&\r
+- p_cep->state != CEP_STATE_DREQ_SENT &&\r
+- p_cep->state != CEP_STATE_SREQ_SENT )\r
+- {\r
+- KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
+- ib_put_mad( p_mad );\r
+- break;\r
+- }\r
+- /* Treat as a timeout so we don't stall the state machine. */\r
+- p_mad->status = IB_WCS_TIMEOUT_RETRY_ERR;\r
+-\r
+- /* Fall through. */\r
+- case IB_WCS_TIMEOUT_RETRY_ERR:\r
+- default:\r
+- /* Timeout. Reject the connection. */\r
+- switch( p_cep->state )\r
+- {\r
+- case CEP_STATE_REQ_SENT:\r
+- case CEP_STATE_REQ_MRA_RCVD:\r
+- case CEP_STATE_REP_SENT:\r
+- case CEP_STATE_REP_MRA_RCVD:\r
+- /* Send the REJ. */\r
+- __reject_timeout( p_port_cep, p_cep, p_mad );\r
+- __remove_cep( p_cep );\r
+- p_cep->state = CEP_STATE_IDLE;\r
+- break;\r
+-\r
+- case CEP_STATE_DREQ_DESTROY:\r
+- p_cep->state = CEP_STATE_DESTROY;\r
+- __insert_timewait( p_cep );\r
+- /* Fall through. */\r
++ goto done;\r
++ }\r
+ \r
+- case CEP_STATE_DESTROY:\r
+- KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
+- ib_put_mad( p_mad );\r
+- goto done;\r
++ /* Clear the sent MAD pointer so that we don't try cancelling again. */\r
++ p_cep->p_send_mad = NULL;\r
+ \r
+- case CEP_STATE_DREQ_SENT:\r
+- /*\r
+- * Make up a DREP mad so we can respond if we receive\r
+- * a DREQ while in timewait.\r
+- */\r
+- __format_mad_hdr( &p_cep->mads.drep.hdr, p_cep, CM_DREP_ATTR_ID );\r
+- __format_drep( p_cep, NULL, 0, &p_cep->mads.drep );\r
+- p_cep->state = CEP_STATE_TIMEWAIT;\r
+- __insert_timewait( p_cep );\r
+- break;\r
++ switch( p_cep->state )\r
++ {\r
++ case CEP_STATE_REQ_SENT:\r
++ case CEP_STATE_REQ_MRA_RCVD:\r
++ case CEP_STATE_REP_SENT:\r
++ case CEP_STATE_REP_MRA_RCVD:\r
++ /* Send the REJ. */\r
++ __reject_timeout( p_port_cep, p_cep, p_mad );\r
++ __remove_cep( p_cep );\r
++ p_cep->state = CEP_STATE_IDLE;\r
++ break;\r
+ \r
+- case CEP_STATE_LAP_SENT:\r
+- /*\r
+- * Before CEP was sent, we have been in CEP_STATE_ESTABLISHED as we\r
+- * failed to send, we return to that state.\r
+- */\r
+- p_cep->state = CEP_STATE_ESTABLISHED;\r
+- break;\r
+- default:\r
+- break;\r
+- }\r
++ case CEP_STATE_DREQ_DESTROY:\r
++ p_cep->state = CEP_STATE_DESTROY;\r
++ __insert_timewait( p_cep );\r
++ /* Fall through. */\r
+ \r
+- status = __cep_queue_mad( p_cep, p_mad );\r
+- CL_ASSERT( status != IB_INVALID_STATE );\r
++ case CEP_STATE_DESTROY:\r
+ KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
++ ib_put_mad( p_mad );\r
++ goto done;\r
+ \r
+- if( status == IB_SUCCESS )\r
+- __process_cep( p_cep );\r
++ case CEP_STATE_DREQ_SENT:\r
++ /*\r
++ * Make up a DREP mad so we can respond if we receive\r
++ * a DREQ while in timewait.\r
++ */\r
++ __format_mad_hdr( &p_cep->mads.drep.hdr, p_cep, CM_DREP_ATTR_ID );\r
++ __format_drep( p_cep, NULL, 0, &p_cep->mads.drep );\r
++ p_cep->state = CEP_STATE_TIMEWAIT;\r
++ __insert_timewait( p_cep );\r
++ break;\r
++\r
++ case CEP_STATE_LAP_SENT:\r
++ /*\r
++ * Before CEP was sent, we have been in CEP_STATE_ESTABLISHED as we\r
++ * failed to send, we return to that state.\r
++ */\r
++ p_cep->state = CEP_STATE_ESTABLISHED;\r
++ break;\r
++ default:\r
+ break;\r
+ }\r
+ \r
++ status = __cep_queue_mad( p_cep, p_mad );\r
++ CL_ASSERT( status != IB_INVALID_STATE );\r
++ KeReleaseInStackQueuedSpinLockFromDpcLevel( &hdl );\r
++\r
++ if( status == IB_SUCCESS )\r
++ __process_cep( p_cep );\r
++\r
+ done:\r
+ pfn_destroy_cb = p_cep->pfn_destroy_cb;\r
+ cep_context = p_cep->context;\r
+@@ -3938,12 +3912,8 @@ __cleanup_cep(
+ CL_ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL );\r
+ \r
+ /* If we've already come through here, we're done. */\r
+- if( p_cep->state == CEP_STATE_DESTROY ||\r
+- p_cep->state == CEP_STATE_DREQ_DESTROY )\r
+- {\r
+- AL_EXIT( AL_DBG_CM );\r
+- return -1;\r
+- }\r
++ CL_ASSERT( p_cep->state != CEP_STATE_DESTROY &&\r
++ p_cep->state != CEP_STATE_DREQ_DESTROY );\r
+ \r
+ /* Cleanup the pending MAD list. */\r
+ while( p_cep->p_mad_head )