[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <877713.29364.qm@web57908.mail.re3.yahoo.com>
Date: Wed, 8 Sep 2010 07:44:44 -0700 (PDT)
From: hong zhang <henryzhang62@...oo.com>
To: linux-mmc@...r.kernel.org, linux-kernel@...r.kernel.org,
Andy Shevchenko <andy.shevchenko@...il.com>
Cc: Hunter Adrian <adrian.hunter@...ia.com>,
Chris Ball <cjb@...top.org>,
Andrew Morton <akpm@...ux-foundation.org>,
Andy Shevchenko <ext-andriy.shevchenko@...ia.com>
Subject: Re: [PATCHv6 3/3] mmc_test: collect data and show it via sysfs by demand
Andy,
Would you please give any command to check card type?
---henry
--- On Tue, 9/7/10, Andy Shevchenko <andy.shevchenko@...il.com> wrote:
> From: Andy Shevchenko <andy.shevchenko@...il.com>
> Subject: [PATCHv6 3/3] mmc_test: collect data and show it via sysfs by demand
> To: linux-mmc@...r.kernel.org, linux-kernel@...r.kernel.org
> Cc: "Hunter Adrian" <adrian.hunter@...ia.com>, "Chris Ball" <cjb@...top.org>, "Andrew Morton" <akpm@...ux-foundation.org>, "Andy Shevchenko" <ext-andriy.shevchenko@...ia.com>
> Date: Tuesday, September 7, 2010, 7:35 AM
> TODO:
> - implement show() method based on seq_file API
>
> Changes since v5:
> - we can't use BUG_ON at exit() method because it quite
> normal case when the
> module is going to be removed with card
> plugged in, that's why we just free
> memory there
> - rebase against recent linux-next tree
>
> Changes since v4:
> - BUG_ON at exit if the list of the results isn't empty
>
> Changes since v3:
> - fix multi-line commentary style
> - protect mmc_test_free_result() by mutex
> - apply known values to newly created
> mmc_test_general_result structure before
> attaching it to the list
> - call list_del() before free mmc_test_transfer_result
> structure
> - check truncated output in show() method, return -ENOBUFS
> if so
> - avoid deadlock in show() method if snprintf() fails
>
> Changes since v2:
> - move card memeber to mmc_test_general_result structrure
> and thus throw away
> mmc_test_overall_result which was
> overkill
> - check result of kmalloc and kzalloc
> - keep pointer to the actual mmc_test_general_result
> structure in the
> mmc_test_card
>
> Changes since v1:
> - structrure members are described
> - save transfer results code is split to separate
> function
> - in mmc_test_print_rate() use count = 1 instead of 0
> - mmc_test_result keeps overall results (across all tested
> cards), however
> it's still global variable
> - list_head variables inside structures have a suffix _lst
> now
>
> Here is a patch which brings possibility to get test
> results via sysfs. It
> helps to do tests non-interactively.
>
> We have the file created under sysfs already and we could
> use it to out test
> results.
>
> This patch applied on top of patches published here [1]
>
> [1] http://lkml.org/lkml/2010/8/18/164
>
> Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@...ia.com>
> ---
> drivers/mmc/card/mmc_test.c | 171
> ++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 169 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/card/mmc_test.c
> b/drivers/mmc/card/mmc_test.c
> index 6bffb33..58d746b 100644
> --- a/drivers/mmc/card/mmc_test.c
> +++ b/drivers/mmc/card/mmc_test.c
> @@ -17,6 +17,7 @@
>
> #include <linux/scatterlist.h>
> #include <linux/swap.h>
> /* For nr_free_buffer_pages() */
> +#include <linux/list.h>
>
> #define RESULT_OK 0
> #define RESULT_FAIL
> 1
> @@ -73,12 +74,45 @@ struct mmc_test_area {
> };
>
> /**
> + * struct mmc_test_transfer_result - transfer results for
> performance tests.
> + * @link: double-linked list
> + * @count: amount of group of sectors to check
> + * @sectors: amount of sectors to check in one group
> + * @ts: time values of transfer
> + * @rate: calculated transfer rate
> + */
> +struct mmc_test_transfer_result {
> + struct list_head link;
> + unsigned int count;
> + unsigned int sectors;
> + struct timespec ts;
> + unsigned int rate;
> +};
> +
> +/**
> + * struct mmc_test_general_result - results for tests.
> + * @link: double-linked list
> + * @card: card under test
> + * @testcase: number of test case
> + * @result: result of test run
> + * @tr_lst: transfer measurements if any as
> mmc_test_transfer_result
> + */
> +struct mmc_test_general_result {
> + struct list_head link;
> + struct mmc_card *card;
> + int testcase;
> + int result;
> + struct list_head tr_lst;
> +};
> +
> +/**
> * struct mmc_test_card - test information.
> * @card: card under test
> * @scratch: transfer buffer
> * @buffer: transfer buffer
> * @highmem: buffer for highmem tests
> * @area: information for performance tests
> + * @gr: pointer to results of current testcase
> */
> struct mmc_test_card {
> struct mmc_card
> *card;
> @@ -88,7 +122,8 @@ struct mmc_test_card {
> #ifdef CONFIG_HIGHMEM
> struct page
> *highmem;
> #endif
> - struct mmc_test_area area;
> + struct mmc_test_area
> area;
> + struct
> mmc_test_general_result *gr;
> };
>
>
> /*******************************************************************/
> @@ -421,6 +456,30 @@ static unsigned int
> mmc_test_rate(uint64_t bytes, struct timespec *ts)
> }
>
> /*
> + * Save transfer results for future usage
> + */
> +static void mmc_test_save_transfer_result(struct
> mmc_test_card *test,
> + unsigned int count, unsigned int
> sectors, struct timespec ts,
> + unsigned int rate)
> +{
> + struct mmc_test_transfer_result *tr;
> +
> + if (!test->gr)
> + return;
> +
> + tr = kmalloc(sizeof(struct
> mmc_test_transfer_result), GFP_KERNEL);
> + if (!tr)
> + return;
> +
> + tr->count = count;
> + tr->sectors = sectors;
> + tr->ts = ts;
> + tr->rate = rate;
> +
> + list_add_tail(&tr->link,
> &test->gr->tr_lst);
> +}
> +
> +/*
> * Print the transfer rate.
> */
> static void mmc_test_print_rate(struct mmc_test_card
> *test, uint64_t bytes,
> @@ -438,6 +497,8 @@ static void mmc_test_print_rate(struct
> mmc_test_card *test, uint64_t bytes,
>
> mmc_hostname(test->card->host),
> sectors, sectors >> 1,
>
> (sectors == 1 ? ".5" : ""),
> (unsigned long)ts.tv_sec,
>
> (unsigned long)ts.tv_nsec,
> rate / 1000, rate / 1024);
> +
> + mmc_test_save_transfer_result(test, 1,
> sectors, ts, rate);
> }
>
> /*
> @@ -461,6 +522,8 @@ static void
> mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t
> bytes,
>
> sectors >> 1, (sectors
> == 1 ? ".5" : ""),
>
> (unsigned long)ts.tv_sec,
> (unsigned long)ts.tv_nsec,
>
> rate / 1000, rate / 1024);
> +
> + mmc_test_save_transfer_result(test,
> count, sectors, ts, rate);
> }
>
> /*
> @@ -1853,6 +1916,8 @@ static const struct mmc_test_case
> mmc_test_cases[] = {
>
> static DEFINE_MUTEX(mmc_test_lock);
>
> +static LIST_HEAD(mmc_test_result);
> +
> static void mmc_test_run(struct mmc_test_card *test, int
> testcase)
> {
> int i, ret;
> @@ -1863,6 +1928,8 @@ static void mmc_test_run(struct
> mmc_test_card *test, int testcase)
>
> mmc_claim_host(test->card->host);
>
> for (i = 0;i <
> ARRAY_SIZE(mmc_test_cases);i++) {
> + struct
> mmc_test_general_result *gr;
> +
> if (testcase
> && ((i + 1) != testcase))
>
> continue;
>
> @@ -1881,6 +1948,25 @@ static void mmc_test_run(struct
> mmc_test_card *test, int testcase)
>
> }
> }
>
> + gr =
> kzalloc(sizeof(struct mmc_test_general_result),
> +
> GFP_KERNEL);
> + if (gr) {
> +
> INIT_LIST_HEAD(&gr->tr_lst);
> +
> +
> /* Assign data what we know already */
> +
> gr->card = test->card;
> +
> gr->testcase = i;
> +
> +
> /* Append container to global one */
> +
> list_add_tail(&gr->link, &mmc_test_result);
> +
> +
> /*
> +
> * Save the pointer to created
> container in our private
> +
> * structure.
> +
> */
> +
> test->gr = gr;
> + }
> +
> ret =
> mmc_test_cases[i].run(test);
> switch (ret) {
> case RESULT_OK:
> @@ -1906,6 +1992,10 @@ static void mmc_test_run(struct
> mmc_test_card *test, int testcase)
>
> mmc_hostname(test->card->host),
> ret);
> }
>
> + /* Save the result
> */
> + if (gr)
> +
> gr->result = ret;
> +
> if
> (mmc_test_cases[i].cleanup) {
>
> ret = mmc_test_cases[i].cleanup(test);
>
> if (ret) {
> @@ -1923,13 +2013,80 @@ static void mmc_test_run(struct
> mmc_test_card *test, int testcase)
>
> mmc_hostname(test->card->host));
> }
>
> +static void mmc_test_free_result(struct mmc_card *card)
> +{
> + struct mmc_test_general_result *gr,
> *grs;
> +
> + mutex_lock(&mmc_test_lock);
> +
> + list_for_each_entry_safe(gr, grs,
> &mmc_test_result, link) {
> + struct
> mmc_test_transfer_result *tr, *trs;
> +
> + if (card &&
> gr->card != card)
> +
> continue;
> +
> +
> list_for_each_entry_safe(tr, trs, &gr->tr_lst, link)
> {
> +
> list_del(&tr->link);
> +
> kfree(tr);
> + }
> +
> +
> list_del(&gr->link);
> + kfree(gr);
> + }
> +
> + mutex_unlock(&mmc_test_lock);
> +}
> +
> static ssize_t mmc_test_show(struct device *dev,
> struct device_attribute *attr, char
> *buf)
> {
> + struct mmc_card *card =
> mmc_dev_to_card(dev);
> + struct mmc_test_general_result *gr;
> + char *p = buf;
> + size_t len = PAGE_SIZE;
> + int ret;
> +
> mutex_lock(&mmc_test_lock);
> +
> + list_for_each_entry(gr,
> &mmc_test_result, link) {
> + struct
> mmc_test_transfer_result *tr;
> +
> + if (gr->card !=
> card)
> +
> continue;
> +
> + ret = snprintf(p,
> len, "Test %d: %d\n", gr->testcase + 1,
> +
> gr->result);
> + if (ret < 0)
> +
> goto err;
> + if (ret >= len)
> {
> +
> ret = -ENOBUFS;
> +
> goto err;
> + }
> + p += ret;
> + len -= ret;
> +
> +
> list_for_each_entry(tr, &gr->tr_lst, link) {
> +
> ret = snprintf(p, len, "%u %d %lu.%09lu %u\n",
> +
> tr->count, tr->sectors,
> +
> (unsigned long)tr->ts.tv_sec,
> +
> (unsigned long)tr->ts.tv_nsec,
> +
> tr->rate);
> +
> if (ret < 0)
> +
> goto err;
> +
> if (ret >= len) {
> +
> ret = -ENOBUFS;
> +
> goto err;
> +
> }
> + p
> += ret;
> +
> len -= ret;
> + }
> + }
> +
> + ret = PAGE_SIZE - len;
> +err:
> mutex_unlock(&mmc_test_lock);
>
> - return 0;
> + return ret;
> }
>
> static ssize_t mmc_test_store(struct device *dev,
> @@ -1946,6 +2103,12 @@ static ssize_t mmc_test_store(struct
> device *dev,
> if (!test)
> return -ENOMEM;
>
> + /*
> + * Remove all test cases
> associated with given card. Thus we have only
> + * actual data of the last
> run.
> + */
> + mmc_test_free_result(card);
> +
> test->card = card;
>
> test->buffer = kzalloc(BUFFER_SIZE,
> GFP_KERNEL);
> @@ -1992,6 +2155,7 @@ static int mmc_test_probe(struct
> mmc_card *card)
>
> static void mmc_test_remove(struct mmc_card *card)
> {
> + mmc_test_free_result(card);
> device_remove_file(&card->dev,
> &dev_attr_test);
> }
>
> @@ -2010,6 +2174,9 @@ static int __init
> mmc_test_init(void)
>
> static void __exit mmc_test_exit(void)
> {
> + /* Clear stalled data if card is still
> plugged */
> + mmc_test_free_result(NULL);
> +
>
> mmc_unregister_driver(&mmc_driver);
> }
>
> --
> 1.6.3.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-mmc" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists