> -----Original Message----- > From: linux-mmc-owner@xxxxxxxxxxxxxxx > [mailto:linux-mmc-owner@xxxxxxxxxxxxxxx] On Behalf Of Andrei Warkentin > Sent: Tuesday, April 05, 2011 4:31 AM > To: linux-mmc@xxxxxxxxxxxxxxx > Cc: Andrei Warkentin > Subject: [RFC] MMC: Request for comments attempt at dealing with removeable > suspend/resume. > > 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? Hi Andrei, I also encountered the same issue with you when system is suspending. And the modification in core.c actually can fix my issue. For the mounted root file system, I think it makes sense for such medias to use MMC_UNSAFE_RESUME. Is there some use case need to remove root file system media? > > Signed-off-by: Andrei Warkentin <andreiw@xxxxxxxxxxxx> > --- > 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 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-mmc" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html