drivers/scsi/qedf/qedf_els.c

Source file repositories/reference/linux-study-clean/drivers/scsi/qedf/qedf_els.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/qedf/qedf_els.c
Extension
.c
Size
28388 bytes
Lines
1067
Domain
Driver Families
Bucket
drivers/scsi
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

test_bit(QEDF_RPORT_IN_LUN_RESET, &fcport->flags)) {
		QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO,
			"Dropping ELS completion xid=0x%x as fcport is flushing",
			els_req->xid);
		return;
	}

	clear_bit(QEDF_CMD_OUTSTANDING, &els_req->flags);

	/* Kill the ELS timer */
	cancel_delayed_work(&els_req->timeout_work);

	/* Get ELS response length from CQE */
	mp_info = &cqe->cqe_info.midpath_info;
	els_req->mp_req.resp_len = mp_info->data_placement_size;

	/* Parse ELS response */
	if ((els_req->cb_func) && (els_req->cb_arg)) {
		els_req->cb_func(els_req->cb_arg);
		els_req->cb_arg = NULL;
	}

	kref_put(&els_req->refcount, qedf_release_cmd);
}

static void qedf_rrq_compl(struct qedf_els_cb_arg *cb_arg)
{
	struct qedf_ioreq *orig_io_req;
	struct qedf_ioreq *rrq_req;
	struct qedf_ctx *qedf;
	int refcount;

	rrq_req = cb_arg->io_req;
	qedf = rrq_req->fcport->qedf;

	QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Entered.\n");

	orig_io_req = cb_arg->aborted_io_req;

	if (!orig_io_req) {
		QEDF_ERR(&qedf->dbg_ctx,
			 "Original io_req is NULL, rrq_req = %p.\n", rrq_req);
		goto out_free;
	}

	refcount = kref_read(&orig_io_req->refcount);
	QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "rrq_compl: orig io = %p,"
		   " orig xid = 0x%x, rrq_xid = 0x%x, refcount=%d\n",
		   orig_io_req, orig_io_req->xid, rrq_req->xid, refcount);

	/*
	 * This should return the aborted io_req to the command pool. Note that
	 * we need to check the refcound in case the original request was
	 * flushed but we get a completion on this xid.
	 */
	if (orig_io_req && refcount > 0)
		kref_put(&orig_io_req->refcount, qedf_release_cmd);

out_free:
	/*
	 * Release a reference to the rrq request if we timed out as the
	 * rrq completion handler is called directly from the timeout handler
	 * and not from els_compl where the reference would have normally been
	 * released.
	 */
	if (rrq_req->event == QEDF_IOREQ_EV_ELS_TMO)
		kref_put(&rrq_req->refcount, qedf_release_cmd);
	kfree(cb_arg);
}

/* Assumes kref is already held by caller */
int qedf_send_rrq(struct qedf_ioreq *aborted_io_req)
{

	struct fc_els_rrq rrq;
	struct qedf_rport *fcport;
	struct fc_lport *lport;
	struct qedf_els_cb_arg *cb_arg = NULL;
	struct qedf_ctx *qedf;
	uint32_t sid;
	uint32_t r_a_tov;
	int rc;
	int refcount;

	if (!aborted_io_req) {
		QEDF_ERR(NULL, "abort_io_req is NULL.\n");
		return -EINVAL;
	}

	fcport = aborted_io_req->fcport;

Annotation

Implementation Notes