drivers/scsi/elx/efct/efct_unsol.c

Source file repositories/reference/linux-study-clean/drivers/scsi/elx/efct/efct_unsol.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/elx/efct/efct_unsol.c
Extension
.c
Size
12700 bytes
Lines
493
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

if (!node) {
			efc_log_err(efct,
				    "Node not found, drop cmd d_id:%x s_id:%x\n",
				    d_id, s_id);
			efct_hw_sequence_free(&efct->hw, seq);
			return 0;
		}

		efct_dispatch_fcp_cmd(node, seq);
	} else {
		node = efct_node_find(efct, d_id, s_id);
		if (!node) {
			efc_log_err(efct, "ABTS: Node not found, d_id:%x s_id:%x\n",
				    d_id, s_id);
			return -EIO;
		}

		efc_log_err(efct, "Received ABTS for Node:%p\n", node);
		efct_node_recv_abts_frame(node, seq);
	}

	kref_put(&node->ref, node->release);
	efct_hw_sequence_free(&efct->hw, seq);
	return 0;
}

int
efct_unsolicited_cb(void *arg, struct efc_hw_sequence *seq)
{
	struct efct *efct = arg;

	/* Process FCP command */
	if (!efct_dispatch_frame(efct, seq))
		return 0;

	/* Forward frame to discovery lib */
	efc_dispatch_frame(efct->efcport, seq);
	return 0;
}

static int
efct_fc_tmf_rejected_cb(struct efct_io *io,
			enum efct_scsi_io_status scsi_status,
			u32 flags, void *arg)
{
	efct_scsi_io_free(io);
	return 0;
}

static void
efct_dispatch_unsol_tmf(struct efct_io *io, u8 tm_flags, u32 lun)
{
	u32 i;
	struct {
		u32 mask;
		enum efct_scsi_tmf_cmd cmd;
	} tmflist[] = {
	{FCP_TMF_ABT_TASK_SET, EFCT_SCSI_TMF_ABORT_TASK_SET},
	{FCP_TMF_CLR_TASK_SET, EFCT_SCSI_TMF_CLEAR_TASK_SET},
	{FCP_TMF_LUN_RESET, EFCT_SCSI_TMF_LOGICAL_UNIT_RESET},
	{FCP_TMF_TGT_RESET, EFCT_SCSI_TMF_TARGET_RESET},
	{FCP_TMF_CLR_ACA, EFCT_SCSI_TMF_CLEAR_ACA} };

	io->exp_xfer_len = 0;

	for (i = 0; i < ARRAY_SIZE(tmflist); i++) {
		if (tmflist[i].mask & tm_flags) {
			io->tmf_cmd = tmflist[i].cmd;
			efct_scsi_recv_tmf(io, lun, tmflist[i].cmd, NULL, 0);
			break;
		}
	}
	if (i == ARRAY_SIZE(tmflist)) {
		/* Not handled */
		efc_log_err(io->node->efct, "TMF x%x rejected\n", tm_flags);
		efct_scsi_send_tmf_resp(io, EFCT_SCSI_TMF_FUNCTION_REJECTED,
					NULL, efct_fc_tmf_rejected_cb, NULL);
	}
}

static int
efct_validate_fcp_cmd(struct efct *efct, struct efc_hw_sequence *seq)
{
	/*
	 * If we received less than FCP_CMND_IU bytes, assume that the frame is
	 * corrupted in some way and drop it.
	 * This was seen when jamming the FCTL
	 * fill bytes field.
	 */
	if (seq->payload->dma.len < sizeof(struct fcp_cmnd)) {

Annotation

Implementation Notes