From: Andrei Warkentin <andreiw@motorola.com>
To: linux-mmc@vger.kernel.org
Cc: Andrei Warkentin <andreiw@motorola.com>
Subject: [RFC] MMC: Request for comments attempt at dealing with removeable suspend/resume.
Date: Mon, 4 Apr 2011 15:31:09 -0500 [thread overview]
Message-ID: <1301949069-13283-1-git-send-email-andreiw@motorola.com> (raw)
In-Reply-To: <BANLkTikMmf-d1BVG6ZMUV-L-nB05ytQVYw@mail.gmail.com>
Is there any value to doing something like this in order to be able to suspend/resume
with a (manually, or rootfs) mounted filesystem on mmcblk?
Thoughts?
Signed-off-by: Andrei Warkentin <andreiw@motorola.com>
---
drivers/mmc/card/block.c | 76 +++++++++++++++++++++++++++++++++++++++++----
drivers/mmc/core/core.c | 3 +-
2 files changed, 70 insertions(+), 9 deletions(-)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index ee8f7a9..19eb5b6 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -53,6 +53,9 @@ MODULE_ALIAS("mmc:block");
((card)->ext_csd.rel_sectors)))
static DEFINE_MUTEX(block_mutex);
+static DEFINE_MUTEX(orphan_mutex);
+
+struct list_head orphans = LIST_HEAD_INIT(orphans);
/*
* The defaults come from config options but can be overriden by module
@@ -77,6 +80,7 @@ struct mmc_blk_data {
struct gendisk *disk;
struct mmc_queue queue;
struct list_head part;
+ struct list_head orphan;
unsigned int usage;
unsigned int read_only;
@@ -88,6 +92,7 @@ struct mmc_blk_data {
* track of the current selected device partition.
*/
unsigned int part_curr;
+ u32 raw_cid[4];
struct device_attribute force_ro;
};
@@ -126,10 +131,12 @@ static void mmc_blk_put(struct mmc_blk_data *md)
mutex_lock(&open_lock);
md->usage--;
if (md->usage == 0) {
- int devidx = mmc_get_devidx(md->disk);
- blk_cleanup_queue(md->queue.queue);
+ mutex_lock(&orphan_mutex);
+ list_del(&md->orphan);
+ mutex_unlock(&orphan_mutex);
- __clear_bit(devidx, dev_use);
+ blk_cleanup_queue(md->queue.queue);
+ __clear_bit(mmc_get_devidx(md->disk), dev_use);
put_disk(md->disk);
kfree(md);
@@ -718,6 +725,49 @@ static inline int mmc_blk_readonly(struct mmc_card *card)
!(card->csd.cmdclass & CCC_BLOCK_WRITE);
}
+static inline struct mmc_blk_data *mmc_lookup_orphan(struct mmc_card *card,
+ struct device *parent,
+ unsigned int part_type,
+ sector_t size)
+{
+ int ret;
+ struct list_head *pos, *q;
+ struct mmc_blk_data *md;
+ bool found = false;
+
+ mutex_lock(&orphan_mutex);
+ list_for_each_safe(pos, q, &orphans) {
+ md = list_entry(pos, struct mmc_blk_data, orphan);
+ if (!memcmp(md->raw_cid, card->raw_cid, sizeof(md->raw_cid)) &&
+ md->part_type == part_type) {
+ list_del(pos);
+ found = true;
+ mmc_blk_get(md->disk);
+ break;
+ }
+ }
+ mutex_unlock(&orphan_mutex);
+
+ if (!found)
+ return NULL;
+
+ ret = mmc_init_queue(&md->queue, card, &md->lock);
+ if (ret)
+ return NULL;
+
+ INIT_LIST_HEAD(&md->part);
+ md->disk->driverfs_dev = parent;
+ md->queue.issue_fn = mmc_blk_issue_rq;
+ md->queue.data = md;
+ md->disk->queue = md->queue.queue;
+ if (REL_WRITES_SUPPORTED(card))
+ blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA);
+ blk_queue_logical_block_size(md->queue.queue, 512);
+ set_capacity(md->disk, size);
+ printk("set cap to %x\n", (unsigned int) get_capacity(md->disk));
+ return md;
+}
+
static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
struct device *parent,
sector_t size,
@@ -752,7 +802,9 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
spin_lock_init(&md->lock);
INIT_LIST_HEAD(&md->part);
+ INIT_LIST_HEAD(&md->orphan);
md->usage = 1;
+ memcpy(md->raw_cid, card->raw_cid, sizeof(card->raw_cid));
ret = mmc_init_queue(&md->queue, card, &md->lock);
if (ret)
@@ -822,7 +874,9 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
size = card->csd.capacity << (card->csd.read_blkbits - 9);
}
- md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL);
+ md = mmc_lookup_orphan(card, &card->dev, 0, size);
+ if (!md)
+ md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL);
return md;
}
@@ -836,8 +890,10 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
char cap_str[10];
struct mmc_blk_data *part_md;
- part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
- subname);
+ part_md = mmc_lookup_orphan(card, disk_to_dev(md->disk), part_type, size);
+ if (!part_md)
+ part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size,
+ default_ro, subname);
if (IS_ERR(part_md))
return PTR_ERR(part_md);
part_md->part_type = part_type;
@@ -906,6 +962,10 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
/* Then flush out any already in there */
mmc_cleanup_queue(&md->queue);
+
+ mutex_lock(&orphan_mutex);
+ list_add(&md->orphan, &orphans);
+ mutex_unlock(&orphan_mutex);
mmc_blk_put(md);
}
}
@@ -933,8 +993,10 @@ static int mmc_add_disk(struct mmc_blk_data *md)
md->force_ro.attr.name = "force_ro";
md->force_ro.attr.mode = S_IRUGO | S_IWUSR;
ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
- if (ret)
+ if (ret) {
del_gendisk(md->disk);
+ return ret;
+ }
return ret;
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 85ef72c..87c4af7 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1823,11 +1823,10 @@ int mmc_pm_notify(struct notifier_block *notify_block,
if (!host->bus_ops || host->bus_ops->suspend)
break;
- mmc_claim_host(host);
-
if (host->bus_ops->remove)
host->bus_ops->remove(host);
+ mmc_claim_host(host);
mmc_detach_bus(host);
mmc_release_host(host);
host->pm_flags = 0;
--
1.7.0.4
next prev parent reply other threads:[~2011-04-04 19:51 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-30 10:52 deadlock between mmc_pm_notify() and mmcqd Frank Hofmann
2011-04-04 12:54 ` Andrei Warkentin
2011-04-04 13:11 ` Frank Hofmann
2011-04-04 14:00 ` [PATCH] MMC: fix mmc_pm_notify bus_ops->remove deadlock Andrei Warkentin
2011-04-04 13:27 ` Andrei Warkentin
2011-04-04 15:01 ` Ohad Ben-Cohen
2011-04-04 15:10 ` Andrei Warkentin
2011-04-04 15:01 ` Andrei Warkentin
[not found] ` <alpine.DEB.2.00.1104041624310.690@localhost6.localdomain6>
2011-04-04 15:47 ` Andrei Warkentin
2011-04-04 16:08 ` Andrei Warkentin
2011-04-04 20:31 ` Andrei Warkentin [this message]
2011-05-17 10:15 ` [RFC] MMC: Request for comments attempt at dealing with removeable suspend/resume Dong, Chuanxiao
2011-05-18 8:06 ` Andrei Warkentin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1301949069-13283-1-git-send-email-andreiw@motorola.com \
--to=andreiw@motorola.com \
--cc=linux-mmc@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).