--- kernel-source-2.6.16-2.6.16.rel/include/linux/mmc/card.h	2007-08-22 10:44:38.000000000 +0200
+++ kernel-source-2.6.16-2.6.16.my/include/linux/mmc/card.h	2007-12-08 21:45:54.000000000 +0100
@@ -39,6 +39,11 @@
 				write_misalign:1;
 };
 
+struct mmc_ext_csd {
+	unsigned int		hs_max_dtr;
+	unsigned int		sectors;
+};
+
 struct sd_scr {
 	unsigned char		sda_vsn;
 	unsigned char		bus_widths;
@@ -46,6 +51,10 @@
 #define SD_SCR_BUS_WIDTH_4	(1<<2)
 };
 
+struct sd_switch_caps {
+	unsigned int		hs_max_dtr;
+};
+
 struct mmc_host;
 
 /*
@@ -62,12 +71,17 @@
 #define MMC_STATE_BAD		(1<<2)		/* unrecognised device */
 #define MMC_STATE_SDCARD	(1<<3)		/* is an SD card */
 #define MMC_STATE_READONLY	(1<<4)		/* card is read-only */
+#define MMC_STATE_HIGHSPEED	(1<<5)		/* card is in high speed mode */
+#define MMC_STATE_BLOCKADDR	(1<<6)		/* card uses block-addressing */
+	unsigned int            rq_state;       /* Last state at end of rq */
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	u32			raw_scr[2];	/* raw card SCR */
 	struct mmc_cid		cid;		/* card identification */
 	struct mmc_csd		csd;		/* card specific */
+	struct mmc_ext_csd	ext_csd;	/* mmc v4 extended card specific */
 	struct sd_scr		scr;		/* extra SD information */
+	struct sd_switch_caps	sw_caps;	/* switch (CMD6) caps */
 };
 
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
@@ -75,12 +89,16 @@
 #define mmc_card_bad(c)		((c)->state & MMC_STATE_BAD)
 #define mmc_card_sd(c)		((c)->state & MMC_STATE_SDCARD)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
+#define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
+#define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_dead(c)	((c)->state |= MMC_STATE_DEAD)
 #define mmc_card_set_bad(c)	((c)->state |= MMC_STATE_BAD)
 #define mmc_card_set_sd(c)	((c)->state |= MMC_STATE_SDCARD)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
+#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
+#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
 
 #define mmc_card_name(c)	((c)->cid.prod_name)
 #define mmc_card_id(c)		((c)->dev.bus_id)
--- kernel-source-2.6.16-2.6.16.rel/include/linux/mmc/host.h	2007-08-22 10:44:38.000000000 +0200
+++ kernel-source-2.6.16-2.6.16.my/include/linux/mmc/host.h	2007-12-08 21:46:30.000000000 +0100
@@ -57,11 +57,18 @@
 #define MMC_POWER_OFF		0
 #define MMC_POWER_UP		1
 #define MMC_POWER_ON		2
+#define MMC_POWER_STANDBY	3
 
 	unsigned char	bus_width;		/* data bus width */
 
 #define MMC_BUS_WIDTH_1		0
 #define MMC_BUS_WIDTH_4		2
+
+	unsigned char	timing;			/* timing specification used */
+
+#define MMC_TIMING_LEGACY	0
+#define MMC_TIMING_MMC_HS	1
+#define MMC_TIMING_SD_HS	2
 };
 
 struct mmc_host_ops {
@@ -77,7 +84,7 @@
 	struct device		*dev;
 	struct class_device	class_dev;
 	int			index;
-	struct mmc_host_ops	*ops;
+	const struct mmc_host_ops *ops;
 	unsigned int		f_min;
 	unsigned int		f_max;
 	u32			ocr_avail;
@@ -85,13 +92,20 @@
 	unsigned long		caps;		/* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA	(1 << 0)	/* Can the host do 4 bit transfers */
+#define MMC_CAP_MULTIWRITE	(1 << 1)	/* Can accurately report bytes sent to card on error */
+#define MMC_CAP_BYTEBLOCK	(1 << 2)	/* Can do non-log2 block sizes */
+#define MMC_CAP_MMC_HIGHSPEED	(1 << 3)	/* Can do MMC high-speed timing */
+#define MMC_CAP_SD_HIGHSPEED	(1 << 4)	/* Can do SD high-speed timing */
+#define MMC_CAP_STANDBY         (1 << 5)        /* Low power mode available */
 
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
 	unsigned short		max_hw_segs;	/* see blk_queue_max_hw_segments */
 	unsigned short		max_phys_segs;	/* see blk_queue_max_phys_segments */
-	unsigned short		max_sectors;	/* see blk_queue_max_sectors */
 	unsigned short		unused;
+	unsigned int		max_req_size;	/* maximum number of bytes in one req */
+	unsigned int		max_blk_size;	/* maximum size of one mmc block */
+	unsigned int		max_blk_count;	/* maximum number of blocks in one req */
 
 	/* private data */
 	struct mmc_ios		ios;		/* current io bus settings */
@@ -104,11 +118,15 @@
 	struct list_head	cards;		/* devices attached to this host */
 
 	wait_queue_head_t	wq;
-	spinlock_t		lock;		/* card_busy lock */
-	struct mmc_card		*card_busy;	/* the MMC card claiming host */
+	spinlock_t		lock;		/* claimed lock */
+	unsigned int		claimed:1;	/* host exclusively claimed */
+
 	struct mmc_card		*card_selected;	/* the selected MMC card */
 
 	struct work_struct	detect;
+	struct work_struct      idle_work;
+	struct timer_list       idle_timer;
+	unsigned int            idle_delay;
 
 	unsigned long		private[0] ____cacheline_aligned;
 };
--- kernel-source-2.6.16-2.6.16.rel/include/linux/mmc/protocol.h	2007-08-22 10:44:38.000000000 +0200
+++ kernel-source-2.6.16-2.6.16.my/include/linux/mmc/protocol.h	2007-12-07 20:21:13.000000000 +0100
@@ -25,14 +25,16 @@
 #ifndef MMC_MMC_PROTOCOL_H
 #define MMC_MMC_PROTOCOL_H
 
-/* Standard MMC commands (3.1)           type  argument     response */
+/* Standard MMC commands (4.1)           type  argument     response */
    /* class 1 */
 #define	MMC_GO_IDLE_STATE         0   /* bc                          */
 #define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
 #define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
 #define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
 #define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
+#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
 #define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
+#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
 #define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
 #define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
 #define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
@@ -77,14 +79,50 @@
 #define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
 
 /* SD commands                           type  argument     response */
-  /* class 8 */
+  /* class 0 */
 /* This is basically the same command as for MMC with some quirks. */
 #define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
+#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
+
+  /* class 10 */
+#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
 
   /* Application commands */
 #define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
+#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
 #define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
 #define SD_APP_SEND_SCR          51   /* adtc                    R1  */
+/*
+ * MMC_SWITCH argument format:
+ *
+ *	[31:26] Always 0
+ *	[25:24] Access Mode
+ *	[23:16] Location of target Byte in EXT_CSD
+ *	[15:08] Value Byte
+ *	[07:03] Always 0
+ *	[02:00] Command Set
+ */
+
+/*
+ * SD_SWITCH argument format:
+ *
+ *      [31] Check (0) or switch (1)
+ *      [30:24] Reserved (0)
+ *      [23:20] Function group 6
+ *      [19:16] Function group 5
+ *      [15:12] Function group 4
+ *      [11:8] Function group 3
+ *      [7:4] Function group 2
+ *      [3:0] Function group 1
+ */
+
+/*
+ * SD_SEND_IF_COND argument format:
+ *
+ *	[31:12] Reserved (0)
+ *	[11:8] Host Voltage Supply Flags
+ *	[7:0] Check Pattern (0xAA)
+ */
 
 /*
   MMC status in R1
@@ -124,6 +162,16 @@
 #define R1_CURRENT_STATE(x)    	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
 #define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
 #define R1_APP_CMD		(1 << 5)	/* sr, c */
+#define R1_STATE_IDLE           0
+#define R1_STATE_READY          1
+#define R1_STATE_IDENT          2
+#define R1_STATE_STBY           3
+#define R1_STATE_TRAN		4
+#define R1_STATE_DATA		5
+#define R1_STATE_REV		6
+#define R1_STATE_PRG		7
+#define R1_STATE_DIS		8
+#define R1_STATE_BTST		9
 
 /* These are unpacked versions of the actual responses */
 
@@ -229,13 +277,57 @@
 
 #define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
 #define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
-#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1       */
+#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
 
 #define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
 #define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
 #define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
-#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 */
+#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
+
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BUS_WIDTH	183	/* R/W */
+#define EXT_CSD_HS_TIMING	185	/* R/W */
+#define EXT_CSD_CARD_TYPE	196	/* RO */
+#define EXT_CSD_SEC_CNT		212	/* RO, 4 bytes */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+#define EXT_CSD_CMD_SET_NORMAL		(1<<0)
+#define EXT_CSD_CMD_SET_SECURE		(1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
+
+#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
+
+#define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */
+
+#define EXT_CSD_SEC_CNT_2GB     (2 << (30 - 9))
+
+/*
+ * MMC_SWITCH access modes
+ */
+
+#define MMC_SWITCH_MODE_CMD_SET		0x00	/* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS	0x01	/* Set bits which are 1 in value */
+#define MMC_SWITCH_MODE_CLEAR_BITS	0x02	/* Clear bits which are 1 in value */
+#define MMC_SWITCH_MODE_WRITE_BYTE	0x03	/* Set target to value */
+
+/*
+ * SCR field definitions
+ */
 
