drivers/mmc/core/block.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mmc/core/block.c
Extension
.c
Size
86446 bytes
Lines
3389
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 bus_type mmc_rpmb_bus_type = {
	.name = "mmc_rpmb",
};

/**
 * struct mmc_rpmb_data - special RPMB device type for these areas
 * @dev: the device for the RPMB area
 * @chrdev: character device for the RPMB area
 * @id: unique device ID number
 * @part_index: partition index (0 on first)
 * @md: parent MMC block device
 * @rdev: registered RPMB device
 * @node: list item, so we can put this device on a list
 */
struct mmc_rpmb_data {
	struct device dev;
	struct cdev chrdev;
	int id;
	unsigned int part_index;
	struct mmc_blk_data *md;
	struct rpmb_dev *rdev;
	struct list_head node;
};

static DEFINE_MUTEX(open_lock);

module_param(perdev_minors, int, 0444);
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");

static inline int mmc_blk_part_switch(struct mmc_card *card,
				      unsigned int part_type);
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
			       struct mmc_card *card,
			       int recovery_mode,
			       struct mmc_queue *mq);
static void mmc_blk_hsq_req_done(struct mmc_request *mrq);
static int mmc_spi_err_check(struct mmc_card *card);
static int mmc_blk_busy_cb(void *cb_data, bool *busy);

static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
	struct mmc_blk_data *md;

	mutex_lock(&open_lock);
	md = disk->private_data;
	if (md && !kref_get_unless_zero(&md->kref))
		md = NULL;
	mutex_unlock(&open_lock);

	return md;
}

static inline int mmc_get_devidx(struct gendisk *disk)
{
	int devidx = disk->first_minor / perdev_minors;
	return devidx;
}

static void mmc_blk_kref_release(struct kref *ref)
{
	struct mmc_blk_data *md = container_of(ref, struct mmc_blk_data, kref);
	int devidx;

	devidx = mmc_get_devidx(md->disk);
	ida_free(&mmc_blk_ida, devidx);

	mutex_lock(&open_lock);
	md->disk->private_data = NULL;
	mutex_unlock(&open_lock);

	put_disk(md->disk);
	kfree(md);
}

static void mmc_blk_put(struct mmc_blk_data *md)
{
	kref_put(&md->kref, mmc_blk_kref_release);
}

static ssize_t power_ro_lock_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	int ret;
	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
	struct mmc_card *card = md->queue.card;
	int locked = 0;

	if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
		locked = 2;
	else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN)

Annotation

Implementation Notes