FreeBSD/sys/dev/iser/iser_verbs.c
/**
 * triggers start of the disconnect procedures and wait for them to be done
 * Called with state mutex held
 */
triggers start of the disconnect procedures and wait for them to be done
Called with state mutex held
triggers start of the disconnect procedures and wait for them to be done Called with state mutex held
int
iser_conn_terminate(struct iser_conn *iser_conn)
{
	struct ib_conn *ib_conn = &iser_conn->ib_conn;
	struct ib_send_wr *bad_send_wr;
	struct ib_recv_wr *bad_recv_wr;
	int err = 0;
	if (!iser_conn_state_comp_exch(iser_conn, ISER_CONN_UP,
					   ISER_CONN_TERMINATING))
		return (0);
	ISER_INFO("iser_conn %p state %d\n", iser_conn, iser_conn->state);
	if (ib_conn->qp == NULL) {
		ISER_WARN("qp wasn't created");
		return (1);
	}
	sx_xlock(&ig.close_conns_mutex);
	if (ib_conn->cma_id) {
		err = rdma_disconnect(ib_conn->cma_id);
		if (err)
			ISER_ERR("Failed to disconnect, conn: 0x%p err %d",
				iser_conn, err);
		mtx_lock(&ib_conn->beacon.flush_lock);
		memset(&ib_conn->beacon.send, 0, sizeof(struct ib_send_wr));
		ib_conn->beacon.send.wr_id = ISER_BEACON_WRID;
		ib_conn->beacon.send.opcode = IB_WR_SEND;
		err = ib_post_send(ib_conn->qp, &ib_conn->beacon.send, &bad_send_wr);
		if (err) {
			ISER_ERR("conn %p failed to post send_beacon", ib_conn);
			mtx_unlock(&ib_conn->beacon.flush_lock);
			goto out;
		}
		ISER_DBG("before send cv_wait: %p", iser_conn);
		cv_wait(&ib_conn->beacon.flush_cv, &ib_conn->beacon.flush_lock);
		ISER_DBG("after send cv_wait: %p", iser_conn);
		memset(&ib_conn->beacon.recv, 0, sizeof(struct ib_recv_wr));
		ib_conn->beacon.recv.wr_id = ISER_BEACON_WRID;
		err = ib_post_recv(ib_conn->qp, &ib_conn->beacon.recv, &bad_recv_wr);
		if (err) {
			ISER_ERR("conn %p failed to post recv_beacon", ib_conn);
			mtx_unlock(&ib_conn->beacon.flush_lock);
			goto out;
		}
		ISER_DBG("before recv cv_wait: %p", iser_conn);
		cv_wait(&ib_conn->beacon.flush_cv, &ib_conn->beacon.flush_lock);
		mtx_unlock(&ib_conn->beacon.flush_lock);
		ISER_DBG("after recv cv_wait: %p", iser_conn);
	}
out:
	sx_xunlock(&ig.close_conns_mutex);
	return (1);
}
int iser_conn_terminate ( struct iser_conn * iser_conn ) { struct ib_conn * ib_conn = & iser_conn -> ib_conn ; struct ib_send_wr * bad_send_wr ; struct ib_recv_wr * bad_recv_wr ; int err = 0 ; if ( ! iser_conn_state_comp_exch ( iser_conn , ISER_CONN_UP , ISER_CONN_TERMINATING ) ) return ( 0 ) ; ISER_INFO ( " \n " , iser_conn , iser_conn -> state ) ; if ( ib_conn -> qp == NULL ) { ISER_WARN ( " " ) ; return ( 1 ) ; } sx_xlock ( & ig . close_conns_mutex ) ; if ( ib_conn -> cma_id ) { err = rdma_disconnect ( ib_conn -> cma_id ) ; if ( err ) ISER_ERR ( " " , iser_conn , err ) ; mtx_lock ( & ib_conn -> beacon . flush_lock ) ; memset ( & ib_conn -> beacon . send , 0 , sizeof ( struct ib_send_wr ) ) ; ib_conn -> beacon . send . wr_id = ISER_BEACON_WRID ; ib_conn -> beacon . send . opcode = IB_WR_SEND ; err = ib_post_send ( ib_conn -> qp , & ib_conn -> beacon . send , & bad_send_wr ) ; if ( err ) { ISER_ERR ( " " , ib_conn ) ; mtx_unlock ( & ib_conn -> beacon . flush_lock ) ; goto out ; } ISER_DBG ( " " , iser_conn ) ; cv_wait ( & ib_conn -> beacon . flush_cv , & ib_conn -> beacon . flush_lock ) ; ISER_DBG ( " " , iser_conn ) ; memset ( & ib_conn -> beacon . recv , 0 , sizeof ( struct ib_recv_wr ) ) ; ib_conn -> beacon . recv . wr_id = ISER_BEACON_WRID ; err = ib_post_recv ( ib_conn -> qp , & ib_conn -> beacon . recv , & bad_recv_wr ) ; if ( err ) { ISER_ERR ( " " , ib_conn ) ; mtx_unlock ( & ib_conn -> beacon . flush_lock ) ; goto out ; } ISER_DBG ( " " , iser_conn ) ; cv_wait ( & ib_conn -> beacon . flush_cv , & ib_conn -> beacon . flush_lock ) ; mtx_unlock ( & ib_conn -> beacon . flush_lock ) ; ISER_DBG ( " " , iser_conn ) ; } out : sx_xunlock ( & ig . close_conns_mutex ) ; return ( 1 ) ; }
triggers start of the disconnect procedures and wait for them to be done
 Called with state mutex held
triggers start of the disconnect procedures and wait for them to be done Called with state mutex held
/* terminate the iser conn only if the conn state is UP */ /* HOW can this be??? */ /*
	 * Todo: This is a temporary workaround.
	 * We serialize the connection closure using global lock in order to
	 * receive all posted beacons completions.
	 * Without Serialization, in case we open many connections (QPs) on
	 * the same CQ, we might miss beacons because of missing interrupts.
	 */ /*
	 * In case we didn't already clean up the cma_id (peer initiated
	 * a disconnection), we need to Cause the CMA to change the QP
	 * state to ERROR.
	 */ /* post an indication that all send flush errors were consumed */ /* post an indication that all recv flush errors were consumed */