[PATCH 1/1] mmc:Extension of MMC Block IOCTL Command support for testing of non read/write Commands

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch provides An infrastructure to test commands other than Read/Write commands using the IOCTL interface.The Patch can be useful incase of validating the device to verify whether device support a given command or not. The result of the sent command will be written to the  result element of the mmc_ioc_cmd structure passed through IOCTL interface.

Signed-off-by: Shashidhar Hiremath <shashidharh@xxxxxxxxxxxxxxx>
---
 drivers/mmc/card/Makefile    |    2 +-
 drivers/mmc/card/block.c     |   28 ++
 drivers/mmc/card/test_cmds.c |  743 ++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/card/test_cmds.h |   53 +++
 drivers/mmc/core/core.c      |    4 +
 drivers/mmc/core/mmc.c       |    4 +
 drivers/mmc/core/mmc_ops.c   |    1 +
 drivers/mmc/core/sd.c        |    2 +
 include/linux/mmc/ioctl.h    |    1 +
 9 files changed, 837 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mmc/card/test_cmds.c
 create mode 100644 drivers/mmc/card/test_cmds.h

diff --git a/drivers/mmc/card/Makefile b/drivers/mmc/card/Makefile
index c73b406..ea52ee1 100644
--- a/drivers/mmc/card/Makefile
+++ b/drivers/mmc/card/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
-mmc_block-objs			:= block.o queue.o
+mmc_block-objs			:= block.o queue.o test_cmds.o
 obj-$(CONFIG_MMC_TEST)		+= mmc_test.o
 
 obj-$(CONFIG_SDIO_UART)		+= sdio_uart.o
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index c80bb6d..c55d564 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -58,6 +58,7 @@ MODULE_ALIAS("mmc:block");
 #define INAND_CMD38_ARG_SECERASE 0x80
 #define INAND_CMD38_ARG_SECTRIM1 0x81
 #define INAND_CMD38_ARG_SECTRIM2 0x88
+#define NON_DATA_CMD 2
 
 static DEFINE_MUTEX(block_mutex);
 
@@ -77,6 +78,11 @@ static int max_devices;
 static DECLARE_BITMAP(dev_use, 256);
 static DECLARE_BITMAP(name_use, 256);
 
+/* prototype of function called for testing
+ * non-read-write commands
+ */
+void test_command(struct mmc_card *card, struct mmc_ioc_cmd *cmd);
+
 /*
  * There is one mmc_blk_data per slot.
  */
@@ -345,6 +351,28 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 
 	mmc_claim_host(card->host);
 