+#define SCR_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.01 */
+#define SCR_SPEC_VER_1      1           /* Implements system specification 1.10 */
+#define SCR_SPEC_VER_2      2           /* Implements system specification 2.00 */
 
 /*
  * SD bus widths
--- kernel-source-2.6.16-2.6.16.rel/include/linux/mmc/mmc.h	2006-11-28 14:17:05.000000000 +0100
+++ kernel-source-2.6.16-2.6.16.my/include/linux/mmc/mmc.h	2007-12-07 20:19:30.000000000 +0100
@@ -43,6 +43,7 @@
 #define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
 #define MMC_RSP_R3	(MMC_RSP_PRESENT)
 #define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC)
+#define MMC_RSP_R7	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
 
 #define mmc_resp_type(cmd)	((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
 
@@ -68,7 +69,6 @@
 struct mmc_data {
 	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
 	unsigned int		timeout_clks;	/* data timeout (in clocks) */
-	unsigned int		blksz_bits;	/* data block size */
 	unsigned int		blksz;		/* data block size */
 	unsigned int		blocks;		/* number of blocks */
 	unsigned int		error;		/* data error */
@@ -105,6 +105,8 @@
 extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
 	struct mmc_command *, int);
 
+extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int);
+
 extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
 
 static inline void mmc_claim_host(struct mmc_host *host)
--- kernel-source-2.6.16-2.6.16.rel/drivers/mmc/mmc_block.c	2007-08-22 10:44:38.000000000 +0200
+++ kernel-source-2.6.16-2.6.16.my/drivers/mmc/mmc_block.c	2007-12-07 21:55:38.000000000 +0100
@@ -29,10 +29,12 @@
 #include <linux/blkdev.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/mutex.h>
+#include <linux/scatterlist.h>
 #include <linux/delay.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -82,7 +84,6 @@
 	md->usage--;
 	if (md->usage == 0) {
 		put_disk(md->disk);
-		mmc_cleanup_queue(&md->queue);
 		kfree(md);
 	}
 	mutex_unlock(&open_lock);
@@ -154,56 +155,152 @@
 	return stat;
 }
 
+static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
+{
+	int err;
+	u32 blocks;
+
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+
+	struct scatterlist sg;
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_APP_CMD;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, 0);
+	if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD))
+		return (u32)-1;
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	mmc_set_data_timeout(&data, card, 0);
+
+	data.blksz = 4;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	sg_init_one(&sg, &blocks, 4);
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE)
+		return (u32)-1;
+
+	blocks = ntohl(blocks);
+
+	return blocks;
+}
+
+static int mmc_blk_configure_xfer(struct mmc_card *card,
+				  struct mmc_blk_request *brq,
+				  struct request *req)
+{
+	u32 readcmd, writecmd;
+
+	if (rq_data_dir(req) != READ &&
+	    !(card->host->caps & MMC_CAP_MULTIWRITE) &&
+	    !mmc_card_sd(card))
+		brq->data.blocks = 1;
+
+	if (brq->data.blocks > 1) {
+		/* MMC cards behave better (at least with write operations)
+		 * if we specify the block count in advance. */
+		if (!mmc_card_sd(card)) {
+			struct mmc_command cmd;
+			int err;
+
+			cmd.opcode = MMC_SET_BLOCK_COUNT;
+			cmd.arg = brq->data.blocks;
+			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+			err = mmc_wait_for_cmd(card->host, &cmd, 5);
+			if (err) {
+				if (printk_ratelimit())
+					printk(KERN_WARNING "%s: error %d setting block count\n",
+					       req->rq_disk->disk_name, cmd.error);
+				/* Fall back to single-block transfer */
+				brq->data.blocks = 1;
+			}
+		} else
+			brq->mrq.stop = &brq->stop;
+	}
+
+	if (brq->data.blocks > 1) {
+		brq->data.flags |= MMC_DATA_MULTI;
+		readcmd = MMC_READ_MULTIPLE_BLOCK;
+		writecmd = MMC_WRITE_MULTIPLE_BLOCK;
+	} else {
+		readcmd = MMC_READ_SINGLE_BLOCK;
+		writecmd = MMC_WRITE_BLOCK;
+	}
+
+	if (rq_data_dir(req) == READ) {
+		brq->cmd.opcode = readcmd;
+		brq->data.flags |= MMC_DATA_READ;
+	} else {
+		brq->cmd.opcode = writecmd;
+		brq->data.flags |= MMC_DATA_WRITE;
+	}
+
+	return 0;
+}
+
 static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 {
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
-	int ret;
+	struct mmc_blk_request brq;
+	int ret = 1;
 
 	if (mmc_card_claim_host(card))
-		goto cmd_err;
+		goto flush_queue;
 
 	do {
-		struct mmc_blk_request brq;
 		struct mmc_command cmd;
-		int loop_count = 0, poll_count = 0;
 
 		memset(&brq, 0, sizeof(struct mmc_blk_request));
 		brq.mrq.cmd = &brq.cmd;
 		brq.mrq.data = &brq.data;
 
-		brq.cmd.arg = req->sector << 9;
+		brq.cmd.arg = req->sector;
+		if (!mmc_card_blockaddr(card))
+			brq.cmd.arg <<= 9;
 		brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-		brq.data.timeout_ns = card->csd.tacc_ns * 10;
-		brq.data.timeout_clks = card->csd.tacc_clks * 10;
-		brq.data.blksz_bits = md->block_bits;
 		brq.data.blksz = 1 << md->block_bits;
-		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
 		brq.stop.opcode = MMC_STOP_TRANSMISSION;
 		brq.stop.arg = 0;
 		brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
+		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
+		if (brq.data.blocks > card->host->max_blk_count)
+			brq.data.blocks = card->host->max_blk_count;
 
-		if (rq_data_dir(req) == READ) {
-			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
-			brq.data.flags |= MMC_DATA_READ;
-		} else {
-			brq.cmd.opcode = MMC_WRITE_BLOCK;
-			brq.data.flags |= MMC_DATA_WRITE;
-			brq.data.blocks = 1;
-
-			/*
-			 * Scale up the timeout by the r2w factor
-			 */
-			brq.data.timeout_ns <<= card->csd.r2w_factor;
-			brq.data.timeout_clks <<= card->csd.r2w_factor;
-		}
+		mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
 
-		if (brq.data.blocks > 1) {
-			brq.data.flags |= MMC_DATA_MULTI;
-			brq.mrq.stop = &brq.stop;
-		} else {
-			brq.mrq.stop = NULL;
-		}
+		/*
+		 * If the host doesn't support multiple block writes, force
+		 * block writes to single block. SD cards are excepted from
+		 * this rule as they support querying the number of
+		 * successfully written sectors.
+		 */
+		if (mmc_blk_configure_xfer(card, &brq, req) < 0)
+			goto cmd_err;
 
 		brq.data.sg = mq->sg;
 		brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
@@ -227,38 +324,29 @@
 			goto cmd_err;
 		}
 
-		do {
-			int err;
-
-			cmd.opcode = MMC_SEND_STATUS;
-			cmd.arg = card->rca << 16;
-			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-			err = mmc_wait_for_cmd(card->host, &cmd, 5);
-			if (err) {
-				printk(KERN_ERR "%s: error %d requesting status\n",
-				       req->rq_disk->disk_name, err);
-				goto cmd_err;
-			}
-			poll_count++;
-			if (poll_count >= 100) {
-				loop_count++;
-				if (loop_count >= 100) {
-					printk(KERN_ERR "%s: card failed to become ready\n",
-					       req->rq_disk->disk_name);
+		if (rq_data_dir(req) != READ) {
+			do {
+				int err;
+
+				cmd.opcode = MMC_SEND_STATUS;
+				cmd.arg = card->rca << 16;
+				cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+				err = mmc_wait_for_cmd(card->host, &cmd, 5);
+				if (err) {
+					printk(KERN_ERR "%s: error %d requesting status\n",
+					       req->rq_disk->disk_name, err);
 					goto cmd_err;
 				}
-				msleep(5);
-				poll_count = 0;
-			}
-		} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
+			} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
 
 #if 0
-		if (cmd.resp[0] & ~0x00000900)
-			printk(KERN_ERR "%s: status = %08x\n",
-			       req->rq_disk->disk_name, cmd.resp[0]);
-		if (mmc_decode_status(cmd.resp))
-			goto cmd_err;
+			if (cmd.resp[0] & ~0x00000900)
+				printk(KERN_ERR "%s: status = %08x\n",
+				       req->rq_disk->disk_name, cmd.resp[0]);
+			if (mmc_decode_status(cmd.resp))
+				goto cmd_err;
 #endif
+		}
 
 		/*
 		 * A block was successfully transferred.
@@ -281,19 +369,46 @@
 	return 1;
 
  cmd_err:
+ 	/*
+ 	 * If this is an SD card and we're writing, we can first
+ 	 * mark the known good sectors as ok.
+ 	 *
+	 * If the card is not SD, we can still ok written sectors
+	 * if the controller can do proper error reporting.
+	 *
+	 * For reads we just fail the entire chunk as that should
+	 * be safe in all cases.
+	 */
+ 	if (rq_data_dir(req) != READ && mmc_card_sd(card)) {
+		u32 blocks;
+		unsigned int bytes;
+
+		blocks = mmc_sd_num_wr_blocks(card);
+		if (blocks != (u32)-1) {
+			if (card->csd.write_partial)
+				bytes = blocks << md->block_bits;
+			else
+				bytes = blocks << 9;
+			spin_lock_irq(&md->lock);
+			ret = end_that_request_chunk(req, 1, bytes);
+			spin_unlock_irq(&md->lock);
+		}
+	} else if (rq_data_dir(req) != READ &&
+		   (card->host->caps & MMC_CAP_MULTIWRITE)) {
+		spin_lock_irq(&md->lock);
+		ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);
+		spin_unlock_irq(&md->lock);
+	}
+
+flush_queue:
+
 	mmc_card_release_host(card);
 
-	/*
-	 * This is a little draconian, but until we get proper
-	 * error handling sorted out here, its the best we can
-	 * do - especially as some hosts have no idea how much
-	 * data was transferred before the error occurred.
-	 */
 	spin_lock_irq(&md->lock);
-	do {
+	while (ret) {
 		ret = end_that_request_chunk(req, 0,
 				req->current_nr_sectors << 9);
-	} while (ret);
+	}
 
 	add_disk_randomness(req->rq_disk);
 	blkdev_dequeue_request(req);
@@ -385,11 +500,20 @@
 
 	blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
 
-	/*
-	 * The CSD capacity field is in units of read_blkbits.
-	 * set_capacity takes units of 512 bytes.
-	 */
-	set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
+	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
+		/*
+		 * The EXT_CSD sector count is in number or 512 byte
+		 * sectors.
+		 */
+		set_capacity(md->disk, card->ext_csd.sectors);
+	} else {
+		/*
+		 * The CSD capacity field is in units of read_blkbits.
+		 * set_capacity takes units of 512 bytes.
+		 */
+		set_capacity(md->disk,
+			card->csd.capacity << (card->csd.read_blkbits - 9));
+	}
 	return md;
 
  err_putdisk:
