From patchwork Tue Sep 7 12:35:26 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Shevchenko X-Patchwork-Id: 178122 Return-path: X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on void.printf.net X-Spam-Level: X-Spam-Status: No, score=-1.0 required=2.9 tests=RCVD_IN_DNSWL_LOW autolearn=disabled version=3.2.5 Envelope-to: chris@printf.net Delivery-date: Tue, 07 Sep 2010 13:41:34 +0100 Received: from lists.laptop.org ([18.85.2.145] helo=mail.laptop.org) by void.printf.net with esmtp (Exim 4.69) (envelope-from ) id 1OsxUU-0004ig-3W for chris@printf.net; Tue, 07 Sep 2010 13:41:34 +0100 Received: by mail.laptop.org (Postfix) id 905EE2439F; Tue, 7 Sep 2010 08:41:14 -0400 (EDT) Delivered-To: cjb@laptop.org Received: from spam.laptop.org (spam.laptop.org [18.85.46.23]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.laptop.org (Postfix) with ESMTPS id 787922439C for ; Tue, 7 Sep 2010 08:41:14 -0400 (EDT) X-ASG-Debug-ID: 1283863292-0b74f42f0001-zHW3sV Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by spam.laptop.org with ESMTP id fvlwCLcypGTsdfPE for ; Tue, 07 Sep 2010 08:41:32 -0400 (EDT) X-Barracuda-Envelope-From: linux-mmc-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756573Ab0IGMlb (ORCPT ); Tue, 7 Sep 2010 08:41:31 -0400 Received: from mail-ey0-f174.google.com ([209.85.215.174]:33392 "EHLO mail-ey0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756571Ab0IGMla (ORCPT ); Tue, 7 Sep 2010 08:41:30 -0400 Received: by eyb6 with SMTP id 6so2288626eyb.19 for ; Tue, 07 Sep 2010 05:41:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references:in-reply-to:references; bh=42ksyk7SkkIDm/185mb5a7czB3azCkXO7arsuebTcF0=; b=AECgl90ccd5VYHdS0qEUxiKWTNfqVA9wVU1cY5EE1fBuafWUsVDFxLVne1XjItAs8L JBN9xkzKKzPZX3jzBOI/V+ZSbKqbHoWcC5IrAlDY/CQYYggrmIn+ZqFt+CuMzFdR8Rk5 HyIpZhZ44H70YUoMRuiDeqyesdahf21fhmPrU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=iIiURYzwPewm1BgfBP6rJT2MwcHKnsEYlh+yZ3zJq9dQ+leXydOLyhBe1umJ9AX1dw HFUTRPIphhtoHuUCDilMOhQGFimCwNHCdZEODB9zpOxxnFj/Y4AlkDMsGZYAYYvlZnjK qRV+QWT8h7P9cJQGxt+uY3nIIOLF1OjJhUpcE= Received: by 10.213.10.141 with SMTP id p13mr206355ebp.23.1283862937897; Tue, 07 Sep 2010 05:35:37 -0700 (PDT) Received: from localhost.localdomain (starua.cc.colocall.com [62.149.23.157]) by mx.google.com with ESMTPS id a48sm9835454eei.1.2010.09.07.05.35.35 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 07 Sep 2010 05:35:37 -0700 (PDT) From: Andy Shevchenko To: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Hunter Adrian , Chris Ball , Andrew Morton , Andy Shevchenko X-ASG-Orig-Subj: [PATCHv6 3/3] mmc_test: collect data and show it via sysfs by demand Subject: [PATCHv6 3/3] mmc_test: collect data and show it via sysfs by demand Date: Tue, 7 Sep 2010 15:35:26 +0300 Message-Id: X-Mailer: git-send-email 1.6.3.3 In-Reply-To: References: <09f59cd98b59bf521a5866ab58c216e0a0347a6c.1283862780.git.ext-andriy.shevchenko@nokia.com> In-Reply-To: <09f59cd98b59bf521a5866ab58c216e0a0347a6c.1283862780.git.ext-andriy.shevchenko@nokia.com> References: <09f59cd98b59bf521a5866ab58c216e0a0347a6c.1283862780.git.ext-andriy.shevchenko@nokia.com> Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Barracuda-Connect: vger.kernel.org[209.132.180.67] X-Barracuda-Start-Time: 1283863292 X-Barracuda-URL: http://18.85.46.23:8000/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at laptop.org X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using global scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=5.5 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.40186 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 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 #include /* For nr_free_buffer_pages() */ +#include #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); }