Hi Chris,

Do you have any concerns about this patch? Or another advice?
Thanks.


-----Original Message-----
From: Liu Qiang-B32616
Sent: Wednesday, December 21, 2011 3:10 PM
To: c...@laptop.org; linux-mmc@vger.kernel.org
Cc: Li Yang-R58472; Liu Qiang-B32616; Liu Qiang-B32616
Subject: [PATCH V2 1/2] SD/MMC: add an interface to re-initialize bounce buffer

Add bounce_size under /sys/block/mmcblk0/bouncesz.
Support dynamic adjustment of bounce buffer in run-time (include mounted or 
unmounted filesystem).

/sys/block/mmcblk0/bouncesz should be integer multiple of 512, the value should 
be range from 4096 to 4194304.

1. use variable instead of MMC_QUEUE_BOUNCESZ; 2. Re-initialize bounce buffer 
accorinding to new bounce size at run-time;

Signed-off-by: Qiang Liu <qiang....@freescale.com>
---
changes for V2
        merge former 2 patches to 1

Here is the test results with different mmc bounce size, IOzone is used to test 
performance of mass data transmission.
Environment:
PowerPC P1022DS platform, Sandisk Class 10, 4G memory card, EXT4 filesystem
[root@p2020ds root]# cat /sys/fs/   block/mmcblk0/bouncesz
65536
[root@p2020ds root]# mount /dev/mmcblk0p1 /mnt/ EXT4-fs (mmcblk0p1): mounted 
filesystem without journal. Opts:
[root@p2020ds root]# iozone -Rab result -i0 -i1 -r64 =-  -n1g -g4g -f /mnt/ff 
........
              KB  reclen   write rewrite    read    reread
         1048576      64   14229   13286   662028   663372
         2097152      64   13758   12605    49549    47443
         4194304      64   13435   12215    21974    22096
........
[root@p2020ds root]# echo 262144 > /sys/block/mmcblk0/bouncesz [root@p2020ds 
root]# cat /sys/block/mmcblk0/bouncesz
262144
[root@p2020ds root]# iozone -Rab result -i0 -i1 -r64 -n1g -g4g -f /mnt/ff 
........
              KB  reclen   write rewrite    read    reread
         1048576      64   19228   19416   676659   677785
         2097152      64   18512   18499    26978    27055
         4194304      64   17932   18185    21945    21805
........
[root@p2020ds root]# echo 8192 > /sys/block/mmcblk0/bouncesz [root@p2020ds 
root]# cat /sys/block/mmcblk0/bouncesz
8192
[root@p2020ds root]# iozone -Rab result -i0 -i1 -r64 -n1g -g1g -f /mnt/ff
              KB  reclen   write rewrite    read    reread
         1048576      64    5068    3324   640266   641609
-------------------------------------------------------------------------------
 drivers/mmc/card/block.c |   43 +++++++++++++++++++
 drivers/mmc/card/queue.c |  102 +++++++++++++++++++++++++++++++++++++++++++++-
 drivers/mmc/card/queue.h |    6 +++
 3 files changed, 149 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 
0c959c9..790abe2 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -59,6 +59,9 @@ MODULE_ALIAS("mmc:block");  #define INAND_CMD38_ARG_SECTRIM1 
0x81  #define INAND_CMD38_ARG_SECTRIM2 0x88

+#define MMC_MIN_QUEUE_BOUNCESZ 4096
+#define MMC_MAX_QUEUE_BOUNCESZ 4194304
+
 static DEFINE_MUTEX(block_mutex);

 /*
@@ -108,6 +111,7 @@ struct mmc_blk_data {
        unsigned int    part_curr;
        struct device_attribute force_ro;
        struct device_attribute power_ro_lock;
+       struct device_attribute bouncesz;
        int     area_type;
 };

@@ -1633,6 +1637,7 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
                        del_gendisk(md->disk);
                }

+               device_remove_file(disk_to_dev(md->disk), &md->bouncesz);
                /* Then flush out any already in there */
                mmc_cleanup_queue(&md->queue);
                mmc_blk_put(md);
@@ -1739,6 +1744,33 @@ static const struct mmc_fixup blk_fixups[] =
        END_FIXUP
 };