@@ -406,6 +530,10 @@
 	struct mmc_command cmd;
 	int err;
 
+	/* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
+	if (mmc_card_blockaddr(card))
+		return 0;
+
 	mmc_card_claim_host(card);
 	cmd.opcode = MMC_SET_BLOCKLEN;
 	cmd.arg = 1 << md->block_bits;
@@ -463,12 +591,11 @@
 	if (md) {
 		int devidx;
 
+		/* Stop new requests from getting into the queue */
 		del_gendisk(md->disk);
 
-		/*
-		 * I think this is needed.
-		 */
-		md->disk->queue = NULL;
+		/* Then flush out any already in there */
+		mmc_cleanup_queue(&md->queue);
 
 		devidx = md->disk->first_minor >> MMC_SHIFT;
 		__clear_bit(devidx, dev_use);
--- kernel-source-2.6.16-2.6.16.rel/drivers/mmc/mmc.c	2007-08-22 10:44:38.000000000 +0200
+++ kernel-source-2.6.16-2.6.16.my/drivers/mmc/mmc.c	2007-12-08 21:48:13.000000000 +0100
@@ -4,12 +4,12 @@
  *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
  *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
  *  SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
+ *  MMCv4 support Copyright (C) 2006 Philip Langdale, 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 version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -57,6 +57,23 @@
 	35,	40,	45,	50,	55,	60,	70,	80,
 };
 
+static void mmc_idle_work(void *data);
+static inline void mmc_set_ios(struct mmc_host *host);
+
+
+static void mmc_card_watch_state(struct mmc_host *host, struct mmc_command *cmd)
+{
+	struct mmc_card *card = host->card_selected;
+
+	if (!host->claimed || card == NULL || card == (void *)-1)
+		return;
+
+	if (mmc_resp_type(cmd) == MMC_RSP_R1) {
+		card->rq_state = R1_CURRENT_STATE(cmd->resp[0]);
+		mod_timer(&host->idle_timer,
+			  jiffies + host->idle_delay);
+	}
+}
 
 /**
  *	mmc_request_done - finish processing an MMC request
@@ -82,6 +99,9 @@
 		cmd->error = 0;
 		host->ops->request(host, mrq);
 	} else if (mrq->done) {
+		if (host->caps & MMC_CAP_STANDBY)
+			mmc_card_watch_state(host, cmd);
+
 		mrq->done(mrq);
 	}
 }
@@ -103,11 +123,16 @@
 		 mmc_hostname(host), mrq->cmd->opcode,
 		 mrq->cmd->arg, mrq->cmd->flags);
 
-	WARN_ON(host->card_busy == NULL);
+	WARN_ON(!host->claimed);
 
 	mrq->cmd->error = 0;
 	mrq->cmd->mrq = mrq;
 	if (mrq->data) {
+		BUG_ON(mrq->data->blksz > host->max_blk_size);
+		BUG_ON(mrq->data->blocks > host->max_blk_count);
+		BUG_ON(mrq->data->blocks * mrq->data->blksz >
+			host->max_req_size);
+
 		mrq->cmd->data = mrq->data;
 		mrq->data->error = 0;
 		mrq->data->mrq = mrq;
@@ -117,6 +142,12 @@
 			mrq->stop->mrq = mrq;
 		}
 	}
+
+	if (host->ios.power_mode != MMC_POWER_ON) {
+		host->ios.power_mode = MMC_POWER_ON;
+		mmc_set_ios(host);
+	}
+
 	host->ops->request(host, mrq);
 }
 
@@ -157,7 +188,7 @@
 {
 	struct mmc_request mrq;
 
-	BUG_ON(host->card_busy == NULL);
+	BUG_ON(!host->claimed);
 
 	memset(&mrq, 0, sizeof(struct mmc_request));
 
@@ -195,7 +226,7 @@
 
 	int i, err;
 
-	BUG_ON(host->card_busy == NULL);
+	BUG_ON(!host->claimed);
 	BUG_ON(retries < 0);
 
 	err = MMC_ERR_INVALID;
@@ -248,6 +279,58 @@
 
 EXPORT_SYMBOL(mmc_wait_for_app_cmd);
 
+/**
+ *	mmc_set_data_timeout - set the timeout for a data command
+ *	@data: data phase for command
+ *	@card: the MMC card associated with the data transfer
+ *	@write: flag to differentiate reads from writes
+ */
+void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
+			  int write)
+{
+	unsigned int mult;
+
+	/*
+	 * SD cards use a 100 multiplier rather than 10
+	 */
+	mult = mmc_card_sd(card) ? 100 : 10;
+
+	/*
+	 * Scale up the multiplier (and therefore the timeout) by
+	 * the r2w factor for writes.
+	 */
+	if (write)
+		mult <<= card->csd.r2w_factor;
+
+	data->timeout_ns = card->csd.tacc_ns * mult;
+	data->timeout_clks = card->csd.tacc_clks * mult;
+
+	/*
+	 * SD cards also have an upper limit on the timeout.
+	 */
+	if (mmc_card_sd(card)) {
+		unsigned int timeout_us, limit_us;
+
+		timeout_us = data->timeout_ns / 1000;
+		timeout_us += data->timeout_clks * 1000 /
+			(card->host->ios.clock / 1000);
+
+		if (write)
+			limit_us = 250000;
+		else
+			limit_us = 100000;
+
+		/*
+		 * SDHC cards always use these fixed values.
+		 */
+		if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
+			data->timeout_ns = limit_us * 1000;
+			data->timeout_clks = 0;
+		}
+	}
+}
+EXPORT_SYMBOL(mmc_set_data_timeout);
+
 static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);
 
 /**
@@ -271,14 +354,14 @@
 	spin_lock_irqsave(&host->lock, flags);
 	while (1) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (host->card_busy == NULL)
+		if (!host->claimed)
 			break;
 		spin_unlock_irqrestore(&host->lock, flags);
 		schedule();
 		spin_lock_irqsave(&host->lock, flags);
 	}
 	set_current_state(TASK_RUNNING);
-	host->card_busy = card;
+	host->claimed = 1;
 	spin_unlock_irqrestore(&host->lock, flags);
 	remove_wait_queue(&host->wq, &wait);
 
@@ -304,10 +387,10 @@
 {
 	unsigned long flags;
 
-	BUG_ON(host->card_busy == NULL);
+	BUG_ON(!host->claimed);
 
 	spin_lock_irqsave(&host->lock, flags);
-	host->card_busy = NULL;
+	host->claimed = 0;
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	wake_up(&host->wq);
@@ -319,11 +402,12 @@
 {
 	struct mmc_ios *ios = &host->ios;
 
-	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
+	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
+		"width %u timing %u\n",
 		 mmc_hostname(host), ios->clock, ios->bus_mode,
 		 ios->power_mode, ios->chip_select, ios->vdd,
-		 ios->bus_width);
-	
+		 ios->bus_width, ios->timing);
+
 	host->ops->set_ios(host, ios);
 }
 
@@ -332,7 +416,7 @@
 	int err;
 	struct mmc_command cmd;
 
-	BUG_ON(host->card_busy == NULL);
+	BUG_ON(!host->claimed);
 
 	if (host->card_selected == card)
 		return MMC_ERR_NONE;
@@ -348,23 +432,23 @@
 		return err;
 
 	/*
-	 * Default bus width is 1 bit.
-	 */
-	host->ios.bus_width = MMC_BUS_WIDTH_1;
-
-	/*
-	 * We can only change the bus width of the selected
-	 * card so therefore we have to put the handling
+	 * We can only change the bus width of SD cards when
+	 * they are selected so we have to put the handling
 	 * here.
+	 *
+	 * The card is in 1 bit mode by default so
+	 * we only need to change if it supports the
+	 * wider version.
 	 */