+	/* Calling API for testing the non-read/write commands */
+	if (idata->ic.write_flag == NON_DATA_CMD) {
+		test_command(card, &(idata->ic));
+		err = 0;
+		if (copy_to_user(&(ic_ptr->response), cmd.resp
+				 , sizeof(cmd.resp))) {
+			err = -EFAULT;
+			goto cmd_rel_host;
+		}
+		/* The result of the state of the tested command is returned
+		 * to user space RESULT OK - 0, RESULT_FAIL - 1
+		 * RESUL_UNSUP_CMD - 2, RESULT_UNSUP_CARD - 3
+		 * Other Failures - any other integer.
+		 */
+		if (copy_to_user(&(ic_ptr->result), &(idata->ic.result)
+				 , sizeof(idata->ic.result))) {
+			err = -EFAULT;
+			goto cmd_rel_host;
+		}
+		goto cmd_rel_host;
+	}
+
 	if (idata->ic.is_acmd) {
 		err = mmc_app_cmd(card->host, card);
 		if (err)
diff --git a/drivers/mmc/card/test_cmds.c b/drivers/mmc/card/test_cmds.c
new file mode 100644
index 0000000..dd9671f
--- /dev/null
+++ b/drivers/mmc/card/test_cmds.c
@@ -0,0 +1,743 @@
+/*
+ *  linux/drivers/mmc/card/test_cmds.c
+ *
+ *  This File implements functions for testing non-data commands 
+ *  through IOCTL interface.
+ *
+ *  Copyright (C) 2011 Vayavya Labs Pvt. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mmc/ioctl.h>
+
+#include "../core/sd_ops.h"
+#include "../core/mmc_ops.h"
+#include "../core/sdio_ops.h"
+#include "test_cmds.h"
+
+static int mmc_test_CMD0(struct mmc_card *card)
+{
+	int ret;
+	struct mmc_host *host = card->host;
+
+	mmc_power_off(host);
+	mmc_power_up(host);
+
+	ret = mmc_go_idle(card->host);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mmc_test_CMD1(struct mmc_card *card)
+{
+	int err = 0;
+	struct mmc_host *host = card->host;
+	u32 ocr;
+
+	if (card->type == MMC_TYPE_MMC) {
+		mmc_test_CMD0(card);
+
+		err = mmc_send_op_cond(card->host, 0, &ocr);
+		if (err)
+			return err;
+
+		/*
+		 * Sanity check the voltages that the card claims to
+		 * support.
+		 */
+		if (ocr & 0x7F) {
+			printk(KERN_WARNING
+			       "%s: card claims to support voltages "
+			       "below the defined range. These will be ignored.\n",
+			       mmc_hostname(host));
+			ocr &= ~0x7F;
+		}
+
+		host->ocr = mmc_select_voltage(host, ocr);
+
+		/*
+		 * Can we support the voltage of the card?
+		 */
+		if (!host->ocr) {
+			err = -EINVAL;
+			printk(KERN_ALERT
+			       "Card voltages cannot be supported\n");
+			return err;
+		}
+
+		mmc_go_idle(host);
+
+		/* The extra bit indicates that we support high capacity */
+		/*Sending ocr = 0 will just probe the card */
+		err = mmc_send_op_cond(card->host, ocr | (1 << 30), NULL);
+		if (err)
+			return err;
+	} else
+		err = RESULT_UNSUP_CARD;
+
+	return err;
+}
+
+static int mmc_test_CMD2(struct mmc_card *card)
+{
+	int err = 0;
+	u32 cid[4], rocr = 0;
+	struct mmc_host *host = card->host;
+	u32 ocr = host->ocr;
+
+	if (card->type == MMC_TYPE_MMC) {
+		err = mmc_test_CMD1(card);
+		if (err)
+			return err;
+
+		/*
+		 * For SPI, enable CRC as appropriate.
+		 */
+		if (mmc_host_is_spi(host)) {
+			err = mmc_spi_set_crc(host, 0);
+			if (err)
+				goto error;
+		}
+
+		/*
+		 * Fetch CID from card.
+		 */
+		if (mmc_host_is_spi(host)) {
+			printk(KERN_ALERT
+			       "Failed to execute since the host is SPI. Send cmd 10 to get CID\n");
+			return err = 1;
+		} else
+			err = mmc_all_send_cid(host, cid);
+		if (err)
+			goto error;
+
+		/*
+		 * Oldcard is not considered, infact the card we operate has its
+		 * card struct which was not freed. Also the CID will be stored
+		 * in the card struct filed CID.
+		 */
+
+		card->type = MMC_TYPE_MMC;
+		card->rca = 1;
+		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+	} else if (card->type == MMC_TYPE_SD) {
+
+		mmc_test_CMD0(card);
+		mmc_send_if_cond(host, host->ocr_avail);
+
+		err = mmc_send_app_op_cond(host, 0, &ocr);
+		if (err)
+			return err;
+
+		/*
+		 * Sanity check the voltages that the card claims to
+		 * support.
+		 */
+		if (ocr & 0x7F) {
+			printk(KERN_WARNING
+			       "%s: card claims to support voltages "
+			       "below the defined range. These will be ignored.\n",
+			       mmc_hostname(host));
+			ocr &= ~0x7F;
+		}
+
+		if (ocr & MMC_VDD_165_195) {
+			printk(KERN_WARNING "%s: SD card claims to support the "
+			       "incompletely defined 'low voltage range'. This "
+			       "will be ignored.\n", mmc_hostname(host));
+			ocr &= ~MMC_VDD_165_195;
+		}
+
+		host->ocr = mmc_select_voltage(host, ocr);
+
+		/*
+		 * Can we support the voltage(s) of the card(s)?
+		 */
+		if (!host->ocr) {
+			printk(KERN_ALERT
+			       "Card voltages cannot be supported\n");
+			err = -EINVAL;
+			return err;
+		}
+
+		err = mmc_sd_get_cid(host, ocr, cid, &rocr);
+		if (err)
+			return err;
+
+		card->type = MMC_TYPE_SD;
+		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+	} else {
+		err = RESULT_UNSUP_CARD;
+		return err;
+	}
+
+error:
+	return err;
+}
+
+static int mmc_test_CMD3(struct mmc_card *card)
+{
+	int err;
+	struct mmc_host *host = card->host;
+
+	err = mmc_test_CMD2(card);
+	if (err)
+		return err;
+
+	if (card->type == MMC_TYPE_MMC) {
+		/* For native busses:  set card RCA and quit open drain mode */
+		if (!mmc_host_is_spi(host)) {
+			err = mmc_set_relative_addr(card);
+			if (err)
+				return err;
+
+			mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+		}
+	} else if (card->type == MMC_TYPE_SD) {
+
+
+		/* For native busses:  get card RCA and quit open drain mode */
+		if (!mmc_host_is_spi(host)) {
+			err = mmc_send_relative_addr(host, &card->rca);
+			if (err)
+				return err;
+
+			mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+		}
+	} else {
+		/* SDIO cards not supported */
+		err = RESULT_UNSUP_CARD;
+		return err;
+	}
+
+	return 0;
+}
+
+static int unsupp_cmd(struct mmc_card *card)
+{
+	printk(KERN_ERR "COMMAND NOT SUPPORTED");
+	return RESULT_UNSUP_CMD;
+}
+
+/* TODO Deselection of the card is yet to be supported */
+static int mmc_test_CMD7(struct mmc_card *card)
+{
+	int err = 0;
+	struct mmc_host *host = card->host;
+
+	if (card->type == MMC_TYPE_MMC || card->type == MMC_TYPE_SD) {
+		err = mmc_test_CMD3(card);
+		if (err)
+			return err;
+	} else {
+		err = RESULT_UNSUP_CARD;
+		return err;
+	}
+
+	/* Select card, as all following commands rely on that */
+	if (!mmc_host_is_spi(host)) {
+		err = mmc_select_card(card);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int mmc_test_CMD8(struct mmc_card *card)
+{
+	int err;
+	struct mmc_host *host = card->host;
+	u32 ocr = host->ocr;
+
+	if (card->type == MMC_TYPE_MMC) {
+
+		err = mmc_test_CMD7(card);
+		if (err)
+			return err;
+
+		/*
+		 * Fetch and process extended CSD.
+		 */
+		err = mmc_read_ext_csd(card);
+		if (err)
+			return err;
+		/* Erase size depends on CSD and Extended CSD */
+		mmc_set_erase_size(card);
+	} else if (card->type == MMC_TYPE_SD) {
+
+		mmc_test_CMD0(card);
+		mmc_send_if_cond(host, host->ocr_avail);
+
+		err = mmc_send_app_op_cond(host, 0, &ocr);
+		if (err)
+			return err;
+
+		/*
+		 * Sanity check the voltages that the card claims to
+		 * support.
+		 */
+		if (ocr & 0x7F) {
+			printk(KERN_WARNING
+			       "%s: card claims to support voltages "
+			       "below the defined range. These will be ignored.\n",
+			       mmc_hostname(host));
+			ocr &= ~0x7F;
+		}
+
+		if (ocr & MMC_VDD_165_195) {
+			printk(KERN_WARNING "%s: SD card claims to support the "
+			       "incompletely defined 'low voltage range'. This "
+			       "will be ignored.\n", mmc_hostname(host));
+			ocr &= ~MMC_VDD_165_195;
+		}
+
+		host->ocr = mmc_select_voltage(host, ocr);
+
+		/*
+		 * Can we support the voltage(s) of the card(s)?
+		 */
+		if (!host->ocr) {
+			printk(KERN_ALERT
+			       "Card voltages cannot be supported\n");
+			err = -EINVAL;
+			return err;
+		}
+
+		/*
+		 * Since we're changing the OCR value, we seem to
+		 * need to tell some cards to go back to the idle
+		 * state.  We wait 1ms to give cards time to
+		 * respond.
+		 */
+		mmc_go_idle(host);
+
+		/*
+		 * If SD_SEND_IF_COND indicates an SD 2.0
+		 * compliant card and we should set bit 30
+		 * of the ocr to indicate that we can handle
+		 * block-addressed SDHC cards.
+		 */
+		err = mmc_send_if_cond(host, host->ocr);
+		if (!err)
+			ocr |= 1 << 30;
+		else
+			return err;
+	} else {
+		err = RESULT_UNSUP_CARD;
+		return err;
+	}
+
+	return 0;
+}
+
+static int mmc_test_CMD9(struct mmc_card *card)
+{
+	int err;
+	struct mmc_host *host = card->host;
+
+	err = mmc_test_CMD3(card);
+	if (err)
+		return err;
+
+	if (card->type == MMC_TYPE_MMC) {
+		/*
+		 * Fetch CSD from card.
+		 */
+		err = mmc_send_csd(card, card->raw_csd);
+		if (err)
+			return err;
+
+		err = mmc_decode_csd(card);
+		if (err)
+			return err;
+
+		err = mmc_decode_cid(card);
+		if (err)
+			return err;
+	} else if (card->type == MMC_TYPE_SD) {
+		err = mmc_sd_get_csd(host, card);
+		if (err)
+			return err;
+
+		mmc_decode_cid(card);
+	} else {
+		return err;
+	}
+
+	return 0;
+}
+
+static int mmc_test_CMD10(struct mmc_card *card)
+{
+	int err = 0;
+	u32 cid[4];
+	struct mmc_host *host = card->host;
+	u32 ocr = host->ocr;
+
+	/* The code has been copied here from the mmc_init_card function. This
+	 * just to stop after CMD2 is successfully sent to the card */
+	if (card->type == MMC_TYPE_MMC) {
+		err = mmc_test_CMD1(card);
+		if (err)
+			return err;
+
+		/*
+		 * For SPI, enable CRC as appropriate.
+		 */
+		if (mmc_host_is_spi(host)) {
+			err = mmc_spi_set_crc(host, 0);
+			if (err)
+				return err;
+		}
+
+		/*
+		 * Fetch CID from card.
+		 */
+		if (mmc_host_is_spi(host))
+			err = mmc_send_cid(host, cid);
+		else {
+			printk(KERN_ALERT
+			       "Host is non-SPI, use CMD2 to get the CID\n");
+			err = 1;
+		}
+		if (err)
+			return err;
+	} else if (card->type == MMC_TYPE_SD) {
+
+		mmc_test_CMD0(card);
+		mmc_send_if_cond(host, host->ocr_avail);
+
+		err = mmc_send_app_op_cond(host, 0, &ocr);
+		if (err)
+			return err;
+
+		/*
+		 * Sanity check the voltages that the card claims to
+		 * support.
+		 */
+		if (ocr & 0x7F) {
+			printk(KERN_WARNING
+			       "%s: card claims to support voltages "
+			       "below the defined range. These will be ignored.\n",
+			       mmc_hostname(host));
+			ocr &= ~0x7F;
+		}
+
+		if (ocr & MMC_VDD_165_195) {
+			printk(KERN_WARNING "%s: SD card claims to support the "
+			       "incompletely defined 'low voltage range'. This "
+			       "will be ignored.\n", mmc_hostname(host));
+			ocr &= ~MMC_VDD_165_195;
+		}
+
+		host->ocr = mmc_select_voltage(host, ocr);
+
+		/*
+		 * Can we support the voltage(s) of the card(s)?
+		 */
+		if (!host->ocr) {
+			printk(KERN_ALERT
+			       "Card voltages cannot be supported\n");
+			err = -EINVAL;
+			return err;
+		}
+
+		/*
+		 * Since we're changing the OCR value, we seem to
+		 * need to tell some cards to go back to the idle
+		 * state.  We wait 1ms to give cards time to
+		 * respond.
+		 */
+		mmc_go_idle(host);
+
+		/*
+		 * If SD_SEND_IF_COND indicates an SD 2.0
+		 * compliant card and we should set bit 30
+		 * of the ocr to indicate that we can handle
+		 * block-addressed SDHC cards.
+		 */
+		err = mmc_send_if_cond(host, host->ocr);
+		if (!err)
+			ocr |= 1 << 30;
+
+		err = mmc_send_app_op_cond(host, ocr, NULL);
+		if (err)
+			return err;
+
+		if (mmc_host_is_spi(host)) {
+			err = mmc_send_cid(host, cid);
+		} else {
+			printk(KERN_ALERT
+			       "Host is non-SPI, hence use CMD2 to get CID\n");
+			err = 1;
+		}
+	} else
+		err = RESULT_UNSUP_CARD;
+
+	return err;
+}
+
+static int mmc_test_CMD12(struct mmc_card *card)
+{
+	int err;
+	struct mmc_command cmd;
+	struct mmc_host *host = card->host;
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_STOP_TRANSMISSION;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int mmc_test_CMD13(struct mmc_card *card)
+{
+	int err = 0;
+	struct mmc_command cmd;
+	u32 *ssr;
+
+	if (card->type == MMC_TYPE_MMC) {
+		/* This code just sends the get status command only
+		 * Get the status of the card without disturbing anything */
+
+		memset(&cmd, 0, sizeof(struct mmc_command));
+		cmd.opcode = MMC_SEND_STATUS;
+		if (!mmc_host_is_spi(card->host))
+			cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
+		err = mmc_wait_for_cmd(card->host, &cmd, 0);
+		if (err) {
+			printk(KERN_ERR "error %d sending status comand\n",
+			       err);
+
+			return err;
+		}
+	} else if (card->type == MMC_TYPE_SD) {
+		if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
+			printk(KERN_WARNING
+			       "%s: card lacks mandatory SD Status "
+			       "function.\n", mmc_hostname(card->host));
+			return 0;
+		}
+
+		ssr = kmalloc(64, GFP_KERNEL);
+		if (!ssr)
+			return -ENOMEM;
+
+		err = mmc_app_sd_status(card, ssr);
+		if (err)
+			printk(KERN_ALERT "%s: problem reading SD Status "
+			       "register.\n", mmc_hostname(card->host));
+		kfree(ssr);
+		return err;
+	} else
+		err = RESULT_UNSUP_CARD;
+
+
+	return 0;
+}
+
+static int mmc_go_inactive_state(struct mmc_card *card)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card->host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_GO_INACTIVE_STATE;
+	cmd.arg = card->host->card->rca << 16;
+	cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, 4);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int mmc_test_CMD15(struct mmc_card *card)
+{
+	int err;
+
+	if (card->type == MMC_TYPE_SDIO) {
+		err = RESULT_UNSUP_CARD;
+		return err;
+	}
+
+	err = mmc_go_inactive_state(card);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+/*
+ * Configure correct block size in card
+ */
+static int mmc_test_set_blksize(struct mmc_card *card, unsigned size)
+{
+	return mmc_set_blocklen(card, size);
+}
+
+/* Coded as a stand alone API
+ * To be used only if the card is in data transfer mode
+ */
+static int mmc_test_CMD16(struct mmc_card *card)
+{
+	int err;
+
+	/* Calling the top level mmc/sd card init functions */
+
+	if (card->type == MMC_TYPE_SDIO) {
+		err = RESULT_UNSUP_CARD;
+		return err;
+	}
+
+	/* Set to 512 for testing */
+	err = mmc_test_set_blksize(card, 512);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+struct mmc_test_case {
+	const char *name;
+	int (*prepare) (struct mmc_card *);
+	int (*run) (struct mmc_card *);
+	int (*cleanup) (struct mmc_card *);
+};
+
+const struct mmc_test_case mmc_test_cases[] = {
+	{
+	 .name = "Test CMD0",
+	 .run = mmc_test_CMD0,
+	 },
+	{
+	 .name = "Test CMD1",
+	 .run = mmc_test_CMD1,
+	 },
+	{
+	 .name = "Test CMD2",
+	 .run = mmc_test_CMD2,
+	 },
+	{
+	 .name = "Test CMD3",
+	 .run = mmc_test_CMD3,
+	 },
+	{
+	 .name = "Test CMD4",
+	 .run = unsupp_cmd,
+	 },
+	{
+	 .name = "Test CMD5",
+	 .run = unsupp_cmd,
+	 },
+	{
+	 .name = "Test CMD6",
+	 .run = unsupp_cmd,
+	 },
+
+	{
+	 .name = "Test CMD7",
+	 .run = mmc_test_CMD7,
+	 },
+	{
+	 .name = "Test CMD8",
+	 .run = mmc_test_CMD8,
+	 },
+	{
+	 .name = "Test CMD9",
+	 .run = mmc_test_CMD9,
+	 },
+	{
+	 .name = "Test CMD10",
+	 .run = mmc_test_CMD10,
+	 },
+	{
+	 .name = "Test CMD11",
+	 .run = unsupp_cmd,
+	 },
+	{
+	 .name = "Test CMD12",
+	 .run = mmc_test_CMD12,
+	 },
+	{
+	 .name = "Test CMD13",
+	 .run = mmc_test_CMD13,
+	 },
+	{
+	 .name = "Test CMD14",
+	 .run = unsupp_cmd,
+	 },
+	{
+	 .name = "Test CMD15",
+	 .run = mmc_test_CMD15,
+	 },
+	{
+	 .name = "Test CMD16",
+	 .run = mmc_test_CMD16,
+	 },
+};
+
+static void mmc_test_run(struct mmc_card *card, struct mmc_ioc_cmd *cmd)
+{
+	int ret;
+
+
+	printk(KERN_ALERT "%s: Test case %d. %s...\n",
+	       mmc_hostname(card->host), cmd->opcode,
+	       mmc_test_cases[cmd->opcode].name);
+
+	ret = mmc_test_cases[cmd->opcode].run(card);
+	switch (ret) {
+	case RESULT_OK:
+		cmd->result = RESULT_OK;
+		break;
+	case RESULT_FAIL:
+		cmd->result = RESULT_FAIL;
+		break;
+	case RESULT_UNSUP_CMD:
+		cmd->result = RESULT_UNSUP_CMD;
+		break;
+	case RESULT_UNSUP_CARD:
+		cmd->result = RESULT_UNSUP_CARD;
+		break;
+	default:
+		cmd->result = ret;
+	}
+
+}
+
+void test_command(struct mmc_card *card, struct mmc_ioc_cmd *cmd)
+{
+
+	mmc_test_run(card, cmd);
+}
+
+MODULE_DESCRIPTION("Supplements the Block Layer for non-data command testing");
+MODULE_AUTHOR("Shashidhar Hiremath");
+MODULE_AUTHOR("Vayavya Labs Pvt. Ltd");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/card/test_cmds.h b/drivers/mmc/card/test_cmds.h
new file mode 100644
index 0000000..877e6c5
--- /dev/null
+++ b/drivers/mmc/card/test_cmds.h
@@ -0,0 +1,53 @@
+/*
+ *  linux/drivers/mmc/card/test_cmds.c
+ *
+ *  This File includes protos for functions for testing non-data commands
+ *  through IOCTL interface.
+ *
+ *  Copyright (C) 2011 Vayavya Labs Pvt. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _TEST_CMDS_H_
+#define _TEST_CMDS_H_
+
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/swap.h>
+
+#define RESULT_OK		0
+#define RESULT_FAIL		1
+#define RESULT_UNSUP_CMD	2
+#define RESULT_UNSUP_CARD	3
+
+
+/* core.c layer exported functions */
+extern void mmc_set_bus_mode(struct mmc_host *, unsigned int);
+extern u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
+extern void mmc_power_up(struct mmc_host *);
+extern void mmc_power_off(struct mmc_host *);
+
+/* Both the below functions are present in sd.c and mmc.c files */
+extern int mmc_decode_csd(struct mmc_card *);
+extern int mmc_decode_cid(struct mmc_card *);
+
+/*Exported from mmc.c file */
+extern int mmc_read_ext_csd(struct mmc_card *);
+extern void mmc_set_erase_size(struct mmc_card *);
+
+/* Defined and exported in mmc_ops.c */
+extern int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
+
+/* Defined and exported in sd.c */
+extern int mmc_sd_get_csd(struct mmc_host *, struct mmc_card *);
+extern int mmc_sd_get_cid(struct mmc_host *, u32, u32 *, u32 *);
+
+#endif /* _TEST_CMDS_H_ */
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7ee2e07..424e0bc 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -951,6 +951,7 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
 	mmc_set_ios(host);
 	mmc_host_clk_release(host);
 }
+EXPORT_SYMBOL(mmc_set_bus_mode);
 
 /*
  * Change data bus width of a host.
@@ -1170,6 +1171,7 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
 
 	return ocr;
 }
+EXPORT_SYMBOL(mmc_select_voltage);
 
 int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11)
 {
@@ -1318,6 +1320,7 @@ static void mmc_power_up(struct mmc_host *host)
 
 	mmc_host_clk_release(host);
 }
+EXPORT_SYMBOL(mmc_power_up);
 
 void mmc_power_off(struct mmc_host *host)
 {
@@ -1352,6 +1355,7 @@ void mmc_power_off(struct mmc_host *host)
 
 	mmc_host_clk_release(host);
 }
+EXPORT_SYMBOL(mmc_power_off);
 
 /*
  * Cleanup when the last reference to the bus operator is dropped.
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index a1223bd..23d7d8e 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -108,6 +108,7 @@ static int mmc_decode_cid(struct mmc_card *card)
 
 	return 0;
 }
+EXPORT_SYMBOL(mmc_decode_cid);
 
 static void mmc_set_erase_size(struct mmc_card *card)
 {
@@ -118,6 +119,7 @@ static void mmc_set_erase_size(struct mmc_card *card)
 
 	mmc_init_erase(card);
 }
+EXPORT_SYMBOL(mmc_set_erase_size);
 
 /*
  * Given a 128-bit response, decode to our card CSD structure.
@@ -172,6 +174,7 @@ static int mmc_decode_csd(struct mmc_card *card)
 
 	return 0;
 }
+EXPORT_SYMBOL(mmc_decode_csd);
 
 /*
  * Read extended CSD.
@@ -492,6 +495,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
 out:
 	return err;
 }
+EXPORT_SYMBOL(mmc_read_ext_csd);
 
 static inline void mmc_free_ext_csd(u8 *ext_csd)
 {
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 007863e..1420ba0 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -364,6 +364,7 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
 		host->use_spi_crc = use_crc;
 	return err;
 }
+EXPORT_SYMBOL(mmc_spi_set_crc);
 
 /**
  *	mmc_switch - modify EXT_CSD register
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index bcc2c90..ba1d3c8 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -776,6 +776,7 @@ try_again:
 
 	return err;
 }
+EXPORT_SYMBOL(mmc_sd_get_cid);
 
 int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card)
 {
@@ -794,6 +795,7 @@ int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card)
 
 	return 0;
 }
+EXPORT_SYMBOL(mmc_sd_get_csd);
 
 int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
 	bool reinit)
diff --git a/include/linux/mmc/ioctl.h b/include/linux/mmc/ioctl.h
index 8fa5bc5..0186a86 100644
--- a/include/linux/mmc/ioctl.h
+++ b/include/linux/mmc/ioctl.h
@@ -39,6 +39,7 @@ struct mmc_ioc_cmd {
 
 	/* DAT buffer */
 	__u64 data_ptr;
+	unsigned int result;
 };
 #define mmc_ioc_cmd_set_data(ic, ptr) ic.data_ptr = (__u64)(unsigned long) ptr
 
-- 
1.7.6.4

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


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux