aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/mmc_block.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/mmc_block.c')
-rw-r--r--drivers/mmc/mmc_block.c66
1 files changed, 40 insertions, 26 deletions
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index a0e0dad1b419..db0e8ad439a5 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -32,6 +32,7 @@
32#include <linux/mmc/card.h> 32#include <linux/mmc/card.h>
33#include <linux/mmc/host.h> 33#include <linux/mmc/host.h>
34#include <linux/mmc/protocol.h> 34#include <linux/mmc/protocol.h>
35#include <linux/mmc/host.h>
35 36
36#include <asm/system.h> 37#include <asm/system.h>
37#include <asm/uaccess.h> 38#include <asm/uaccess.h>
@@ -165,6 +166,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
165 do { 166 do {
166 struct mmc_blk_request brq; 167 struct mmc_blk_request brq;
167 struct mmc_command cmd; 168 struct mmc_command cmd;
169 u32 readcmd, writecmd;
168 170
169 memset(&brq, 0, sizeof(struct mmc_blk_request)); 171 memset(&brq, 0, sizeof(struct mmc_blk_request));
170 brq.mrq.cmd = &brq.cmd; 172 brq.mrq.cmd = &brq.cmd;
@@ -172,7 +174,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
172 174
173 brq.cmd.arg = req->sector << 9; 175 brq.cmd.arg = req->sector << 9;
174 brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 176 brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
175 brq.data.blksz_bits = md->block_bits;
176 brq.data.blksz = 1 << md->block_bits; 177 brq.data.blksz = 1 << md->block_bits;
177 brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); 178 brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
178 brq.stop.opcode = MMC_STOP_TRANSMISSION; 179 brq.stop.opcode = MMC_STOP_TRANSMISSION;
@@ -181,20 +182,31 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
181 182
182 mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ); 183 mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
183 184
184 if (rq_data_dir(req) == READ) { 185 /*
185 brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; 186 * If the host doesn't support multiple block writes, force
186 brq.data.flags |= MMC_DATA_READ; 187 * block writes to single block.
187 } else { 188 */
188 brq.cmd.opcode = MMC_WRITE_BLOCK; 189 if (rq_data_dir(req) != READ &&
189 brq.data.flags |= MMC_DATA_WRITE; 190 !(card->host->caps & MMC_CAP_MULTIWRITE))
190 brq.data.blocks = 1; 191 brq.data.blocks = 1;
191 }
192 192
193 if (brq.data.blocks > 1) { 193 if (brq.data.blocks > 1) {
194 brq.data.flags |= MMC_DATA_MULTI; 194 brq.data.flags |= MMC_DATA_MULTI;
195 brq.mrq.stop = &brq.stop; 195 brq.mrq.stop = &brq.stop;
196 readcmd = MMC_READ_MULTIPLE_BLOCK;
197 writecmd = MMC_WRITE_MULTIPLE_BLOCK;
196 } else { 198 } else {
197 brq.mrq.stop = NULL; 199 brq.mrq.stop = NULL;
200 readcmd = MMC_READ_SINGLE_BLOCK;
201 writecmd = MMC_WRITE_BLOCK;
202 }
203
204 if (rq_data_dir(req) == READ) {
205 brq.cmd.opcode = readcmd;
206 brq.data.flags |= MMC_DATA_READ;
207 } else {
208 brq.cmd.opcode = writecmd;
209 brq.data.flags |= MMC_DATA_WRITE;
198 } 210 }
199 211
200 brq.data.sg = mq->sg; 212 brq.data.sg = mq->sg;
@@ -219,27 +231,29 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
219 goto cmd_err; 231 goto cmd_err;
220 } 232 }
221 233
222 do { 234 if (rq_data_dir(req) != READ) {
223 int err; 235 do {
224 236 int err;
225 cmd.opcode = MMC_SEND_STATUS; 237
226 cmd.arg = card->rca << 16; 238 cmd.opcode = MMC_SEND_STATUS;
227 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 239 cmd.arg = card->rca << 16;
228 err = mmc_wait_for_cmd(card->host, &cmd, 5); 240 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
229 if (err) { 241 err = mmc_wait_for_cmd(card->host, &cmd, 5);
230 printk(KERN_ERR "%s: error %d requesting status\n", 242 if (err) {
231 req->rq_disk->disk_name, err); 243 printk(KERN_ERR "%s: error %d requesting status\n",
232 goto cmd_err; 244 req->rq_disk->disk_name, err);
233 } 245 goto cmd_err;
234 } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); 246 }
247 } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
235 248
236#if 0 249#if 0
237 if (cmd.resp[0] & ~0x00000900) 250 if (cmd.resp[0] & ~0x00000900)
238 printk(KERN_ERR "%s: status = %08x\n", 251 printk(KERN_ERR "%s: status = %08x\n",
239 req->rq_disk->disk_name, cmd.resp[0]); 252 req->rq_disk->disk_name, cmd.resp[0]);
240 if (mmc_decode_status(cmd.resp)) 253 if (mmc_decode_status(cmd.resp))
241 goto cmd_err; 254 goto cmd_err;
242#endif 255#endif
256 }
243 257
244 /* 258 /*
245 * A block was successfully transferred. 259 * A block was successfully transferred.