drivers/memstick/core/mspro_block.c

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

File Facts

System
Linux kernel
Corpus path
drivers/memstick/core/mspro_block.c
Extension
.c
Size
38010 bytes
Lines
1399
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 mspro_mq_ops = {
	.queue_rq	= mspro_queue_rq,
};

static int mspro_block_init_disk(struct memstick_dev *card)
{
	struct mspro_block_data *msb = memstick_get_drvdata(card);
	struct queue_limits lim = {
		.logical_block_size	= msb->page_size,
		.max_hw_sectors		= MSPRO_BLOCK_MAX_PAGES,
		.max_segments		= MSPRO_BLOCK_MAX_SEGS,
		.max_segment_size	= MSPRO_BLOCK_MAX_PAGES * msb->page_size,
	};
	struct mspro_devinfo *dev_info = NULL;
	struct mspro_sys_info *sys_info = NULL;
	struct mspro_sys_attr *s_attr = NULL;
	int rc, disk_id;
	unsigned long capacity;

	for (rc = 0; msb->attr_group.attrs[rc]; ++rc) {
		s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]);

		if (s_attr->id == MSPRO_BLOCK_ID_DEVINFO)
			dev_info = s_attr->data;
		else if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO)
			sys_info = s_attr->data;
	}

	if (!dev_info || !sys_info)
		return -ENODEV;

	msb->cylinders = be16_to_cpu(dev_info->cylinders);
	msb->heads = be16_to_cpu(dev_info->heads);
	msb->sectors_per_track = be16_to_cpu(dev_info->sectors_per_track);

	msb->page_size = be16_to_cpu(sys_info->unit_size);

	mutex_lock(&mspro_block_disk_lock);
	disk_id = idr_alloc(&mspro_block_disk_idr, card, 0, 256, GFP_KERNEL);
	mutex_unlock(&mspro_block_disk_lock);
	if (disk_id < 0)
		return disk_id;

	rc = blk_mq_alloc_sq_tag_set(&msb->tag_set, &mspro_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;

	msb->disk->major = major;
	msb->disk->first_minor = disk_id << MSPRO_BLOCK_PART_SHIFT;
	msb->disk->minors = 1 << MSPRO_BLOCK_PART_SHIFT;
	msb->disk->fops = &ms_block_bdops;
	msb->disk->private_data = msb;

	sprintf(msb->disk->disk_name, "mspblk%d", disk_id);

	capacity = be16_to_cpu(sys_info->user_block_count);
	capacity *= be16_to_cpu(sys_info->block_size);
	capacity *= msb->page_size >> 9;
	set_capacity(msb->disk, capacity);
	dev_dbg(&card->dev, "capacity set %ld\n", capacity);

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

	rc = device_add_disk(&card->dev, msb->disk, NULL);
	if (rc)
		goto out_cleanup_disk;
	msb->active = 1;
	return 0;

out_cleanup_disk:
	put_disk(msb->disk);
out_free_tag_set:
	blk_mq_free_tag_set(&msb->tag_set);
out_release_id:
	mutex_lock(&mspro_block_disk_lock);
	idr_remove(&mspro_block_disk_idr, disk_id);
	mutex_unlock(&mspro_block_disk_lock);
	return rc;
}

static void mspro_block_data_clear(struct mspro_block_data *msb)
{

Annotation

Implementation Notes