Commit 5e09e197 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull MMC fixes from Ulf Hansson:

 - Use kref to fix KASAN splats triggered during card removal

 - Don't allocate IDA for OF aliases

* tag 'mmc-v5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: core: Don't allocate IDA for OF aliases
  mmc: core: Use kref in place of struct mmc_blk_data::usage
parents 3d5895cd 10252bae
Loading
Loading
Loading
Loading
+21 −14
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/errno.h>
#include <linux/hdreg.h>
#include <linux/kdev_t.h>
#include <linux/kref.h>
#include <linux/blkdev.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
@@ -111,7 +112,7 @@ struct mmc_blk_data {
#define MMC_BLK_CMD23	(1 << 0)	/* Can do SET_BLOCK_COUNT for multiblock */
#define MMC_BLK_REL_WR	(1 << 1)	/* MMC Reliable write support */

	unsigned int	usage;
	struct kref	kref;
	unsigned int	read_only;
	unsigned int	part_type;
	unsigned int	reset_done;
@@ -181,10 +182,8 @@ static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)

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

	return md;
@@ -196,18 +195,25 @@ static inline int mmc_get_devidx(struct gendisk *disk)
	return devidx;
}

static void mmc_blk_put(struct mmc_blk_data *md)
static void mmc_blk_kref_release(struct kref *ref)
{
	mutex_lock(&open_lock);
	md->usage--;
	if (md->usage == 0) {
		int devidx = mmc_get_devidx(md->disk);
	struct mmc_blk_data *md = container_of(ref, struct mmc_blk_data, kref);
	int devidx;

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

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

	put_disk(md->disk);
	kfree(md);
}
	mutex_unlock(&open_lock);

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,
@@ -2327,7 +2333,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,

	INIT_LIST_HEAD(&md->part);
	INIT_LIST_HEAD(&md->rpmbs);
	md->usage = 1;
	kref_init(&md->kref);

	md->queue.blkdata = md;

	md->disk->major	= MMC_BLOCK_MAJOR;
+10 −10
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ static void mmc_host_classdev_release(struct device *dev)
{
	struct mmc_host *host = cls_dev_to_mmc_host(dev);
	wakeup_source_unregister(host->ws);
	if (of_alias_get_id(host->parent->of_node, "mmc") < 0)
		ida_simple_remove(&mmc_host_ida, host->index);
	kfree(host);
}
@@ -502,7 +503,7 @@ static int mmc_first_nonreserved_index(void)
 */
struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
	int err;
	int index;
	struct mmc_host *host;
	int alias_id, min_idx, max_idx;

@@ -515,20 +516,19 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)

	alias_id = of_alias_get_id(dev->of_node, "mmc");
	if (alias_id >= 0) {
		min_idx = alias_id;
		max_idx = alias_id + 1;
		index = alias_id;
	} else {
		min_idx = mmc_first_nonreserved_index();
		max_idx = 0;
	}

	err = ida_simple_get(&mmc_host_ida, min_idx, max_idx, GFP_KERNEL);
	if (err < 0) {
		index = ida_simple_get(&mmc_host_ida, min_idx, max_idx, GFP_KERNEL);
		if (index < 0) {
			kfree(host);
			return NULL;
		}
	}

	host->index = err;
	host->index = index;

	dev_set_name(&host->class_dev, "mmc%d", host->index);
	host->ws = wakeup_source_register(NULL, dev_name(&host->class_dev));