From 5ba593a97206fb96dc0e63f209e6ade86452844f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 21 Nov 2006 17:45:37 +0100 Subject: [PATCH] mmc: Handle wbsd's stupid command list The wbsd hardware is so incredibly brain damaged that it has an internal list of commands that result in data transfers. The result being that commands that aren't on this list aren't supported. Instead of locking up, waiting for a data interrupt that will never come, we try to fail a bit more gracefully. Signed-off-by: Pierre Ossman --- drivers/mmc/wbsd.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index cf16e44c0301..c1dd6ad8dab3 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -1,7 +1,7 @@ /* * linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver * - * Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved. + * Copyright (C) 2004-2006 Pierre Ossman, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -909,6 +909,45 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq) * transfered. */ if (cmd->data && (cmd->error == MMC_ERR_NONE)) { + /* + * The hardware is so delightfully stupid that it has a list + * of "data" commands. If a command isn't on this list, it'll + * just go back to the idle state and won't send any data + * interrupts. + */ + switch (cmd->opcode) { + case 11: + case 17: + case 18: + case 20: + case 24: + case 25: + case 26: + case 27: + case 30: + case 42: + case 56: + break; + + /* ACMDs. We don't keep track of state, so we just treat them + * like any other command. */ + case 51: + break; + + default: +#ifdef CONFIG_MMC_DEBUG + printk(KERN_WARNING "%s: Data command %d is not " + "supported by this controller.\n", + mmc_hostname(host->mmc), cmd->opcode); +#endif + cmd->data->error = MMC_ERR_INVALID; + + if (cmd->data->stop) + wbsd_send_command(host, cmd->data->stop); + + goto done; + }; + /* * Dirty fix for hardware bug. */