> -----Original Message-----
> From: [email protected]
> [mailto:[email protected]] On Behalf Of Andrei Warkentin
> Sent: Tuesday, April 05, 2011 4:31 AM
> To: [email protected]
> 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 <[email protected]>
> ---
>  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 [email protected]
> 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to