drivers/memstick/core/ms_block.c

Source file repositories/reference/linux-study-clean/drivers/memstick/core/ms_block.c

File Facts

System
Linux kernel
Corpus path
drivers/memstick/core/ms_block.c
Extension
.c
Size
57340 bytes
Lines
2343
Domain
Driver Families
Bucket
drivers/memstick
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 msb_mq_ops = {
	.queue_rq	= msb_queue_rq,
};

/* Registers the block device */
static int msb_init_disk(struct memstick_dev *card)
{
	struct msb_data *msb = memstick_get_drvdata(card);
	struct queue_limits lim = {
		.logical_block_size	= msb->page_size,
		.max_hw_sectors		= MS_BLOCK_MAX_PAGES,
		.max_segments		= MS_BLOCK_MAX_SEGS,
		.max_segment_size	= MS_BLOCK_MAX_PAGES * msb->page_size,
	};
	int rc;
	unsigned long capacity;

	mutex_lock(&msb_disk_lock);
	msb->disk_id = idr_alloc(&msb_disk_idr, card, 0, 256, GFP_KERNEL);
	mutex_unlock(&msb_disk_lock);

	if (msb->disk_id  < 0)
		return msb->disk_id;

	rc = blk_mq_alloc_sq_tag_set(&msb->tag_set, &msb_mq_ops, 2, 0);
	if (rc)
		goto out_release_id;

	msb->disk = blk_mq_alloc_disk(&msb->tag_set, &lim, card);
	if (IS_ERR(msb->disk)) {
		rc = PTR_ERR(msb->disk);
		goto out_free_tag_set;
	}
	msb->queue = msb->disk->queue;

	sprintf(msb->disk->disk_name, "msblk%d", msb->disk_id);
	msb->disk->fops = &msb_bdops;
	msb->disk->private_data = msb;

	capacity = msb->pages_in_block * msb->logical_block_count;
	capacity *= (msb->page_size / 512);
	set_capacity(msb->disk, capacity);
	dbg("Set total disk size to %lu sectors", capacity);

	msb->io_queue = alloc_ordered_workqueue("ms_block", WQ_MEM_RECLAIM);
	if (!msb->io_queue) {
		rc = -ENOMEM;
		goto out_cleanup_disk;
	}

	INIT_WORK(&msb->io_work, msb_io_work);
	sg_init_table(msb->prealloc_sg, MS_BLOCK_MAX_SEGS+1);

	if (msb->read_only)
		set_disk_ro(msb->disk, 1);

	msb_start(card);
	rc = device_add_disk(&card->dev, msb->disk, NULL);
	if (rc)
		goto out_destroy_workqueue;
	dbg("Disk added");
	return 0;

out_destroy_workqueue:
	destroy_workqueue(msb->io_queue);
out_cleanup_disk:
	put_disk(msb->disk);
out_free_tag_set:
	blk_mq_free_tag_set(&msb->tag_set);
out_release_id:
	mutex_lock(&msb_disk_lock);
	idr_remove(&msb_disk_idr, msb->disk_id);
	mutex_unlock(&msb_disk_lock);
	return rc;
}

static int msb_probe(struct memstick_dev *card)
{
	struct msb_data *msb;
	int rc = 0;

	msb = kzalloc_obj(struct msb_data);
	if (!msb)
		return -ENOMEM;
	memstick_set_drvdata(card, msb);
	msb->card = card;
	spin_lock_init(&msb->q_lock);

	rc = msb_init_card(card);
	if (rc)

Annotation

Implementation Notes