-	if (host->caps & MMC_CAP_4_BIT_DATA) {
+	if (mmc_card_sd(card) &&
+		(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+
 		/*
-		 * The card is in 1 bit mode by default so
-		 * we only need to change if it supports the
-		 * wider version.
-		 */
-		if (mmc_card_sd(card) &&
-			(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+		* Default bus width is 1 bit.
+		*/
+		host->ios.bus_width = MMC_BUS_WIDTH_1;
+
+		if (host->caps & MMC_CAP_4_BIT_DATA) {
 			struct mmc_command cmd;
 			cmd.opcode = SD_APP_SET_BUS_WIDTH;
 			cmd.arg = SD_BUS_WIDTH_4;
@@ -427,7 +511,7 @@
 	if (bit) {
 		bit -= 1;
 
-		ocr = 3 << bit;
+		ocr &= 3 << bit;
 
 		host->ios.vdd = bit;
 		mmc_set_ios(host);
@@ -539,34 +623,65 @@
 
 	if (mmc_card_sd(card)) {
 		csd_struct = UNSTUFF_BITS(resp, 126, 2);
-		if (csd_struct != 0) {
+
+		switch (csd_struct) {
+		case 0:
+			m = UNSTUFF_BITS(resp, 115, 4);
+			e = UNSTUFF_BITS(resp, 112, 3);
+			csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+			csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+			m = UNSTUFF_BITS(resp, 99, 4);
+			e = UNSTUFF_BITS(resp, 96, 3);
+			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+			e = UNSTUFF_BITS(resp, 47, 3);
+			m = UNSTUFF_BITS(resp, 62, 12);
+			csd->capacity	  = (1 + m) << (e + 2);
+
+			csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+			csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+			csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+			csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+			csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+			csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+			csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+			break;
+		case 1:
+			/*
+			 * This is a block-addressed SDHC card. Most
+			 * interesting fields are unused and have fixed
+			 * values. To avoid getting tripped by buggy cards,
+			 * we assume those fixed values ourselves.
+			 */
+			mmc_card_set_blockaddr(card);
+
+			csd->tacc_ns	 = 0; /* Unused */
+			csd->tacc_clks	 = 0; /* Unused */
+
+			m = UNSTUFF_BITS(resp, 99, 4);
+			e = UNSTUFF_BITS(resp, 96, 3);
+			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+			m = UNSTUFF_BITS(resp, 48, 22);
+			csd->capacity     = (1 + m) << 10;
+
+			csd->read_blkbits = 9;
+			csd->read_partial = 0;
+			csd->write_misalign = 0;
+			csd->read_misalign = 0;
+			csd->r2w_factor = 4; /* Unused */
+			csd->write_blkbits = 9;
+			csd->write_partial = 0;
+			break;
+		default:
 			printk("%s: unrecognised CSD structure version %d\n",
 				mmc_hostname(card->host), csd_struct);
 			mmc_card_set_bad(card);
 			return;
 		}
-
-		m = UNSTUFF_BITS(resp, 115, 4);
-		e = UNSTUFF_BITS(resp, 112, 3);
-		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-		m = UNSTUFF_BITS(resp, 99, 4);
-		e = UNSTUFF_BITS(resp, 96, 3);
-		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-
-		e = UNSTUFF_BITS(resp, 47, 3);
-		m = UNSTUFF_BITS(resp, 62, 12);
-		csd->capacity	  = (1 + m) << (e + 2);
-
-		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
 	} else {
 		/*
 		 * We only understand CSD structure v1.1 and v1.2.
@@ -721,6 +836,7 @@
 	host->ios.chip_select = MMC_CS_DONTCARE;
 	host->ios.power_mode = MMC_POWER_UP;
 	host->ios.bus_width = MMC_BUS_WIDTH_1;
+	host->ios.timing = MMC_TIMING_LEGACY;
 	mmc_set_ios(host);
 
 	mmc_delay(1);
@@ -740,6 +856,7 @@
 	host->ios.chip_select = MMC_CS_DONTCARE;
 	host->ios.power_mode = MMC_POWER_OFF;
 	host->ios.bus_width = MMC_BUS_WIDTH_1;
+	host->ios.timing = MMC_TIMING_LEGACY;
 	mmc_set_ios(host);
 }
 
@@ -799,6 +916,41 @@
 	return err;
 }
 
+static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
+{
+	struct mmc_command cmd;
+	int err, sd2;
+	static const u8 test_pattern = 0xAA;
+
+	/*
+	* To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
+	* before SD_APP_OP_COND. This command will harmlessly fail for
+	* SD 1.0 cards.
+	*/
+	cmd.opcode = SD_SEND_IF_COND;
+	cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
+	cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+	if (err == MMC_ERR_NONE) {
+		if ((cmd.resp[0] & 0xFF) == test_pattern) {
+			sd2 = 1;
+		} else {
+			sd2 = 0;
+			err = MMC_ERR_FAILED;
+		}
+	} else {
+		/*
+		 * Treat errors as SD 1.0 card.
+		 */
+		sd2 = 0;
+		err = MMC_ERR_NONE;
+	}
+	if (rsd2)
+		*rsd2 = sd2;
+	return err;
+}
+
 /*
  * Discover cards by requesting their CID.  If this command
  * times out, it is not an error; there are no further cards
@@ -905,7 +1057,7 @@
 	}
 }
 
-static void mmc_read_scrs(struct mmc_host *host)
+static void mmc_process_ext_csds(struct mmc_host *host)
 {
 	int err;
 	struct mmc_card *card;
@@ -916,6 +1068,157 @@
 
 	struct scatterlist sg;
 
+	/*
+	 * As the ext_csd is so large and mostly unused, we don't store the
+	 * raw block in mmc_card.
+	 */
+	u8 *ext_csd;
+	ext_csd = kmalloc(512, GFP_KERNEL);
+	if (!ext_csd) {
+		printk("%s: could not allocate a buffer to receive the ext_csd."
+		       "mmc v4 cards will be treated as v3.\n",
+			mmc_hostname(host));
+		return;
+	}
+
+	list_for_each_entry(card, &host->cards, node) {
+		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+			continue;
+		if (mmc_card_sd(card))
+			continue;
+		if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+			continue;
+
+		err = mmc_select_card(host, card);
+		if (err != MMC_ERR_NONE) {
+			mmc_card_set_dead(card);
+			continue;
+		}
+
+		memset(&cmd, 0, sizeof(struct mmc_command));
+
+		cmd.opcode = MMC_SEND_EXT_CSD;
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+		memset(&data, 0, sizeof(struct mmc_data));
+
+		mmc_set_data_timeout(&data, card, 0);
+
+		data.blksz = 512;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+		data.sg = &sg;
+		data.sg_len = 1;
+
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		mrq.cmd = &cmd;
+		mrq.data = &data;
+
+		sg_init_one(&sg, ext_csd, 512);
+
+		mmc_wait_for_req(host, &mrq);
+
+		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+			if (card->csd.capacity == (4096 * 512)) {
+				printk(KERN_ERR "%s: unable to read EXT_CSD "
+					"on a possible high capacity card. "
+					"Card will be ignored.\n",
+					mmc_hostname(card->host));
+				mmc_card_set_dead(card);
+			} else {
+				printk(KERN_WARNING "%s: unable to read "
+					"EXT_CSD, performance might "
+					"suffer.\n",
+					mmc_hostname(card->host));
+			}
+			continue;
+		}
+
+		card->ext_csd.sectors =
+			ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
+			ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
+			ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
+			ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
+		if (card->ext_csd.sectors > EXT_CSD_SEC_CNT_2GB)
+			mmc_card_set_blockaddr(card);
+
+		switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+		case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
+			card->ext_csd.hs_max_dtr = 52000000;
+			break;
+		case EXT_CSD_CARD_TYPE_26:
+			card->ext_csd.hs_max_dtr = 26000000;
+			break;
+		default:
+			/* MMC v4 spec says this cannot happen */
+			printk("%s: card is mmc v4 but doesn't support "
+			       "any high-speed modes.\n",
+				mmc_hostname(card->host));
+			continue;
+		}
+
+		if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
+			/* Activate highspeed support. */
+			cmd.opcode = MMC_SWITCH;
+			cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+				  (EXT_CSD_HS_TIMING << 16) |
+				  (1 << 8) |
+				  EXT_CSD_CMD_SET_NORMAL;
+			cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+			if (err != MMC_ERR_NONE) {
+				printk("%s: failed to switch card to mmc v4 "
+				       "high-speed mode.\n",
+				       mmc_hostname(card->host));
+				continue;
+			}
+
+			mmc_card_set_highspeed(card);
+
+			host->ios.timing = MMC_TIMING_MMC_HS;
+			mmc_set_ios(host);
+		}
+
+		/* Check for host support for wide-bus modes. */
+		if (host->caps & MMC_CAP_4_BIT_DATA) {
+			/* Activate 4-bit support. */
+			cmd.opcode = MMC_SWITCH;
+			cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+				  (EXT_CSD_BUS_WIDTH << 16) |
+				  (EXT_CSD_BUS_WIDTH_4 << 8) |
+				  EXT_CSD_CMD_SET_NORMAL;
+			cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+			if (err != MMC_ERR_NONE) {
+				printk("%s: failed to switch card to "
+				       "mmc v4 4-bit bus mode.\n",
+				       mmc_hostname(card->host));
+				continue;
+			}
+
+			host->ios.bus_width = MMC_BUS_WIDTH_4;
+			mmc_set_ios(host);
+		}
+	}
+
+	kfree(ext_csd);
+
+	mmc_deselect_cards(host);
+}
+
+static void mmc_read_scrs(struct mmc_host *host)
+{
+	int err;
+	struct mmc_card *card;
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+
 	list_for_each_entry(card, &host->cards, node) {
 		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
 			continue;
@@ -948,9 +1251,8 @@
 
 		memset(&data, 0, sizeof(struct mmc_data));
 
-		data.timeout_ns = card->csd.tacc_ns * 10;
-		data.timeout_clks = card->csd.tacc_clks * 10;
-		data.blksz_bits = 3;
+		mmc_set_data_timeout(&data, card, 0);
+
 		data.blksz = 1 << 3;
 		data.blocks = 1;
 		data.flags = MMC_DATA_READ;
@@ -980,14 +1282,137 @@
 	mmc_deselect_cards(host);
 }
 
+static void mmc_read_switch_caps(struct mmc_host *host)
+{
+	int err;
+	struct mmc_card *card;
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	unsigned char *status;
+	struct scatterlist sg;
+
+	if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
+		return;
+
+	status = kmalloc(64, GFP_KERNEL);
+	if (!status) {
+		printk(KERN_WARNING "%s: Unable to allocate buffer for "
+			"reading switch capabilities.\n",
+			mmc_hostname(host));
+		return;
+	}
+
+	list_for_each_entry(card, &host->cards, node) {
+		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+			continue;
+		if (!mmc_card_sd(card))
+			continue;
+		if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+			continue;
+
+		err = mmc_select_card(host, card);
+		if (err != MMC_ERR_NONE) {
+			mmc_card_set_dead(card);
+			continue;
+		}
+
+		memset(&cmd, 0, sizeof(struct mmc_command));
+
+		cmd.opcode = SD_SWITCH;
+		cmd.arg = 0x00FFFFF1;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+		memset(&data, 0, sizeof(struct mmc_data));
+
+		mmc_set_data_timeout(&data, card, 0);
+
+		data.blksz = 64;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+		data.sg = &sg;
+		data.sg_len = 1;
+
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		mrq.cmd = &cmd;
+		mrq.data = &data;
+
+		sg_init_one(&sg, status, 64);
+
+		mmc_wait_for_req(host, &mrq);
+
+		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+			printk("%s: unable to read switch capabilities, "
+				"performance might suffer.\n",
+				mmc_hostname(card->host));
+			continue;
+		}
+
+		if (status[13] & 0x02)
+			card->sw_caps.hs_max_dtr = 50000000;
+
+		memset(&cmd, 0, sizeof(struct mmc_command));
+
+		cmd.opcode = SD_SWITCH;
+		cmd.arg = 0x80FFFFF1;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+		memset(&data, 0, sizeof(struct mmc_data));
+
+		mmc_set_data_timeout(&data, card, 0);
+
+		data.blksz = 64;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+		data.sg = &sg;
+		data.sg_len = 1;
+
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		mrq.cmd = &cmd;
+		mrq.data = &data;
+
+		sg_init_one(&sg, status, 64);
+
+		mmc_wait_for_req(host, &mrq);
+
+		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE ||
+			(status[16] & 0xF) != 1) {
+			printk(KERN_WARNING "%s: Problem switching card "
+				"into high-speed mode!\n",
+				mmc_hostname(host));
+			continue;
+		}
+
+		mmc_card_set_highspeed(card);
+
+		host->ios.timing = MMC_TIMING_SD_HS;
+		mmc_set_ios(host);
+	}
+
+	kfree(status);
+
+	mmc_deselect_cards(host);
+}
+
 static unsigned int mmc_calculate_clock(struct mmc_host *host)
 {
 	struct mmc_card *card;
 	unsigned int max_dtr = host->f_max;
 
 	list_for_each_entry(card, &host->cards, node)
-		if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)
-			max_dtr = card->csd.max_dtr;
+		if (!mmc_card_dead(card) && !mmc_card_bad(card)) {
+			if (mmc_card_highspeed(card) && mmc_card_sd(card)) {
+				if (max_dtr > card->sw_caps.hs_max_dtr)
+					max_dtr = card->sw_caps.hs_max_dtr;
+			} else if (mmc_card_highspeed(card) && !mmc_card_sd(card)) {
+				if (max_dtr > card->ext_csd.hs_max_dtr)
+					max_dtr = card->ext_csd.hs_max_dtr;
+			} else if (max_dtr > card->csd.max_dtr) {
+				max_dtr = card->csd.max_dtr;
+			}
+		}
 
 	pr_debug("%s: selected %d.%03dMHz transfer rate\n",
 		 mmc_hostname(host),
@@ -1029,7 +1454,8 @@
 
 static void mmc_setup(struct mmc_host *host)
 {
-	if (host->ios.power_mode != MMC_POWER_ON) {
+	if (host->ios.power_mode != MMC_POWER_ON &&
+	    host->ios.power_mode != MMC_POWER_STANDBY) {
 		int err;
 		u32 ocr;
 
@@ -1038,6 +1464,10 @@
 		mmc_power_up(host);
 		mmc_idle_cards(host);
 
+		err = mmc_send_if_cond(host, host->ocr_avail, NULL);
+		if (err != MMC_ERR_NONE) {
+			return;
+		}
 		err = mmc_send_app_op_cond(host, 0, &ocr);
 
 		/*
@@ -1090,10 +1520,22 @@
 	 * all get the idea that they should be ready for CMD2.
 	 * (My SanDisk card seems to need this.)
 	 */
-	if (host->mode == MMC_MODE_SD)
-		mmc_send_app_op_cond(host, host->ocr, NULL);
-	else
-		mmc_send_op_cond(host, host->ocr, NULL);
+	if (host->mode == MMC_MODE_SD) {
+		int err, sd2;
+		err = mmc_send_if_cond(host, host->ocr, &sd2);
+		if (err == MMC_ERR_NONE) {
+			/*
+			* 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.
+			*/
+			mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
+		}
+	} else {
+		/* The extra bit indicates that we support high capacity */
+		mmc_send_op_cond(host, host->ocr | (1 << 30), NULL);
+	}
 
 	mmc_discover_cards(host);
 
@@ -1103,20 +1545,85 @@
 	host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
 	mmc_set_ios(host);
 
-	/*
-	 * Some already detected cards get confused in the card identification
-	 * mode and futher commands can fail.  Doing an extra status inquiry
-	 * after the identification mode seems to get cards back to their
-	 * senses.
-	 */
-	mmc_check_cards(host);
-
 	mmc_read_csds(host);
 
-	if (host->mode == MMC_MODE_SD)
+	if (host->mode == MMC_MODE_SD) {
 		mmc_read_scrs(host);
+		mmc_read_switch_caps(host);
+	} else
+		mmc_process_ext_csds(host);
 }
 
+/**
+ *	mmc_idle_timer -
+ *	@host: MMC host which completed request
+ *	@mrq: MMC request which request
+ *
+ *      MMC idle timer is set to run after any read or write request
+ *      to put host standby mode once the cards are idle
+ */
+static void
+mmc_idle_timer(unsigned long data)
+{
+	struct mmc_host *host = (struct mmc_host *)data;
+	schedule_work(&host->idle_work);
+}
+
+/**
+ *      mmc_idle_work - put host into standby mode
+ *	@host: MMC host which completed request a while ago
+ *
+ *
+ */
+static void mmc_idle_work(void *data)
+{
+	struct mmc_host *host = data;
+	struct list_head *l, *n;
+	int busy;
+
+	mmc_claim_host(host);
+
+	if (host->ios.power_mode != MMC_POWER_ON &&
+	    host->ios.power_mode != MMC_POWER_STANDBY)
+		goto exit;
+
+	mmc_deselect_cards(host);
+	busy = 0;
+	list_for_each_safe(l, n, &host->cards) {
+		struct mmc_card *card = mmc_list_to_card(l);
+		struct mmc_command cmd;
+		int err;
+
+		if (mmc_card_dead(card) ||
+		    card->rq_state == R1_STATE_TRAN ||
+		    card->rq_state == R1_STATE_STBY)
+			continue;
+
+		cmd.opcode = MMC_SEND_STATUS;
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+		if (err != MMC_ERR_NONE) {
+			mmc_detect_change(host, 0);
+			goto exit;
+		}
+
+		card->rq_state = R1_CURRENT_STATE(cmd.resp[0]);
+		if (card->rq_state != R1_STATE_STBY)
+			busy = 1;
+	}
+
+	if (busy)
+		mod_timer(&host->idle_timer, jiffies + host->idle_delay);
+	else {
+		host->ios.power_mode = MMC_POWER_STANDBY;
+		mmc_set_ios(host);
+	}
+
+exit:
+	mmc_release_host(host);
+}
 
 /**
  *	mmc_detect_change - process change of state on a MMC socket
@@ -1129,9 +1636,9 @@
 void mmc_detect_change(struct mmc_host *host, unsigned long delay)
 {
 	if (delay)
-		schedule_delayed_work(&host->detect, delay);
+		mmc_schedule_delayed_work(&host->detect, delay);
 	else
-		schedule_work(&host->detect);
+		mmc_schedule_work(&host->detect);
 }
 
 EXPORT_SYMBOL(mmc_detect_change);
@@ -1141,14 +1648,18 @@
 {
 	struct mmc_host *host = data;
 	struct list_head *l, *n;
+	unsigned char power_mode;
 
 	mmc_claim_host(host);
 
-	if (host->ios.power_mode == MMC_POWER_ON)
-		mmc_check_cards(host);
+	power_mode = host->ios.power_mode;
 
 	mmc_setup(host);
 
+	if (power_mode == MMC_POWER_ON ||
+	    power_mode == MMC_POWER_STANDBY)
+		mmc_check_cards(host);
+
 	if (!list_empty(&host->cards)) {
 		/*
 		 * (Re-)calculate the fastest clock rate which the
@@ -1209,14 +1720,22 @@
 		INIT_LIST_HEAD(&host->cards);
 		INIT_WORK(&host->detect, mmc_rescan, host);
 
+		init_timer(&host->idle_timer);
+		host->idle_timer.function = mmc_idle_timer;
+		host->idle_timer.data = (unsigned long)host;
+		INIT_WORK(&host->idle_work, mmc_idle_work, host);
+
 		/*
 		 * By default, hosts do not support SGIO or large requests.
 		 * They have to set these according to their abilities.
 		 */
 		host->max_hw_segs = 1;
 		host->max_phys_segs = 1;
-		host->max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
 		host->max_seg_size = PAGE_CACHE_SIZE;
+
+		host->max_req_size = PAGE_CACHE_SIZE;
+		host->max_blk_size = 512;
+		host->max_blk_count = PAGE_CACHE_SIZE / 512;
 	}
 
 	return host;
@@ -1254,6 +1773,7 @@
 {
 	struct list_head *l, *n;
 
+	del_timer_sync(&host->idle_timer);
 	list_for_each_safe(l, n, &host->cards) {
 		struct mmc_card *card = mmc_list_to_card(l);
 
@@ -1274,7 +1794,7 @@
  */
 void mmc_free_host(struct mmc_host *host)
 {
-	flush_scheduled_work();
+	mmc_flush_scheduled_work();
 	mmc_free_host_sysfs(host);
 }
 
@@ -1290,6 +1810,7 @@
 int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
 {
 	mmc_claim_host(host);
+	del_timer_sync(&host->idle_timer);
 	mmc_deselect_cards(host);
 	mmc_power_off(host);
 	mmc_release_host(host);
--- kernel-source-2.6.16-2.6.16.rel/drivers/mmc/mmc.h	2006-11-28 14:17:01.000000000 +0100
+++ kernel-source-2.6.16-2.6.16.my/drivers/mmc/mmc.h	2007-08-29 22:12:20.000000000 +0200
@@ -18,4 +18,8 @@
 int mmc_add_host_sysfs(struct mmc_host *host);
 void mmc_remove_host_sysfs(struct mmc_host *host);
 void mmc_free_host_sysfs(struct mmc_host *host);
+
+int mmc_schedule_work(struct work_struct *work);
+int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay);
+void mmc_flush_scheduled_work(void);
 #endif
--- kernel-source-2.6.16-2.6.16.rel/drivers/mmc/mmc_sysfs.c	2006-11-28 14:17:01.000000000 +0100
+++ kernel-source-2.6.16-2.6.16.my/drivers/mmc/mmc_sysfs.c	2007-08-29 21:48:13.000000000 +0200
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/idr.h>
+#include <linux/workqueue.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -317,10 +318,41 @@
 	class_device_put(&host->class_dev);
 }
 
+static struct workqueue_struct *workqueue;
+
+/*
+ * Internal function. Schedule work in the MMC work queue.
+ */
+int mmc_schedule_work(struct work_struct *work)
+{
+	return queue_work(workqueue, work);
+}
+
+/*
+ * Internal function. Schedule delayed work in the MMC work queue.
+ */
+int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay)
+{
+	return queue_delayed_work(workqueue, work, delay);
+}
+
+/*
+ * Internal function. Flush all scheduled work from the MMC work queue.
+ */
+void mmc_flush_scheduled_work(void)
+{
+	flush_workqueue(workqueue);
+}
 
 static int __init mmc_init(void)
 {
-	int ret = bus_register(&mmc_bus_type);
+	int ret;
+
+	workqueue = create_singlethread_workqueue("kmmcd");
+	if (!workqueue)
+		return -ENOMEM;
+
+	ret = bus_register(&mmc_bus_type);
 	if (ret == 0) {
 		ret = class_register(&mmc_host_class);
 		if (ret)
@@ -333,6 +365,7 @@
 {
 	class_unregister(&mmc_host_class);
 	bus_unregister(&mmc_bus_type);
+	destroy_workqueue(workqueue);
 }
 
 module_init(mmc_init);
--- kernel-source-2.6.16-2.6.16.rel/drivers/mmc/mmc_queue.c	2006-11-28 14:17:01.000000000 +0100
+++ kernel-source-2.6.16-2.6.16.my/drivers/mmc/mmc_queue.c	2007-12-07 22:17:39.000000000 +0100
@@ -41,6 +41,8 @@
 		 * Block I/O requests need translating according
 		 * to the protocol.
 		 */
+		if (!mq)
+			return ret;
 		ret = mq->prep_fn(mq, req);
 	} else {
 		/*
@@ -111,6 +113,19 @@
 static void mmc_request(request_queue_t *q)
 {
 	struct mmc_queue *mq = q->queuedata;
+	struct request *req;
+	int ret;
+
+	if (!mq) {
+		printk(KERN_ERR "MMC: killing requests for dead queue\n");
+		while ((req = elv_next_request(q)) != NULL) {
+			do {
+				ret = end_that_request_chunk(req, 0,
+					req->current_nr_sectors << 9);
+			} while (ret);
+		}
+		return;
+	}
 
 	if (!mq->req)
 		wake_up(&mq->thread_wq);
@@ -140,7 +155,7 @@
 
 	blk_queue_prep_rq(mq->queue, mmc_prep_request);
 	blk_queue_bounce_limit(mq->queue, limit);
-	blk_queue_max_sectors(mq->queue, host->max_sectors);
+	blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
 	blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
 	blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
 	blk_queue_max_segment_size(mq->queue, host->max_seg_size);
@@ -152,7 +167,7 @@
 			 GFP_KERNEL);
 	if (!mq->sg) {
 		ret = -ENOMEM;
-		goto cleanup;
+		goto cleanup_queue;
 	}
 
 	init_completion(&mq->thread_complete);
@@ -167,10 +182,9 @@
 		goto out;
 	}
 
- cleanup:
 	kfree(mq->sg);
 	mq->sg = NULL;
-
+ cleanup_queue:
 	blk_cleanup_queue(mq->queue);
  out:
 	return ret;
@@ -179,6 +193,14 @@
 
 void mmc_cleanup_queue(struct mmc_queue *mq)
 {
+	request_queue_t *q = mq->queue;
+	unsigned long flags;
+
+	/* Mark that we should start throwing out stragglers */
+	spin_lock_irqsave(q->queue_lock, flags);
+	q->queuedata = NULL;
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
 	mq->flags |= MMC_QUEUE_EXIT;
 	wake_up(&mq->thread_wq);
 	wait_for_completion(&mq->thread_complete);
--- kernel-source-2.6.16-2.6.16.rel/drivers/mmc/omap.c	2007-08-22 10:44:38.000000000 +0200
+++ kernel-source-2.6.16-2.6.16.my/drivers/mmc/omap.c	2007-12-08 21:53:54.000000000 +0100
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/media/mmc/omap.c
  *
- *  Copyright (C) 2004 Nokia Corporation
+ *  Copyright (C) 2004, 2007 Nokia Corporation
  *  Written by Tuukka Tikkanen and Juha Yrjölä<juha.yrjola@nokia.com>
  *  Misc hacks here and there by Tony Lindgren <tony@atomide.com>
  *  Other hacks (DMA, SD, etc) by David Brownell
@@ -105,7 +105,7 @@
 	u16			saved_con;
 	u16			bus_mode;
 	unsigned int		fclk_freq;
-	unsigned		powered:1;
+	unsigned		power_mode;
 
 	struct work_struct	cover_work;
 	struct timer_list	cover_timer;
@@ -133,6 +133,9 @@
 	unsigned int		phys_base;
 	int			irq;
 
+	struct work_struct      cmd_abort;
+	struct timer_list       cmd_timer;
+
 	unsigned int		sg_len;
 	int			sg_idx;
 	u16 *			buffer;
@@ -154,10 +157,12 @@
 	wait_queue_head_t	slot_wq;
 	int			nr_slots;
 
+	int			fclk_enabled;
+
         struct omap_mmc_platform_data *pdata;
 };
 
-static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed)
+static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed, int need_clock)
 {
 	struct mmc_omap_host *host = slot->host;
 	unsigned long flags;
@@ -173,13 +178,25 @@
 	host->mmc = slot->mmc;
 	spin_unlock_irqrestore(&host->slot_lock, flags);
 no_claim:
-	clk_enable(host->fclk);
 	if (host->current_slot != slot) {
 		if (host->pdata->switch_slot != NULL)
 			host->pdata->switch_slot(mmc_dev(slot->mmc), slot->id);
 		host->current_slot = slot;
 	}
-	OMAP_MMC_WRITE(host, CON, slot->saved_con);
+
+	if (need_clock) {
+		if (host->fclk_enabled == 0) {
+			host->fclk_enabled = 1;
+			clk_enable(host->fclk);
+		}
+
+		/* Doing the dummy read here seems to work around some bug
+		 * at least in OMAP24xx silicon where the command would not
+		 * start after writing the CMD register. Sigh. */
+		OMAP_MMC_READ(host, CON);
+
+		OMAP_MMC_WRITE(host, CON, slot->saved_con);
+	}
 }
 
 static void mmc_omap_start_request(struct mmc_omap_host *host,
@@ -192,7 +209,7 @@
 	int i;
 
 	BUG_ON(slot == NULL || host->mmc == NULL);
-	clk_disable(host->fclk);
+	OMAP_MMC_WRITE(host, CON, slot->saved_con & 0xFC00);
 
 	spin_lock_irqsave(&host->slot_lock, flags);
 	/* Check for any pending requests */
@@ -209,7 +226,7 @@
 
 		host->mmc = new_slot->mmc;
 		spin_unlock_irqrestore(&host->slot_lock, flags);
-		mmc_omap_select_slot(new_slot, 1);
+		mmc_omap_select_slot(new_slot, 1, 1);
 		rq = new_slot->mrq;
 		new_slot->mrq = NULL;
 		mmc_omap_start_request(host, rq);
@@ -321,6 +338,8 @@
 	if (host->data && !(host->data->flags & MMC_DATA_WRITE))
 		cmdreg |= 1 << 15;
 
+	mod_timer(&host->cmd_timer, jiffies + HZ/2);
+
 	OMAP_MMC_WRITE(host, CTO, 200);
 	OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
 	OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16);
@@ -334,23 +353,30 @@
 }
 
 static void
+mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data,
+		     int abort)
+{
+	enum dma_data_direction dma_data_dir;
+
+	BUG_ON(host->dma_ch < 0);
+	if (abort)
+		omap_stop_dma(host->dma_ch);
+	/* Release DMA channel lazily */
+	mod_timer(&host->dma_timer, jiffies + HZ);
+	if (data->flags & MMC_DATA_WRITE)
+		dma_data_dir = DMA_TO_DEVICE;
+	else
+		dma_data_dir = DMA_FROM_DEVICE;
+	dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
+		     dma_data_dir);
+}
+
+static void
 mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 {
-	if (host->dma_in_use) {
-		enum dma_data_direction dma_data_dir;
+	if (host->dma_in_use)
+		mmc_omap_release_dma(host, data, data->error != MMC_ERR_NONE);
 
-		BUG_ON(host->dma_ch < 0);
-		if (data->error != MMC_ERR_NONE)
-			omap_stop_dma(host->dma_ch);
-		/* Release DMA channel lazily */
-		mod_timer(&host->dma_timer, jiffies + HZ);
-		if (data->flags & MMC_DATA_WRITE)
-			dma_data_dir = DMA_TO_DEVICE;
-		else
-			dma_data_dir = DMA_FROM_DEVICE;
-		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
-			     dma_data_dir);
-	}
 	host->data = NULL;
 	host->sg_len = 0;
 
@@ -373,6 +399,52 @@
 }
 
 static void
