drivers/mmc/core/queue.c

Source file repositories/reference/linux-study-clean/drivers/mmc/core/queue.c

File Facts

System
Linux kernel
Corpus path
drivers/mmc/core/queue.c
Extension
.c
Size
13480 bytes
Lines
539
Domain
Driver Families
Bucket
drivers/mmc
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 mmc_mq_ops = {
	.queue_rq	= mmc_mq_queue_rq,
	.init_request	= mmc_mq_init_request,
	.exit_request	= mmc_mq_exit_request,
	.complete	= mmc_blk_mq_complete,
	.timeout	= mmc_mq_timed_out,
};

static struct gendisk *mmc_alloc_disk(struct mmc_queue *mq,
		struct mmc_card *card, unsigned int features)
{
	struct mmc_host *host = card->host;
	struct queue_limits lim = {
		.features		= features,
	};
	struct gendisk *disk;

	if (mmc_card_can_erase(card))
		mmc_queue_setup_discard(card, &lim);

	lim.max_hw_sectors = min(host->max_blk_count, host->max_req_size / 512);

	if (mmc_card_mmc(card) && card->ext_csd.data_sector_size)
		lim.logical_block_size = card->ext_csd.data_sector_size;
	else
		lim.logical_block_size = 512;

	WARN_ON_ONCE(lim.logical_block_size != 512 &&
		     lim.logical_block_size != 4096);

	/*
	 * Setting a virt_boundary implicity sets a max_segment_size, so try
	 * to set the hardware one here.
	 */
	if (host->can_dma_map_merge) {
		lim.virt_boundary_mask = dma_get_merge_boundary(mmc_dev(host));
		lim.max_segments = MMC_DMA_MAP_MERGE_SEGMENTS;
	} else {
		lim.max_segment_size =
			round_down(host->max_seg_size, lim.logical_block_size);
		lim.max_segments = host->max_segs;
	}

	if (mmc_host_is_spi(host) && host->use_spi_crc)
		lim.features |= BLK_FEAT_STABLE_WRITES;

	disk = blk_mq_alloc_disk(&mq->tag_set, &lim, mq);
	if (IS_ERR(disk))
		return disk;
	mq->queue = disk->queue;

	blk_queue_rq_timeout(mq->queue, 60 * HZ);

	if (mmc_dev(host)->dma_parms)
		dma_set_max_seg_size(mmc_dev(host), queue_max_segment_size(mq->queue));

	INIT_WORK(&mq->recovery_work, mmc_mq_recovery_handler);
	INIT_WORK(&mq->complete_work, mmc_blk_mq_complete_work);

	mutex_init(&mq->complete_lock);

	init_waitqueue_head(&mq->wait);

	mmc_crypto_setup_queue(mq->queue, host);
	return disk;
}

static inline bool mmc_merge_capable(struct mmc_host *host)
{
	return host->caps2 & MMC_CAP2_MERGE_CAPABLE;
}

/* Set queue depth to get a reasonable value for q->nr_requests */
#define MMC_QUEUE_DEPTH 64

/**
 * mmc_init_queue - initialise a queue structure.
 * @mq: mmc queue
 * @card: mmc card to attach this queue
 * @features: block layer features (BLK_FEAT_*)
 *
 * Initialise a MMC card request queue.
 */
struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
		unsigned int features)
{
	struct mmc_host *host = card->host;
	struct gendisk *disk;
	int ret;

Annotation

Implementation Notes