diff options
Diffstat (limited to 'drivers/mmc/mmc_block.c')
| -rw-r--r-- | drivers/mmc/mmc_block.c | 66 |
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. |