+mmc_omap_send_abort(struct mmc_omap_host *host)
+{
+	struct mmc_omap_slot *slot = host->current_slot;
+	unsigned int restarts, passes, timeout;
+	u16 stat = 0;
+
+	/* Sending abort takes 80 clocks. Have some extra and round up */
+	timeout = (120*1000000 + slot->fclk_freq - 1)/slot->fclk_freq;
+	restarts = 0;
+	while(restarts < 10000) {
+		OMAP_MMC_WRITE(host, STAT, 0xFFFF);
+		OMAP_MMC_WRITE(host, CMD, (3 << 12) | (1 << 7));
+
+		passes = 0;
+		while (passes < timeout) {
+			stat = OMAP_MMC_READ(host, STAT);
+			if (stat & OMAP_MMC_STAT_END_OF_CMD)
+				goto out;
+			udelay(1);
+			passes ++;
+		}
+
+		restarts++;
+	}
+out:
+	OMAP_MMC_WRITE(host, STAT, stat);
+}
+
+static void
+mmc_omap_abort_xfer(struct mmc_omap_host *host, struct mmc_data *data)
+{
+	u16 ie;
+
+	if (host->dma_in_use)
+		mmc_omap_release_dma(host, data, 1);
+
+	host->data = NULL;
+	host->sg_len = 0;
+
+	ie = OMAP_MMC_READ(host, IE);
+	OMAP_MMC_WRITE(host, IE, 0);
+	mmc_omap_send_abort(host);
+	OMAP_MMC_WRITE(host, IE, ie);
+}
+
+static void
 mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data)
 {
 	unsigned long flags;
@@ -425,6 +497,8 @@
 {
 	host->cmd = NULL;
 
+	del_timer(&host->cmd_timer);
+
 	if (cmd->flags & MMC_RSP_PRESENT) {
 		if (cmd->flags & MMC_RSP_136) {
 			/* response type 2 */
@@ -451,6 +525,8 @@
 	if (host->data == NULL || cmd->error != MMC_ERR_NONE) {
 		struct mmc_host *mmc;
 
+		if (host->data != NULL)
+			mmc_omap_abort_xfer(host, host->data);
 		host->mrq = NULL;
 		mmc = host->mmc;
 		mmc_omap_release_slot(host->current_slot);
@@ -458,6 +534,46 @@
 	}
 }
 
+/*
+ * Abort stuck command. Can occur when card is removed while it is being
+ * read.
+ */
+static void mmc_omap_abort_command(void *data)
+{
+	struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+	u16 ie;
+
+	ie = OMAP_MMC_READ(host, IE);
+	OMAP_MMC_WRITE(host, IE, 0);
+
+	if (!host->cmd) {
+		OMAP_MMC_WRITE(host, IE, ie);
+		return;
+	}
+
+	dev_dbg(mmc_dev(host->mmc), "Aborting stuck command CMD%d\n",
+		host->cmd->opcode);
+
+	if (host->data && host->dma_in_use)
+		mmc_omap_release_dma(host, host->data, 1);
+
+	host->data = NULL;
+	host->sg_len = 0;
+
+	mmc_omap_send_abort(host);
+	host->cmd->error = MMC_ERR_TIMEOUT;
+	mmc_omap_cmd_done(host, host->cmd);
+	OMAP_MMC_WRITE(host, IE, ie);
+}
+
+static void
+mmc_omap_cmd_timer(unsigned long data)
+{
+	struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+
+	schedule_work(&host->cmd_abort);
+}
+
 /* PIO only */
 static void
 mmc_omap_sg_to_buf(struct mmc_omap_host *host)
@@ -536,10 +652,16 @@
 	transfer_error = 0;
 
 	while ((status = OMAP_MMC_READ(host, STAT)) != 0) {
+		int cmd;
+
 		OMAP_MMC_WRITE(host, STAT, status);
+		if (host->cmd != NULL)
+			cmd = host->cmd->opcode;
+		else
+			cmd = -1;
 #ifdef CONFIG_MMC_DEBUG
-		dev_info(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
-			 status, host->cmd != NULL ? host->cmd->opcode : -1);
+		dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD%d): ",
+			status, cmd);
 		mmc_omap_report_irq(status);
 		printk("\n");
 #endif
@@ -551,12 +673,12 @@
 				mmc_omap_xfer_data(host, 1);
 		}
 
-		if (status & OMAP_MMC_STAT_END_OF_DATA) {
+		if (status & OMAP_MMC_STAT_END_OF_DATA)
 			end_transfer = 1;
-		}
 
 		if (status & OMAP_MMC_STAT_DATA_TOUT) {
-			dev_dbg(mmc_dev(host->mmc), "data timeout\n");
+			dev_err(mmc_dev(host->mmc), "data timeout (CMD%d)\n",
+				cmd);
 			if (host->data) {
 				host->data->error |= MMC_ERR_TIMEOUT;
 				transfer_error = 1;
@@ -566,12 +688,12 @@
 		if (status & OMAP_MMC_STAT_DATA_CRC) {
 			if (host->data) {
 				host->data->error |= MMC_ERR_BADCRC;
-				dev_dbg(mmc_dev(host->mmc),
-					 "data CRC error, bytes left %d\n",
-					host->total_bytes_left);
+				dev_err(mmc_dev(host->mmc),
+					"data CRC error, bytes left %d (CMD%d)\n",
+					host->total_bytes_left, cmd);
 				transfer_error = 1;
 			} else {
-				dev_dbg(mmc_dev(host->mmc), "data CRC error\n");
+				dev_err(mmc_dev(host->mmc), "data CRC error\n");
 			}
 		}
 
@@ -582,8 +704,8 @@
 				    host->cmd->opcode != MMC_SEND_OP_COND &&
 				    host->cmd->opcode != MMC_APP_CMD)
 					dev_err(mmc_dev(host->mmc),
-						"command timeout, CMD %d\n",
-						host->cmd->opcode);
+						"command timeout (CMD%d)\n",
+						cmd);
 				host->cmd->error = MMC_ERR_TIMEOUT;
 				end_command = 1;
 			}
@@ -593,7 +715,7 @@
 			if (host->cmd) {
 				dev_err(mmc_dev(host->mmc),
 					"command CRC error (CMD%d, arg 0x%08x)\n",
-					host->cmd->opcode, host->cmd->arg);
+					cmd, host->cmd->arg);
 				host->cmd->error = MMC_ERR_BADCRC;
 				end_command = 1;
 			} else
@@ -614,8 +736,8 @@
 				}
 			}
 
-			dev_dbg(mmc_dev(host->mmc), "card status error (CMD%d)\n",
-				host->cmd->opcode);
+			dev_err(mmc_dev(host->mmc), "card status error (CMD%d)\n",
+				cmd);
 			if (host->cmd) {
 				host->cmd->error = MMC_ERR_FAILED;
 				end_command = 1;
@@ -636,13 +758,14 @@
 		}
 	}
 
-	if (end_command) {
+	if (end_command)
 		mmc_omap_cmd_done(host, host->cmd);
+	if (host->data != NULL) {
+		if (transfer_error)
+			mmc_omap_xfer_done(host, host->data);
+		else if (end_transfer)
+			mmc_omap_end_of_data(host, host->data);
 	}
-	if (transfer_error)
-		mmc_omap_xfer_done(host, host->data);
-	else if (end_transfer)
-		mmc_omap_end_of_data(host, host->data);
 
 	return IRQ_HANDLED;
 }
@@ -653,6 +776,10 @@
 
 	BUG_ON(slot >= host->nr_slots);
 
+	/* Other subsystems can call in here before we're initialised. */
+	if (host->nr_slots == 0 || !host->slots[slot])
+		return;
+
 	schedule_work(&host->slots[slot]->cover_work);
 }
 
@@ -710,10 +837,10 @@
 	int sync_dev = 0;
 
 	data_addr = host->phys_base + OMAP_MMC_REG_DATA;
-	frame = 1 << data->blksz_bits;
+	frame = data->blksz;
 	count = sg_dma_len(sg);
 
-	if ((data->blocks == 1) && (count > (1 << data->blksz_bits)))
+	if ((data->blocks == 1) && (count > data->blksz))
 		count = frame;
 
 	host->dma_len = count;
@@ -901,7 +1028,7 @@
 	}
 
 
-	block_size = 1 << data->blksz_bits;
+	block_size = data->blksz;
 
 	OMAP_MMC_WRITE(host, NBLK, data->blocks - 1);
 	OMAP_MMC_WRITE(host, BLEN, block_size - 1);
@@ -983,22 +1110,22 @@
 	} else
 		host->mmc = mmc;
 	spin_unlock_irqrestore(&host->slot_lock, flags);
-	mmc_omap_select_slot(slot, 1);
+	mmc_omap_select_slot(slot, 1, 1);
 	mmc_omap_start_request(host, req);
 }
 
