diff mbox

[3/3] mmc_test: collect data and show it via sysfs by demand

Message ID 5f816a17d1a3a630eeb2850ec217d32a9b55fc8d.1283276161.git.ext-andriy.shevchenko@nokia.com (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Andy Shevchenko Sept. 1, 2010, 6:26 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 5423ac9..3cfef37 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -16,6 +16,7 @@ 
 
 #include <linux/scatterlist.h>
 #include <linux/swap.h>
+#include <linux/list.h>
 
 #define RESULT_OK		0
 #define RESULT_FAIL		1
@@ -66,6 +67,28 @@  struct mmc_test_area {
 };
 
 /**
+ * struct mmc_test_transfer_result - container of the transfer results for
+ * performance tests.
+ */
+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 - container of the results for tests.
+ */
+struct mmc_test_general_result {
+	struct list_head link;
+	int testcase;
+	int result;
+	struct list_head transfer;
+};
+
+/**
  * struct mmc_test_card - test information.
  * @card: card under test
  * @scratch: transfer buffer
@@ -81,7 +104,8 @@  struct mmc_test_card {
 #ifdef CONFIG_HIGHMEM
 	struct page	*highmem;
 #endif
-	struct mmc_test_area area;
+	struct mmc_test_area	area;
+	struct list_head	*result;
 };
 
 /*******************************************************************/
@@ -420,6 +444,10 @@  static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes,
 {
 	unsigned int rate, sectors = bytes >> 9;
 	struct timespec ts;
+	struct mmc_test_transfer_result *transfer;
+	struct mmc_test_general_result *result =
+		list_entry(test->result->prev, struct mmc_test_general_result,
+			link);
 
 	ts = timespec_sub(*ts2, *ts1);
 
@@ -430,6 +458,15 @@  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);
+
+	transfer = kmalloc(sizeof(struct mmc_test_transfer_result), GFP_KERNEL);
+
+	transfer->count = 0;
+	transfer->sectors = sectors;
+	memcpy(&transfer->ts, &ts, sizeof(struct timespec));
+	transfer->rate = rate;
+
+	list_add_tail(&transfer->link, &result->transfer);
 }
 
 /*
@@ -442,6 +479,10 @@  static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
 	unsigned int rate, sectors = bytes >> 9;
 	uint64_t tot = bytes * count;
 	struct timespec ts;
+	struct mmc_test_transfer_result *transfer;
+	struct mmc_test_general_result *result =
+		list_entry(test->result->prev, struct mmc_test_general_result,
+			link);
 
 	ts = timespec_sub(*ts2, *ts1);
 
@@ -453,6 +494,15 @@  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);
+
+	transfer = kmalloc(sizeof(struct mmc_test_transfer_result), GFP_KERNEL);
+
+	transfer->count = count;
+	transfer->sectors = sectors;
+	memcpy(&transfer->ts, &ts, sizeof(struct timespec));
+	transfer->rate = rate;
+
+	list_add_tail(&transfer->link, &result->transfer);
 }
 
 /*
@@ -1847,6 +1897,8 @@  static void mmc_test_run(struct mmc_test_card *test, long testcase)
 	mmc_claim_host(test->card->host);
 
 	for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
+		struct mmc_test_general_result *result;
+
 		if (testcase && ((i + 1) != testcase))
 			continue;
 
@@ -1865,6 +1917,11 @@  static void mmc_test_run(struct mmc_test_card *test, long testcase)
 			}
 		}
 
+		result = kzalloc(sizeof(struct mmc_test_general_result),
+			GFP_KERNEL);
+		INIT_LIST_HEAD(&result->transfer);
+		list_add_tail(&result->link, test->result);
+
 		ret = mmc_test_cases[i].run(test);
 		switch (ret) {
 		case RESULT_OK:
@@ -1890,6 +1947,10 @@  static void mmc_test_run(struct mmc_test_card *test, long testcase)
 				mmc_hostname(test->card->host), ret);
 		}
 
+		/* Save the result */
+		result->testcase = i;
+		result->result = ret;
+
 		if (mmc_test_cases[i].cleanup) {
 			ret = mmc_test_cases[i].cleanup(test);
 			if (ret) {
@@ -1907,13 +1968,57 @@  static void mmc_test_run(struct mmc_test_card *test, long testcase)
 		mmc_hostname(test->card->host));
 }
 
+static struct list_head mmc_test_result;
+
+static void mmc_test_result_free(struct list_head *result)
+{
+	struct mmc_test_general_result *gr, *grs;
+
+	list_for_each_entry_safe(gr, grs, result, link) {
+		struct mmc_test_transfer_result *tr, *trs;
+
+		list_for_each_entry_safe(tr, trs, &gr->transfer, link)
+			kfree(tr);
+		kfree(gr);
+	}
+}
+
 static ssize_t mmc_test_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
+	struct mmc_test_general_result *result;
+	char *p = buf;
+	size_t len = PAGE_SIZE;
+
 	mutex_lock(&mmc_test_lock);
+
+	list_for_each_entry(result, &mmc_test_result, link) {
+		struct mmc_test_transfer_result *transfer;
+		int ret;
+
+		ret = snprintf(p, len, "Test %d: %d\n", result->testcase + 1,
+			result->result);
+		if (ret < 0)
+			return ret;
+		p += ret;
+		len -= ret;
+
+		list_for_each_entry(transfer, &result->transfer, link) {
+			ret = snprintf(p, len, "%u %d %lu.%09lu %u\n",
+				transfer->count, transfer->sectors,
+				(unsigned long)transfer->ts.tv_sec,
+				(unsigned long)transfer->ts.tv_nsec,
+				transfer->rate);
+			if (ret < 0)
+				return ret;
+			p += ret;
+			len -= ret;
+		}
+	}
+
 	mutex_unlock(&mmc_test_lock);
 
-	return 0;
+	return PAGE_SIZE - len;
 }
 
 static ssize_t mmc_test_store(struct device *dev,
@@ -1932,6 +2037,10 @@  static ssize_t mmc_test_store(struct device *dev,
 
 	test->card = card;
 
+	mmc_test_result_free(&mmc_test_result);
+	INIT_LIST_HEAD(&mmc_test_result);
+	test->result = &mmc_test_result;
+
 	test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
 #ifdef CONFIG_HIGHMEM
 	test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
@@ -1969,6 +2078,8 @@  static int mmc_test_probe(struct mmc_card *card)
 	if (ret)
 		return ret;
 
+	INIT_LIST_HEAD(&mmc_test_result);
+
 	dev_info(&card->dev, "Card claimed for testing.\n");
 
 	return 0;
@@ -1976,6 +2087,7 @@  static int mmc_test_probe(struct mmc_card *card)
 
 static void mmc_test_remove(struct mmc_card *card)
 {
+	mmc_test_result_free(&mmc_test_result);
 	device_remove_file(&card->dev, &dev_attr_test);
 }