diff options
Diffstat (limited to 'drivers/mmc/mmc_block.c')
-rw-r--r-- | drivers/mmc/mmc_block.c | 130 |
1 files changed, 47 insertions, 83 deletions
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 587458b370b..db0e8ad439a 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c | |||
@@ -27,11 +27,12 @@ | |||
27 | #include <linux/hdreg.h> | 27 | #include <linux/hdreg.h> |
28 | #include <linux/kdev_t.h> | 28 | #include <linux/kdev_t.h> |
29 | #include <linux/blkdev.h> | 29 | #include <linux/blkdev.h> |
30 | #include <linux/devfs_fs_kernel.h> | ||
31 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
32 | 31 | ||
33 | #include <linux/mmc/card.h> | 32 | #include <linux/mmc/card.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,35 +174,39 @@ 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.timeout_ns = card->csd.tacc_ns * 10; | ||
176 | brq.data.timeout_clks = card->csd.tacc_clks * 10; | ||
177 | brq.data.blksz_bits = md->block_bits; | ||
178 | brq.data.blksz = 1 << md->block_bits; | 177 | brq.data.blksz = 1 << md->block_bits; |
179 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); | 178 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); |
180 | brq.stop.opcode = MMC_STOP_TRANSMISSION; | 179 | brq.stop.opcode = MMC_STOP_TRANSMISSION; |
181 | brq.stop.arg = 0; | 180 | brq.stop.arg = 0; |
182 | brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; | 181 | brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; |
183 | 182 | ||
184 | if (rq_data_dir(req) == READ) { | 183 | mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ); |
185 | brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; | ||
186 | brq.data.flags |= MMC_DATA_READ; | ||
187 | } else { | ||
188 | brq.cmd.opcode = MMC_WRITE_BLOCK; | ||
189 | brq.data.flags |= MMC_DATA_WRITE; | ||
190 | brq.data.blocks = 1; | ||
191 | 184 | ||
192 | /* | 185 | /* |
193 | * Scale up the timeout by the r2w factor | 186 | * If the host doesn't support multiple block writes, force |
194 | */ | 187 | * block writes to single block. |
195 | brq.data.timeout_ns <<= card->csd.r2w_factor; | 188 | */ |
196 | brq.data.timeout_clks <<= card->csd.r2w_factor; | 189 | if (rq_data_dir(req) != READ && |
197 | } | 190 | !(card->host->caps & MMC_CAP_MULTIWRITE)) |
191 | brq.data.blocks = 1; | ||
198 | 192 | ||
199 | if (brq.data.blocks > 1) { | 193 | if (brq.data.blocks > 1) { |
200 | brq.data.flags |= MMC_DATA_MULTI; | 194 | brq.data.flags |= MMC_DATA_MULTI; |
201 | brq.mrq.stop = &brq.stop; | 195 | brq.mrq.stop = &brq.stop; |
196 | readcmd = MMC_READ_MULTIPLE_BLOCK; | ||
197 | writecmd = MMC_WRITE_MULTIPLE_BLOCK; | ||
202 | } else { | 198 | } else { |
203 | 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; | ||
204 | } | 210 | } |
205 | 211 | ||
206 | brq.data.sg = mq->sg; | 212 | brq.data.sg = mq->sg; |
@@ -225,27 +231,29 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
225 | goto cmd_err; | 231 | goto cmd_err; |
226 | } | 232 | } |
227 | 233 | ||
228 | do { | 234 | if (rq_data_dir(req) != READ) { |
229 | int err; | 235 | do { |
230 | 236 | int err; | |
231 | cmd.opcode = MMC_SEND_STATUS; | 237 | |
232 | cmd.arg = card->rca << 16; | 238 | cmd.opcode = MMC_SEND_STATUS; |
233 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | 239 | cmd.arg = card->rca << 16; |
234 | err = mmc_wait_for_cmd(card->host, &cmd, 5); | 240 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; |
235 | if (err) { | 241 | err = mmc_wait_for_cmd(card->host, &cmd, 5); |
236 | printk(KERN_ERR "%s: error %d requesting status\n", | 242 | if (err) { |
237 | req->rq_disk->disk_name, err); | 243 | printk(KERN_ERR "%s: error %d requesting status\n", |
238 | goto cmd_err; | 244 | req->rq_disk->disk_name, err); |
239 | } | 245 | goto cmd_err; |
240 | } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); | 246 | } |
247 | } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); | ||
241 | 248 | ||
242 | #if 0 | 249 | #if 0 |
243 | if (cmd.resp[0] & ~0x00000900) | 250 | if (cmd.resp[0] & ~0x00000900) |
244 | printk(KERN_ERR "%s: status = %08x\n", | 251 | printk(KERN_ERR "%s: status = %08x\n", |
245 | req->rq_disk->disk_name, cmd.resp[0]); | 252 | req->rq_disk->disk_name, cmd.resp[0]); |
246 | if (mmc_decode_status(cmd.resp)) | 253 | if (mmc_decode_status(cmd.resp)) |
247 | goto cmd_err; | 254 | goto cmd_err; |
248 | #endif | 255 | #endif |
256 | } | ||
249 | 257 | ||
250 | /* | 258 | /* |
251 | * A block was successfully transferred. | 259 | * A block was successfully transferred. |
@@ -325,52 +333,11 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
325 | md->read_only = mmc_blk_readonly(card); | 333 | md->read_only = mmc_blk_readonly(card); |
326 | 334 | ||
327 | /* | 335 | /* |
328 | * Figure out a workable block size. MMC cards have: | 336 | * Both SD and MMC specifications state (although a bit |
329 | * - two block sizes, one for read and one for write. | 337 | * unclearly in the MMC case) that a block size of 512 |
330 | * - may support partial reads and/or writes | 338 | * bytes must always be supported by the card. |
331 | * (allows block sizes smaller than specified) | ||
332 | */ | ||
333 | md->block_bits = card->csd.read_blkbits; | ||
334 | if (card->csd.write_blkbits != card->csd.read_blkbits) { | ||
335 | if (card->csd.write_blkbits < card->csd.read_blkbits && | ||
336 | card->csd.read_partial) { | ||
337 | /* | ||
338 | * write block size is smaller than read block | ||
339 | * size, but we support partial reads, so choose | ||
340 | * the smaller write block size. | ||
341 | */ | ||
342 | md->block_bits = card->csd.write_blkbits; | ||
343 | } else if (card->csd.write_blkbits > card->csd.read_blkbits && | ||
344 | card->csd.write_partial) { | ||
345 | /* | ||
346 | * read block size is smaller than write block | ||
347 | * size, but we support partial writes. Use read | ||
348 | * block size. | ||
349 | */ | ||
350 | } else { | ||
351 | /* | ||
352 | * We don't support this configuration for writes. | ||
353 | */ | ||
354 | printk(KERN_ERR "%s: unable to select block size for " | ||
355 | "writing (rb%u wb%u rp%u wp%u)\n", | ||
356 | mmc_card_id(card), | ||
357 | 1 << card->csd.read_blkbits, | ||
358 | 1 << card->csd.write_blkbits, | ||
359 | card->csd.read_partial, | ||
360 | card->csd.write_partial); | ||
361 | md->read_only = 1; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * Refuse to allow block sizes smaller than 512 bytes. | ||
367 | */ | 339 | */ |
368 | if (md->block_bits < 9) { | 340 | md->block_bits = 9; |
369 | printk(KERN_ERR "%s: unable to support block size %u\n", | ||
370 | mmc_card_id(card), 1 << md->block_bits); | ||
371 | ret = -EINVAL; | ||
372 | goto err_kfree; | ||
373 | } | ||
374 | 341 | ||
375 | md->disk = alloc_disk(1 << MMC_SHIFT); | 342 | md->disk = alloc_disk(1 << MMC_SHIFT); |
376 | if (md->disk == NULL) { | 343 | if (md->disk == NULL) { |
@@ -409,7 +376,6 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
409 | */ | 376 | */ |
410 | 377 | ||
411 | sprintf(md->disk->disk_name, "mmcblk%d", devidx); | 378 | sprintf(md->disk->disk_name, "mmcblk%d", devidx); |
412 | sprintf(md->disk->devfs_name, "mmc/blk%d", devidx); | ||
413 | 379 | ||
414 | blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits); | 380 | blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits); |
415 | 381 | ||
@@ -555,7 +521,6 @@ static int __init mmc_blk_init(void) | |||
555 | if (major == 0) | 521 | if (major == 0) |
556 | major = res; | 522 | major = res; |
557 | 523 | ||
558 | devfs_mk_dir("mmc"); | ||
559 | return mmc_register_driver(&mmc_driver); | 524 | return mmc_register_driver(&mmc_driver); |
560 | 525 | ||
561 | out: | 526 | out: |
@@ -565,7 +530,6 @@ static int __init mmc_blk_init(void) | |||
565 | static void __exit mmc_blk_exit(void) | 530 | static void __exit mmc_blk_exit(void) |
566 | { | 531 | { |
567 | mmc_unregister_driver(&mmc_driver); | 532 | mmc_unregister_driver(&mmc_driver); |
568 | devfs_remove("mmc"); | ||
569 | unregister_blkdev(major, "mmc"); | 533 | unregister_blkdev(major, "mmc"); |
570 | } | 534 | } |
571 | 535 | ||