-static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on, int vdd)
+static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_mode, int vdd)
 {
 	struct mmc_omap_host *host;
 
 	host = slot->host;
 
 	if (slot->pdata->set_power != NULL)
-		slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on, vdd);
+		slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_mode, vdd);
 	if (cpu_is_omap24xx()) {
 		u16 w;
 
-		if (power_on) {
+		if (power_mode != MMC_POWER_OFF) {
 			w = OMAP_MMC_READ(host, CON);
 			OMAP_MMC_WRITE(host, CON, w | (1 << 11));
 		} else {
@@ -1008,12 +1135,31 @@
 	}
 }
 
+static void mmc_omap_set_standby(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct mmc_omap_slot *slot = mmc_priv(mmc);
+	struct mmc_omap_host *host = slot->host;
+	mmc_omap_select_slot(slot, 0, 0);
+	mmc_omap_set_power(slot, MMC_POWER_STANDBY, ios->vdd);
+	slot->vdd = ios->vdd;
+	slot->power_mode = MMC_POWER_STANDBY;
+	if (host->fclk_enabled == 1) {
+		host->fclk_enabled = 0;
+		clk_disable(host->fclk);
+	}
+	mmc_omap_release_slot(slot);
+}
+
 static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mmc_omap_slot *slot = mmc_priv(mmc);
 	struct mmc_omap_host *host = slot->host;
-	int dsor, power_on;
+	int dsor, power_on, slot_powered;
 	int i;
+	if (ios->power_mode == MMC_POWER_STANDBY) {
+		mmc_omap_set_standby(mmc, ios);
+		return;
+	}
 
 	if (ios->clock != 0) {
 		int freq, fclk_rate;
@@ -1043,11 +1189,21 @@
 	else
 		power_on = 0;
 
-	mmc_omap_select_slot(slot, 0);
-	if (slot->powered != power_on || ios->vdd != slot->vdd) {
-		mmc_omap_set_power(slot, power_on, ios->vdd);
-		slot->vdd = ios->vdd;
-		slot->powered = power_on;
+	mmc_omap_select_slot(slot, 0, 1);
+
+	slot_powered =
+		slot->power_mode == MMC_POWER_ON ||
+		slot->power_mode == MMC_POWER_UP;
+
+	if (slot_powered != power_on || ios->vdd != slot->vdd)
+		mmc_omap_set_power(slot, ios->power_mode, ios->vdd);
+
+	slot->vdd = ios->vdd;
+	slot->power_mode = ios->power_mode;
+
+	if (!power_on && host->fclk_enabled) {
+		host->fclk_enabled = 0;
+		clk_disable(host->fclk);
 	}
 
 	if (power_on)
@@ -1110,15 +1266,20 @@
 
 	host->slots[id] = slot;
 
+	mmc->caps = MMC_CAP_BYTEBLOCK | MMC_CAP_MULTIWRITE;
+	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
+	mmc->caps |= MMC_CAP_STANDBY;
 	if (host->pdata->wire4)
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
 
+	mmc->idle_delay = HZ/2;
+
 	mmc->ops = &mmc_omap_ops;
 	mmc->f_min = 400000;
-	if (cpu_class_is_omap2())
+//	if (cpu_class_is_omap2())
 		mmc->f_max = 48000000;
-	else
-		mmc->f_max = 24000000;
+//	else
+//		mmc->f_max = 24000000;
 	if (host->pdata->max_freq)
 		mmc->f_max = min(host->pdata->max_freq, mmc->f_max);
 	mmc->ocr_avail = slot->pdata->ocr_mask;
@@ -1129,8 +1290,10 @@
 	 */
 	mmc->max_phys_segs = 32;
 	mmc->max_hw_segs = 32;
-	mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */
-	mmc->max_seg_size = mmc->max_sectors * 512;
+	mmc->max_blk_size = 2048;	/* BLEN is 11 bits (+1) */
+	mmc->max_blk_count = 2048;	/* NBLK is 11 bits (+1) */
+	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+	mmc->max_seg_size = mmc->max_req_size;
 
 	r = mmc_add_host(mmc);
 	if (r < 0)
@@ -1205,6 +1368,11 @@
 		goto err_free_mem_region;
 	}
 
+	INIT_WORK(&host->cmd_abort, mmc_omap_abort_command, host);
+	init_timer(&host->cmd_timer);
+	host->cmd_timer.function = mmc_omap_cmd_timer;
+	host->cmd_timer.data = (unsigned long) host;
+
 	spin_lock_init(&host->dma_lock);
 	init_timer(&host->dma_timer);
 	spin_lock_init(&host->slot_lock);
@@ -1322,7 +1490,7 @@
 	int ret = 0, i;
 	struct mmc_omap_host *host = platform_get_drvdata(pdev);
 
-	if (host == NULL || (host != NULL && host->suspended))
+	if (host == NULL || host->suspended)
 		return 0;
 
 	for (i = 0; i < host->nr_slots; i++) {
@@ -1347,7 +1515,7 @@
 	int ret = 0, i;
 	struct mmc_omap_host *host = platform_get_drvdata(pdev);
 
-	if (host == NULL || (host != NULL && host->suspended))
+	if (host == NULL || !host->suspended)
 		return 0;
 
 	for (i = 0; i < host->nr_slots; i++) {
--- kernel-source-2.6.16-2.6.16.rel/arch/arm/mach-omap1/board-nokia770-mmc.c	2007-05-30 21:38:59.000000000 +0200
+++ kernel-source-2.6.16-2.6.16.my/arch/arm/mach-omap1/board-nokia770-mmc.c	2007-12-07 21:13:26.000000000 +0100
@@ -138,7 +138,7 @@
 	.enabled		= 1,
 	.nr_slots		= 1,
 	.wire4			= 0,
-	.max_freq		= 12000000,
+	.max_freq		= 48000000,
 	.init			= nokia770_mmc_late_init,
 	.cleanup		= nokia770_mmc_cleanup,
 	.slots[0] = {
