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 @@ ...@@ -28,6 +28,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include <linux/kref.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/mutex.h> #include <linux/mutex.h>
...@@ -111,7 +112,7 @@ struct mmc_blk_data { ...@@ -111,7 +112,7 @@ struct mmc_blk_data {
#define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */ #define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */
#define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */ #define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */
unsigned int usage; struct kref kref;
unsigned int read_only; unsigned int read_only;
unsigned int part_type; unsigned int part_type;
unsigned int reset_done; unsigned int reset_done;
...@@ -181,10 +182,8 @@ static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) ...@@ -181,10 +182,8 @@ static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
mutex_lock(&open_lock); mutex_lock(&open_lock);
md = disk->private_data; md = disk->private_data;
if (md && md->usage == 0) if (md && !kref_get_unless_zero(&md->kref))
md = NULL; md = NULL;
if (md)
md->usage++;
mutex_unlock(&open_lock); mutex_unlock(&open_lock);
return md; return md;
...@@ -196,18 +195,25 @@ static inline int mmc_get_devidx(struct gendisk *disk) ...@@ -196,18 +195,25 @@ static inline int mmc_get_devidx(struct gendisk *disk)
return devidx; 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); struct mmc_blk_data *md = container_of(ref, struct mmc_blk_data, kref);
md->usage--; int devidx;
if (md->usage == 0) {
int devidx = mmc_get_devidx(md->disk);
ida_simple_remove(&mmc_blk_ida, devidx); devidx = mmc_get_devidx(md->disk);
put_disk(md->disk); ida_simple_remove(&mmc_blk_ida, devidx);
kfree(md);
} mutex_lock(&open_lock);
md->disk->private_data = NULL;
mutex_unlock(&open_lock); 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, 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, ...@@ -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->part);
INIT_LIST_HEAD(&md->rpmbs); INIT_LIST_HEAD(&md->rpmbs);
md->usage = 1; kref_init(&md->kref);
md->queue.blkdata = md; md->queue.blkdata = md;
md->disk->major = MMC_BLOCK_MAJOR; md->disk->major = MMC_BLOCK_MAJOR;
......
...@@ -75,7 +75,8 @@ static void mmc_host_classdev_release(struct device *dev) ...@@ -75,7 +75,8 @@ static void mmc_host_classdev_release(struct device *dev)
{ {
struct mmc_host *host = cls_dev_to_mmc_host(dev); struct mmc_host *host = cls_dev_to_mmc_host(dev);
wakeup_source_unregister(host->ws); 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); kfree(host);
} }
...@@ -502,7 +503,7 @@ static int mmc_first_nonreserved_index(void) ...@@ -502,7 +503,7 @@ static int mmc_first_nonreserved_index(void)
*/ */
struct mmc_host *mmc_alloc_host(int extra, struct device *dev) struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{ {
int err; int index;
struct mmc_host *host; struct mmc_host *host;
int alias_id, min_idx, max_idx; int alias_id, min_idx, max_idx;
...@@ -515,20 +516,19 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) ...@@ -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"); alias_id = of_alias_get_id(dev->of_node, "mmc");
if (alias_id >= 0) { if (alias_id >= 0) {
min_idx = alias_id; index = alias_id;
max_idx = alias_id + 1;
} else { } else {
min_idx = mmc_first_nonreserved_index(); min_idx = mmc_first_nonreserved_index();
max_idx = 0; max_idx = 0;
}
err = ida_simple_get(&mmc_host_ida, min_idx, max_idx, GFP_KERNEL); index = ida_simple_get(&mmc_host_ida, min_idx, max_idx, GFP_KERNEL);
if (err < 0) { if (index < 0) {
kfree(host); kfree(host);
return NULL; return NULL;
}
} }
host->index = err; host->index = index;
dev_set_name(&host->class_dev, "mmc%d", host->index); dev_set_name(&host->class_dev, "mmc%d", host->index);
host->ws = wakeup_source_register(NULL, dev_name(&host->class_dev)); 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