Commit 5e09e197 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

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
......@@ -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;
ida_simple_remove(&mmc_blk_ida, devidx);
put_disk(md->disk);
kfree(md);
}
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);
}
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;
......
......@@ -75,7 +75,8 @@ static void mmc_host_classdev_release(struct device *dev)
{
struct mmc_host *host = cls_dev_to_mmc_host(dev);
wakeup_source_unregister(host->ws);
ida_simple_remove(&mmc_host_ida, host->index);
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) {
kfree(host);
return NULL;
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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment