FreeBSD/sys/ofed/drivers/infiniband/core/iwcm.c
/*
 * CM_ID <-- IDLE
 *
 * If in the ESTBLISHED or CLOSING states, the QP will have have been
 * moved by the provider to the ERR state. Disassociate the CM_ID from
 * the QP,  move to IDLE, and remove the 'connected' reference.
 *
 * If in some other state, the cm_id was destroyed asynchronously.
 * This is the last reference that will result in waking up
 * the app thread blocked in iw_destroy_cm_id.
 */
CM_ID <-- IDLE
If in the ESTBLISHED or CLOSING states, the QP will have have been
moved by the provider to the ERR state. Disassociate the CM_ID from
the QP,  move to IDLE, and remove the 'connected' reference.

If in some other state, the cm_id was destroyed asynchronously.
This is the last reference that will result in waking up
the app thread blocked in iw_destroy_cm_id.
CM_ID < -- IDLE If in the ESTBLISHED or CLOSING states the QP will have have been moved by the provider to the ERR state . Disassociate the CM_ID from the QP move to IDLE and remove the ' connected ' reference . If in some other state the cm_id was destroyed asynchronously . This is the last reference that will result in waking up the app thread blocked in iw_destroy_cm_id .
static int cm_close_handler(struct iwcm_id_private *cm_id_priv,
				  struct iw_cm_event *iw_event)
{
	unsigned long flags;
	int ret = 0;
	spin_lock_irqsave(&cm_id_priv->lock, flags);
	if (cm_id_priv->qp) {
		cm_id_priv->id.device->iwcm->rem_ref(cm_id_priv->qp);
		cm_id_priv->qp = NULL;
	}
	switch (cm_id_priv->state) {
	case IW_CM_STATE_ESTABLISHED:
	case IW_CM_STATE_CLOSING:
		cm_id_priv->state = IW_CM_STATE_IDLE;
		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
		ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
		spin_lock_irqsave(&cm_id_priv->lock, flags);
		break;
	case IW_CM_STATE_DESTROYING:
		break;
	default:
		BUG();
	}
	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
	return ret;
}
static int cm_close_handler ( struct iwcm_id_private * cm_id_priv , struct iw_cm_event * iw_event ) { unsigned long flags ; int ret = 0 ; spin_lock_irqsave ( & cm_id_priv -> lock , flags ) ; if ( cm_id_priv -> qp ) { cm_id_priv -> id . device -> iwcm -> rem_ref ( cm_id_priv -> qp ) ; cm_id_priv -> qp = NULL ; } switch ( cm_id_priv -> state ) { case IW_CM_STATE_ESTABLISHED : case IW_CM_STATE_CLOSING : cm_id_priv -> state = IW_CM_STATE_IDLE ; spin_unlock_irqrestore ( & cm_id_priv -> lock , flags ) ; ret = cm_id_priv -> id . cm_handler ( & cm_id_priv -> id , iw_event ) ; spin_lock_irqsave ( & cm_id_priv -> lock , flags ) ; break ; case IW_CM_STATE_DESTROYING : break ; default : BUG ( ) ; } spin_unlock_irqrestore ( & cm_id_priv -> lock , flags ) ; return ret ; }
CM_ID <-- IDLE
 If in the ESTBLISHED or CLOSING states, the QP will have have been
 moved by the provider to the ERR state.
CM_ID < -- IDLE If in the ESTBLISHED or CLOSING states the QP will have have been moved by the provider to the ERR state .