drivers/target/tcm_fc/tfc_cmd.c

Source file repositories/reference/linux-study-clean/drivers/target/tcm_fc/tfc_cmd.c

File Facts

System
Linux kernel
Corpus path
drivers/target/tcm_fc/tfc_cmd.c
Extension
.c
Size
13857 bytes
Lines
563
Domain
Driver Families
Bucket
drivers/target
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

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2010 Cisco Systems, Inc.
 */

/* XXX TBD some includes may be extraneous */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/utsname.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/configfs.h>
#include <linux/ctype.h>
#include <linux/hash.h>
#include <linux/unaligned.h>
#include <scsi/scsi_tcq.h>
#include <scsi/libfc.h>

#include <target/target_core_base.h>
#include <target/target_core_fabric.h>

#include "tcm_fc.h"

/*
 * Dump cmd state for debugging.
 */
static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
{
	struct fc_exch *ep;
	struct fc_seq *sp;
	struct se_cmd *se_cmd;
	struct scatterlist *sg;
	int count;

	se_cmd = &cmd->se_cmd;
	pr_debug("%s: cmd %p sess %p seq %p se_cmd %p\n",
		caller, cmd, cmd->sess, cmd->seq, se_cmd);

	pr_debug("%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n",
		caller, cmd, se_cmd->t_data_nents,
	       se_cmd->data_length, se_cmd->se_cmd_flags);

	for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, count)
		pr_debug("%s: cmd %p sg %p page %p "
			"len 0x%x off 0x%x\n",
			caller, cmd, sg,
			sg_page(sg), sg->length, sg->offset);

	sp = cmd->seq;
	if (sp) {
		ep = fc_seq_exch(sp);
		pr_debug("%s: cmd %p sid %x did %x "
			"ox_id %x rx_id %x seq_id %x e_stat %x\n",
			caller, cmd, ep->sid, ep->did, ep->oxid, ep->rxid,
			sp->id, ep->esb_stat);
	}
}

void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
{
	if (unlikely(ft_debug_logging))
		_ft_dump_cmd(cmd, caller);
}

static void ft_free_cmd(struct ft_cmd *cmd)
{
	struct fc_frame *fp;
	struct ft_sess *sess;

	if (!cmd)
		return;
	sess = cmd->sess;
	fp = cmd->req_frame;
	if (fr_seq(fp))
		fc_seq_release(fr_seq(fp));
	fc_frame_free(fp);
	target_free_tag(sess->se_sess, &cmd->se_cmd);
	ft_sess_put(sess);	/* undo get from lookup at recv */
}

void ft_release_cmd(struct se_cmd *se_cmd)
{
	struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);

	ft_free_cmd(cmd);
}

Annotation

Implementation Notes