drivers/scsi/scsi_lib.c

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

File Facts

System
Linux kernel
Corpus path
drivers/scsi/scsi_lib.c
Extension
.c
Size
96428 bytes
Lines
3602
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct blk_mq_ops scsi_mq_ops_no_commit = {
	.get_budget	= scsi_mq_get_budget,
	.put_budget	= scsi_mq_put_budget,
	.queue_rq	= scsi_queue_rq,
	.complete	= scsi_complete,
	.timeout	= scsi_timeout,
#ifdef CONFIG_BLK_DEBUG_FS
	.show_rq	= scsi_show_rq,
#endif
	.init_request	= scsi_mq_init_request,
	.exit_request	= scsi_mq_exit_request,
	.cleanup_rq	= scsi_cleanup_rq,
	.busy		= scsi_mq_lld_busy,
	.map_queues	= scsi_map_queues,
	.init_hctx	= scsi_init_hctx,
	.poll		= scsi_mq_poll,
	.set_rq_budget_token = scsi_mq_set_rq_budget_token,
	.get_rq_budget_token = scsi_mq_get_rq_budget_token,
};


static void scsi_commit_rqs(struct blk_mq_hw_ctx *hctx)
{
	struct Scsi_Host *shost = hctx->driver_data;

	shost->hostt->commit_rqs(shost, hctx->queue_num);
}

static const struct blk_mq_ops scsi_mq_ops = {
	.get_budget	= scsi_mq_get_budget,
	.put_budget	= scsi_mq_put_budget,
	.queue_rq	= scsi_queue_rq,
	.commit_rqs	= scsi_commit_rqs,
	.complete	= scsi_complete,
	.timeout	= scsi_timeout,
#ifdef CONFIG_BLK_DEBUG_FS
	.show_rq	= scsi_show_rq,
#endif
	.init_request	= scsi_mq_init_request,
	.exit_request	= scsi_mq_exit_request,
	.cleanup_rq	= scsi_cleanup_rq,
	.busy		= scsi_mq_lld_busy,
	.map_queues	= scsi_map_queues,
	.init_hctx	= scsi_init_hctx,
	.poll		= scsi_mq_poll,
	.set_rq_budget_token = scsi_mq_set_rq_budget_token,
	.get_rq_budget_token = scsi_mq_get_rq_budget_token,
};

int scsi_mq_setup_tags(struct Scsi_Host *shost)
{
	unsigned int cmd_size, sgl_size;
	struct blk_mq_tag_set *tag_set = &shost->tag_set;

	sgl_size = max_t(unsigned int, sizeof(struct scatterlist),
				scsi_mq_inline_sgl_size(shost));
	cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size + sgl_size;
	if (scsi_host_get_prot(shost))
		cmd_size += sizeof(struct scsi_data_buffer) +
			sizeof(struct scatterlist) * SCSI_INLINE_PROT_SG_CNT;

	memset(tag_set, 0, sizeof(*tag_set));
	if (shost->hostt->commit_rqs)
		tag_set->ops = &scsi_mq_ops;
	else
		tag_set->ops = &scsi_mq_ops_no_commit;
	tag_set->nr_hw_queues = shost->nr_hw_queues ? : 1;
	tag_set->nr_maps = shost->nr_maps ? : 1;
	tag_set->queue_depth = shost->can_queue + shost->nr_reserved_cmds;
	tag_set->reserved_tags = shost->nr_reserved_cmds;
	tag_set->cmd_size = cmd_size;
	tag_set->numa_node = dev_to_node(shost->dma_dev);
	if (shost->hostt->tag_alloc_policy_rr)
		tag_set->flags |= BLK_MQ_F_TAG_RR;
	if (shost->queuecommand_may_block)
		tag_set->flags |= BLK_MQ_F_BLOCKING;
	tag_set->driver_data = shost;
	if (shost->host_tagset)
		tag_set->flags |= BLK_MQ_F_TAG_HCTX_SHARED;

	return blk_mq_alloc_tag_set(tag_set);
}

void scsi_mq_free_tags(struct kref *kref)
{
	struct Scsi_Host *shost = container_of(kref, typeof(*shost),
					       tagset_refcnt);

	blk_mq_free_tag_set(&shost->tag_set);
	complete(&shost->tagset_freed);

Annotation

Implementation Notes