+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+static ssize_t mmc_bouncesz_show(struct device *dev,
+               struct device_attribute *attr, char *buf) {
+        return sprintf(buf, "%u\n", mmc_queue_bouncesz); }
+
+static ssize_t mmc_bouncesz_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       unsigned int bouncesz;
+       struct mmc_blk_data *md;
+
+       if ((sscanf(buf, "%d", &bouncesz) != 1) ||
+                       (bouncesz < MMC_MIN_QUEUE_BOUNCESZ) ||
+                       (bouncesz > MMC_MAX_QUEUE_BOUNCESZ) ||
+                       (bouncesz % 512 != 0))
+               return -EINVAL;
+
+       md = mmc_blk_get(dev_to_disk(dev));
+       mmc_reinit_bounce_queue(&md->queue, md->queue.card, bouncesz);
+       mmc_blk_put(md);
+       return mmc_queue_bouncesz;
+}
+#endif
+
 static int mmc_blk_probe(struct mmc_card *card)  {
        struct mmc_blk_data *md, *part_md;
@@ -1771,6 +1803,17 @@ static int mmc_blk_probe(struct mmc_card *card)
        mmc_set_drvdata(card, md);
        mmc_fixup_device(card, blk_fixups);

+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+       md->bouncesz.show = mmc_bouncesz_show;
+       md->bouncesz.store = mmc_bouncesz_store;
+       sysfs_attr_init(&md->bouncesz.attr);
+       md->bouncesz.attr.name = "bouncesz";
+       md->bouncesz.attr.mode = S_IRUGO | S_IWUSR;
+       err = device_create_file(disk_to_dev(md->disk), &md->bouncesz);
+       if (err)
+               goto out;
+#endif
+
        if (mmc_add_disk(md))
                goto out;

diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 
dcad59c..c563e33 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -21,7 +21,9 @@
 #include "queue.h"

 #define MMC_QUEUE_BOUNCESZ     65536
-
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+unsigned mmc_queue_bouncesz = MMC_QUEUE_BOUNCESZ; #endif
 #define MMC_QUEUE_SUSPENDED    (1 << 0)

 /*
@@ -185,7 +187,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card 
*card,
        if (host->max_segs == 1) {
                unsigned int bouncesz;

-               bouncesz = MMC_QUEUE_BOUNCESZ;
+               bouncesz = mmc_queue_bouncesz;

                if (bouncesz > host->max_req_size)
                        bouncesz = host->max_req_size;
@@ -329,6 +331,102 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
 EXPORT_SYMBOL(mmc_cleanup_queue);

 /**
+ * mmc_reinit_bounce_queue - re-initialise a bounce buffer.
+ * @mq: mmc queue
+ * @card: mmc card to attach this queue
+ * @bouncesz: the bounce size that need re-initializing
+ *
+ * Initialise a MMC card request queue.
+ */
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+int mmc_reinit_bounce_queue(struct mmc_queue *mq, struct mmc_card *card,
+                  unsigned int bouncesz)
+{
+       struct mmc_host *host = card->host;
+       struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
+       struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
+       int ret;
+       struct scatterlist *curr_bounce_sg, *prev_bounce_sg;
+       char *curr_bounce_buf, *prev_bounce_buf;
+
+       mmc_claim_host(card->host);
+
+       bouncesz = min(bouncesz, host->max_req_size);
+       bouncesz = min(bouncesz, host->max_seg_size);
+       bouncesz = min(bouncesz, host->max_blk_count * 512);
+
+       /* store current using addr of bounce_buf and bounce_sg */
+       curr_bounce_sg = mqrq_cur->bounce_sg;
+       prev_bounce_sg = mqrq_prev->bounce_sg;
+       curr_bounce_buf = mqrq_cur->bounce_buf;
+       prev_bounce_buf = mqrq_prev->bounce_buf;
+
+       if (host->max_segs != 1)
+               goto restore_queue;
+
+       /* realloc bounce queue use given bounce size */
+       mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+       if (!mqrq_cur->bounce_buf) {
+               printk(KERN_WARNING "%s: unable to "
+                       "allocate bounce cur buffer\n",
+                       mmc_card_name(card));
+               ret = -ENOMEM;
+               goto restore_queue;
+       }
+
+       mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+       if (!mqrq_prev->bounce_buf) {
+               printk(KERN_WARNING "%s: unable to "
+                       "allocate bounce prev buffer\n",
+                       mmc_card_name(card));
+               kfree(mqrq_cur->bounce_buf);
+               mqrq_cur->bounce_buf = NULL;
+               ret = -ENOMEM;
+               goto restore_queue;
+       }
+
+       mqrq_cur->bounce_sg =
+               mmc_alloc_sg(bouncesz / 512, &ret);
+       if (ret)
+               goto cleanup_queue;
+
+       mqrq_prev->bounce_sg =
+               mmc_alloc_sg(bouncesz / 512, &ret);
+       if (ret)
+               goto cleanup_queue;
+
+       blk_queue_max_hw_sectors(mq->queue, bouncesz / 512);
+       blk_queue_max_segments(mq->queue, bouncesz / 512);
+       blk_queue_max_segment_size(mq->queue, bouncesz);
+       mmc_queue_bouncesz = bouncesz;
+
+       kfree(curr_bounce_sg);
+       kfree(prev_bounce_sg);
+       kfree(curr_bounce_buf);
+       kfree(prev_bounce_buf);
+
+       mmc_release_host(card->host);
+       return 0;
+
+cleanup_queue:
+       /* cleanup bounce queue first */
+       kfree(mqrq_cur->sg);
+       kfree(mqrq_cur->bounce_buf);
+       kfree(mqrq_prev->sg);
+       kfree(mqrq_prev->bounce_buf);
+
+restore_queue:
+       mqrq_cur->bounce_buf = curr_bounce_buf;
+       mqrq_prev->bounce_buf = prev_bounce_buf;
+       mqrq_cur->bounce_sg = curr_bounce_sg;
+       mqrq_prev->bounce_sg = prev_bounce_sg;
+
+       mmc_release_host(card->host);
+       return ret;
+}
+#endif
+
+/**
  * mmc_queue_suspend - suspend a MMC request queue
  * @mq: MMC queue to suspend
  *
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index d2a1eb4..c1dee6d 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -46,4 +46,10 @@ extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
 extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
 extern void mmc_queue_bounce_post(struct mmc_queue_req *);

+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+extern int mmc_reinit_bounce_queue(struct mmc_queue *, struct mmc_card *,
+               unsigned int);
+extern unsigned mmc_queue_bouncesz;
+#endif
+
 #endif
--
1.6.4


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to