drivers/infiniband/sw/siw/siw_qp.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/sw/siw/siw_qp.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/sw/siw/siw_qp.c
Extension
.c
Size
32481 bytes
Lines
1319
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

down_read_trylock(&qp->state_lock))) {
		read_descriptor_t rd_desc = { .arg.data = qp, .count = 1 };

		if (likely(qp->attrs.state == SIW_QP_STATE_RTS))
			/*
			 * Implements data receive operation during
			 * socket callback. TCP gracefully catches
			 * the case where there is nothing to receive
			 * (not calling siw_tcp_rx_data() then).
			 */
			tcp_read_sock(sk, &rd_desc, siw_tcp_rx_data);

		up_read(&qp->state_lock);
	} else {
		siw_dbg_qp(qp, "unable to process RX, suspend: %d\n",
			   qp->rx_stream.rx_suspend);
	}
done:
	read_unlock(&sk->sk_callback_lock);
}

void siw_qp_llp_close(struct siw_qp *qp)
{
	siw_dbg_qp(qp, "enter llp close, state = %s\n",
		   siw_qp_state_to_string[qp->attrs.state]);

	down_write(&qp->state_lock);

	qp->rx_stream.rx_suspend = 1;
	qp->tx_ctx.tx_suspend = 1;
	qp->attrs.sk = NULL;

	switch (qp->attrs.state) {
	case SIW_QP_STATE_RTS:
	case SIW_QP_STATE_RTR:
	case SIW_QP_STATE_IDLE:
	case SIW_QP_STATE_TERMINATE:
		qp->attrs.state = SIW_QP_STATE_ERROR;
		break;
	/*
	 * SIW_QP_STATE_CLOSING:
	 *
	 * This is a forced close. shall the QP be moved to
	 * ERROR or IDLE ?
	 */
	case SIW_QP_STATE_CLOSING:
		if (tx_wqe(qp)->wr_status == SIW_WR_IDLE)
			qp->attrs.state = SIW_QP_STATE_ERROR;
		else
			qp->attrs.state = SIW_QP_STATE_IDLE;
		break;

	default:
		siw_dbg_qp(qp, "llp close: no state transition needed: %s\n",
			   siw_qp_state_to_string[qp->attrs.state]);
		break;
	}
	siw_sq_flush(qp);
	siw_rq_flush(qp);

	/*
	 * Dereference closing CEP
	 */
	if (qp->cep) {
		siw_cep_put(qp->cep);
		qp->cep = NULL;
	}

	up_write(&qp->state_lock);

	siw_dbg_qp(qp, "llp close exit: state %s\n",
		   siw_qp_state_to_string[qp->attrs.state]);
}

/*
 * socket callback routine informing about newly available send space.
 * Function schedules SQ work for processing SQ items.
 */
void siw_qp_llp_write_space(struct sock *sk)
{
	struct siw_cep *cep;

	read_lock(&sk->sk_callback_lock);

	cep  = sk_to_cep(sk);
	if (cep) {
		cep->sk_write_space(sk);

		if (!test_bit(SOCK_NOSPACE, &sk->sk_socket->flags))
			(void)siw_sq_start(cep->qp);

Annotation

Implementation Notes